2014-02-20

Duplicate config sections in web.config and internal server errors...

There is a duplicate 'myApp' section defined, Internal Server Error

Had a breakdown moment today when two sites didn't behave. Each site had a virtual application with its own web.config.
Both sites where configured almost the same but one of the virtual applications worked and not the other.
The following error was displayed.

HTTP Error 500.19 - Internal Server Error

The requested page cannot be accessed because the related configuration data for the page is invalid.

Detailed Error Information:

Module           IIS Web Core
Notification     BeginRequest
Handler          Not yet determined
Error Code       0x800700b7
Config Error     There is a duplicate 'myapp' section defined
Config File      \\?\c:\MyApp\vapp\web.config
Requested URL    http://myapp:80/vapp/
Physical Path    c:\MyApp\
Logon Method     Not yet determined
Logon User       Not yet determined

Config Source:
    7:   <configsections>
    8:     <section name="myApp" type="MyApp.MyConfigSection, MyApp"/>
    9:   </configsections>

This configuration section was present in my site as well, like below.

<section name="myApp" type="MyApp.MyConfigSection,MyApp"/>

Removing the section from the vapp did the trick, but why did it work on the other site?

Finally after some testing and borrowing a second pair of eyes (thx robert), a small difference in the setup was detected. One of the sections where declared with the type "MyApp.MyConfigSection, MyApp" and the other with "MyApp.MyConfigSection,MyApp". Did you see it?! A small whitespace between the type and assembly names where missing.
After adjusting the typo to either keeping the whitespace or removing it on both, it started to work...

2013-10-14

Kernel mode caching and HttpHandlers

Ever tried to get a IHttpHandler delivered data to use the IIS (7) kernel mode cache?
Ever tried to get fancy and make the handler auto configured (ie managing it programmatically)?
Well, I tried a lot but gave up.

Basic setup to use IHttpHandler and kernel mode cache

