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.

2011-06-23

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

For a background in the subject please see part 1.


To handle Cors requests we can take advantage of the extensibility mechanism that is embedded in WCF. There are many extension points that we can use and the cors problem can be issued in more than one way.
There is a great article, written by Aaron Skonnard, published in the Dec 2007 issue of MSDN magazine, that covers many parts of this mechanism that I can recommend for further reading.

Our main problem is that we need to analyse the incoming request and determine if it is a cors preflight request, cors normal request or a normal request. Preflight request should not reach the service method at all since we don't want to invoke the service method. The other requests should invoke the method but for all cors responses we should add extra headers.

I found a reply by Carlos Figueira in a msdn thread that solves the "analyse message and skip invoking the service method"-part that I used as a start. (as a side note Richard Blewett stated (in the same thread) that we could intercept the message before it reaches the dispatcher by writing a protocol channel. I will leave that excercise to the reader or for another day.)



So to analyse the incoming message we use the first avaliable extension point in the dispatcher (server) that would be the Message inspection stage.
To use this extension point we implement an IDispatchMessageInspector. In this stage we are at the service endpoint and haven't decided wich method of the service that we should call. What we do here is that we look for a cors request (checking if the Origin header is present). If so we create a Cors state object and adds a property to the message so we can use this later on in other extension points.
If it is a preflight request we also create a response message that we should use.
When the message inspector receives the reply we add the headers (and if it was a preflight request, we replace the whole response.

In part 3 we will continue to the operation level where we check the property and omits the call to the service method in case of a preflight request.

View code on github https://github.com/dhvik/Wcf-cors-behavior/blob/master/CorsDispatchMessageInspector.cs

In part 3 we will see how we handle things on the operation level.

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

If you use try to consume a rest service using JavaScript (jquery) and are using chrome or Firefox (newer versions) you might run into cross domain issues that involves the w3c standard for accessing resources on other domains (or ports).

In short, if you try to request a resource on a page using javascript(call a rest service) that is located on another domain/port then the XMLHttpRequest object that is implemented in the browser will first try to discover if the cross-origin resource is prepared/allows to accept requests from the origin. If this preflight request succeeds then the real request will be fired.
All this is handled by the browsers XMLHttpRequest object so from the JavaScript side this don't affect the code.

The server side code must support cors though.

An example: we take a simple service method that only returns a string.

public string Hello() {
return "Hello!";
}

If we want to allow cors requests, then we must detect the preflight request and reply accordingly and if it is the real request we should perform the actual method.

public string Hello(){
//for all cors requests
WebOperationContext.Current.OutgoingResponse.Headers
.Add("Access-Control-Allow-Origin","*");
//identify preflight request and add extra headers
if (WebOperationContext.Current.IncomingRequest.Method == "OPTIONS") {
WebOperationContext.Current.OutgoingResponse.Headers
.Add("Access-Control-Allow-Methods", "POST, OPTIONS, GET");
WebOperationContext.Current.OutgoingResponse.Headers
.Add("Access-Control-Allow-Headers",
"Content-Type, Accept, Authorization, x-requested-with");
return null;
}
return "Hello!";
}

Basically we first add the Access-Control-Allow-Origin header telling that we allow any origins (we can also specify an origin that matches the origin that the request comes from). Then we check if the request is a preflight request (method is OPTIONS). If it is we add extra headers to declare which methods and headers that we allow the real request to contain. There are a few more access-control headers that we can add if we need and these are described in the w3c spec.

To add this code in every method is not a great solution but in part 2 we will see how we can use WCF extensibility to do this in a more elegant way.

2011-01-02

Alpha version of IOU tracker

Have been experimenting with .net4, MVC2 and EntityFramework. The result is a IOU tracker that is available at iou.nu.
Service is free of charge and feel free to try it out.

I know there are several other iou trackers out there, but since the most lack some features and I needed to dig deeper into net4/mvc2/EF anyway so why not give it a try!?

/Dan