1. To get a IHttpHandler deliver data (like images) and make it use the IIS kernel-mode cache, there are a few points that you must not miss. (http://support.microsoft.com/kb/817445)
2. You need to register the handler in the system.webServer/handlers section (http://msdn.microsoft.com/en-us/library/46c5ddfy(v=vs.100).aspx)
3. If you run a routed site (like a MVC site) you must Ignore the route of the handler (else it will not be added to the kernel cache).

Trying to get fancy and using any method below to minimize configuration (avoid step 2 above).
a. Adding the IHttpHandler using a IRouteHandler (http://www.mikesdotnetting.com/Article/126/ASP.NET-MVC-Prevent-Image-Leeching-with-a-Custom-RouteHandler)
b. Changing handler after the handler has been calculated (http://stackoverflow.com/questions/1888016/any-way-to-add-httphandler-programatically-in-net)
c. Using a IHttpHandlerFactory (same registration as point 2 but if you have several handlers you can configure one factory and redirect to each handler)
d. Modifying system.webServer/handlers programmatically doesn't even work. No API, no hacks, no nothing?! Didn't even find a way to read which handlers were registered in web.config without parsing it manually and backtracking inherited configuration files...

None of the fancy methods works (1-3 works but not with kernel cache). Problem is that kernel cache is disabled IF the handler is changed along the way. (http://blogs.msdn.com/b/tmarq/archive/2010/04/01/asp-net-4-0-enables-routing-of-extensionless-urls-without-impacting-static-requests.aspx)

So I'm back with a standard IHttpHandler, manually registering it in web.config and ignoring routes...

2013-06-11

Using a custom format in ImageVault to specify compression quality in jpg images

If you want to request an converted image in ImageVault and also specify the compression quality for a jpeg image you cannot use the LINQ syntax in the C# API of ImageVault. The LINQ engine only wraps some functions in the API and compression quality is not yet added to the mix.
To do this we need to use another approach and access the service methods directly (like the LINQ parser does internally).

First we need a client.

var client = ClientFactory.GetSdkClient();
Then we need to create a format that has the correct parameters.
//Compression quality can be set on ImageFormats where 100 is maximum quality
var format = new ImageFormat {
  CompressionQuality = 80,
  MediaFormatOutputType = MediaFormatOutputTypes.Jpeg;
};
format.Effects.Add(new ResizeEffect(200, 200));
Here we created an ImageFormat and specifies the Compression quality to 80 and specify that we want to have a jpeg output image. We can then add other effects to it, like in this case, a Resize effect.

Next step is to create a query that will be used to find the media we are looking for.
var q = new MediaItemQuery {
  //we filter out the items we want to retrieve (in this case media with id 485)
  Filter = { Id = new List<int> { 485 } },
  //and supply the format that we want to populate
  Populate = {
    MediaFormats = { format },
    PublishIdentifier = client.PublishIdentifier
  }
};
This query will filter out image with id 485 and populate the found MediaItem with the requested formats (in this case the one that we defined above).
Note that we have not created the format, this will be done automatically (or if a matching format is found, it will be reused). These format are called system formats and is not visible in the UI.
We also specify a publish identifier that will generate the urls to the converted media as public urls (no authentication).

This query is then passed to the service method.
//first create the media service channel
var mediaService = client.CreateChannel<IMediaService>();
//we then pass the query object to the find method
var mediaItem = mediaService.Find(q).Single();
//and since we only requested one Format, the converted image url will reside 
//in the first MediaConversion of the item.
var url = mediaItem.MediaConversions[0].Url;
When all is done we have the url to the converted (and published) jpeg image.
Note: the client.PublishIdentifier will be set if you are in an EPiServer site or if you configure it in the imagevault.client.config. You can also set this manually.

2013-05-16

Using the REST API of ImageVault

In ImageVault 4 we introduced a REST API for the ImageVault Core service. This will show a small example on how to use that.

Javascript

This example uses javascript and the javascript classes that are included in the ImageVault installation (in the UI). I will use the scripts that are located on the beta installation but you can use the ones that are on your installation as well.
We need three scripts, jquery, json2 and ImageVault.Client. ImageVault.Client handles authentication and CORS logic for the app.

<script type="text/javascript" src="https://imagevault.se/beta/ImageVault/Scripts/lib/jquery-1.6.1.js" ></script>
<script type="text/javascript" src="https://imagevault.se/beta/ImageVault/Scripts/lib/json2.js"></script>
<script type="text/javascript" src="https://imagevault.se/beta/ImageVault/Scripts/ImageVault.Client.js"></script>

Client

To connect to core we need the javascript client.
var core = new ImageVault.Client({
 authUrl: "https://imagevault.se/beta/ImageVaultIdp/http.issue",
 realm: "https://imagevault.se:1234",
 username: "demouser",
 password: "P@55w0rd!"
});
The core client is created using the following parameters
authUrl
This is the url to the Idp endpoint that can issue a ticket to be used with the core calls. Authentication uses federated authentication
realm
This is the url to core and also instructs the Idp on who the recipient of the ticket is.
username/password
the username and password of the user.

Authentication

We use federated authentication and to be able to call the services you need to have an authentication ticket. To get the ticket you need to authenticate vs the IdentityProvider (Idp). This is handled by the ImageVault.Client script. Also reissuing of tickets when they exipire are handled by the client script.

API calls to Core

To call the REST API we use the json method of the client that performs an authenticated call to the core.

core.json("MediaService/Find", {
  Filter: { SearchString: searchString },
  Populate: {
    MediaFormats: [
      //Thumbnail format
      {  
        $type: "ImageVault.Common.Data.ThumbnailFormat,ImageVault.Common", 
        Effects:[
          {$type:"ImageVault.Common.Data.Effects.ResizeEffect, ImageVault.Common",Width:200,Height:200,ResizeMode:'ScaleToFill'}
        ]
      }
    ]
  }    
}, function (d) {
  alert(JSON.stringify(d));
});
The json call uses the following parameters
path
The service/method to call. Name of the service is the same as the interface (omit the leading I)
arguments
the arguments to the service method as a javascript object. If the method takes multiple arguments, wrap them in a single object (.e {arg1:'test',arg2:'test2'} )
success callback
The function to call when the service call is done. The argument to the function is the return value of the service method.
The services are documented at the ImageVault API reference documentation. The full ImageVault developer documentation can be found at http://imagevault.se/doc

You can test a fully fledged demo below that uses the ImageVault demo site scripts and content that performs a search and displays the thumbnail media

Demo


2013-02-26

Keeping configuration transforms after applying EPiServer 7 Patch

When installing the patch 1 for EPiServer CMS 7 the installation instructions stated that you needed to turn of the msbuild build tasks that created the configuration files from different xml fragments using xml transform.
The patch also noted that you needed to manually replace the assembly redirect assembly versions directly in the web.config file.

Since I have grown quite fond of using the xml fragments to apply configuration changes for our entire development team I found a way to apply the patch changes by a simple xml transform.
Just edit the [Configuration]/Common/Web.Common.config and add the redirects that you need to fix.

<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform" xmlns:asm="urn:schemas-microsoft-com:asm.v1">
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly xdt:Transform="Replace" xdt:Locator="Condition(asm:assemblyIdentity/@name='EPiServer.Framework')">
        <assemblyIdentity name="EPiServer.Framework" publicKeyToken="8fe83dea738b45b7" culture="neutral" />
        <bindingRedirect oldVersion="1.0.0.0-7.0.859.4" newVersion="7.0.859.4" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

The key here is that we replace the original assembly redirect with the new binding (with the new version number) and use a Locator attribute to find the correct node in the original web.config file to replace.

The tricky part in this case is that the assemblyBinding changes the default namespace. To get a correct xpath we need to use this namespace to locate the child node. To use a namespace in an xpath expression we first need to register it with a prefix (here using asm) in the root node (or somewhere in scope). We can then build a correct xpath expression (asm:assemblyIdentity/@name) to locate the node.

I will follow up with a final post stating all adjustments needed to get this to work.

Update/follow up
I completed the adjustments for both the Framework and CMS packages and collected the needed transforms in the following file.
https://dl.dropbox.com/u/10119568/EPiServerCms7Patch1/web.common.config
The installation instructions also stated that other assemblies could be present (in my case there wasn't) but if that's so in your case, just add those transformations to the list.)

Note: I needed to remove the old dll:s from the [Libraries] folder in the Alloy template or my VisualStudio didn't get the hint path correctly.

2011-06-24

Supporting Cross Origin Resource Sharing (CORS) requests in a WCF Rest service - Part 4

For background information, see part 1
For message inspection code, see part 2
For operation dispatcher code, see part 3

To include the message inspection in our wcf service for our service we need to bind it to our service. This is done using behaviors. To bind the IDispatchMessageInspector that works on the ServiceEndpoint level we need to implement an IEndpointBehavior and assign it to our endpoint.

To bind the IOperationInvoker and IDispatchMessageFormatter we need to implement the IOperationBehavior that works on the operation level.

This class also works as an attribute so you can decorate your contract and operations with it if need be. It also contains some properties if you want to control the header values.

https://github.com/dhvik/Wcf-cors-behavior/blob/master/CorsBehaviorAttribute.cs

Assigning can be done in many ways. By declarations on the contract (attribute), configuration in the applications configuration file or direct using code. I'm using code since I host the services in a windows service.
var host = new WebServiceHost2(serviceType, false,
new Uri(serviceBaseUrl + serviceName));
var endpoint = host.AddServiceEndpoint(contractType,
new WebHttpBinding(WebHttpSecurityMode.None), "");
//add support for cors (both for the endpoint to detect and create reply)
endpoint.Behaviors.Add(new CorsBehaviorAttribute());

foreach (var operation in endpoint.Contract.Operations) {
//add support for cors (and for operation to be able to not
//invoke the operation if we have a preflight cors request)
operation.Behaviors.Add(new CorsBehaviorAttribute());
}
When we now have all pieces in place we don't need to bother about cross domain requests. Our endpoint and operation behaviors handles this and we don't need to litter our service code with things that don't belong there anyway.

Supporting Cross Origin Resource Sharing (CORS) requests in a WCF Rest service - Part 3

For background information, see part 1
For message inspection code, see part 2

When a cors request is identified we now have the CorsState object available on our operation level and can act upon this. To be able to skip calling the service method in case of a preflight request we need to implement two extension points in the operation level. Message formatting and operation invocation. Since the preflight request won't have the correct requests message format, we skip the deserializing process and the message using the normal deserializator can results in errors. So in that case we skip both serialization and deserialization.

https://github.com/dhvik/Wcf-cors-behavior/blob/master/CorsFormatter.cs

When it comes to the IOperationInvoker we just skip invoking the operation if we have a preflight request. All other requests uses the original invoker.

https://github.com/dhvik/Wcf-cors-behavior/blob/master/CorsInvoker.cs


In the part 4 we will see how we bind all these extension points together for our service.