Posts Tagged ‘WCF’

Basic authentication of a .NET REST service

Tuesday, July 28th, 2009

One of the issues one can encounter when building a REST service with the .NET Framework 3.5 SP1 is the fact that when basic authentication is enabled, it defaults to authentication against Windows accounts in IIS. It’s not possible to specify your own handler/provider to authenticate against for instance a proprietary user database, nor is it possible to secure only a certain operation/service and leave the others unsecured.

Luckily there’s a open source project hosted on CodePlex called WCF REST Contrib which, besides adding a whole lot of other improvements, solves the aforementioned issues. The project provides a sample solution showcasing all the features, which might seem a bit overwhelming since it includes quite some configuration. I have attached a sample project with only the bare minimum configuration (using attributes) to enable per operation authentication.

Browse to CancerService.svc/request/skincancer to test the authentication, the browser should display a prompt asking for a username and password. The username is “tony” and password “clifton”. Don’t mind the rather questionable service and operation name, I had no inspiration at the time.

The original documentation failed to mention that the per operation/service authentication depended on the WebErrorHandler, which has been corrected.

Attachment: Authentication Tryout

Caching using WCF REST Starter Kit in Medium Trust

Sunday, April 26th, 2009

Caching is one of the features provided by the WCF REST Starter Kit released by Microsoft at CodePlex. Jesus Rodriguez has written a walkthrough on how to get it running. The kit was designed to run under Medium Trust, but if you want to use caching in this trust level, you’ll have to configure it a bit differently.

System.Security.SecurityException: Request for the permission of type ‘System.Configuration.ConfigurationPermission, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a’ failed.

Using Jesus’ approach you’ll be greated by a nice Security Exception, for some reason you can’t configure the caching in the Web.Config in Medium Trust. Luckily you can add all the caching configuration as attributes to your method. You’ll have to remove the <caching> block from the Web.Config, but leave the aspNetCompatibilityEnabled tag enabled! Here’s an example:

Instead of using this XML configuration:

<caching>
   <outputCacheSettings>
      <outputCacheProfiles>
         <clear/>
         <add name="SampleProfile" duration="30" enabled="true" location="Any" />
      </outputCacheProfiles>
   </outputCacheSettings>
</caching>

We add these attributes, unfortunately you’ll have to add these attributes to every method you’d like to cache. There are more attributes available, you can see them using the IntelliSense, but this configuration mimics the XML config.

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class SampleService : ISampleService
{
   [WebGet(UriTemplate= "/results")]
   [WebCache(Duration=30, Location=OutputCacheLocation.Any)]
   public Atom10FeedFormatter GetData()
   {
      ...
   }
}

Note: Tested in the ASP.NET Development Server provided by Visual Studio 2008 SP1. The OutputCacheLocation enum is located in the System.Web.UI namespace.

Reduce the XML WCF response size

Monday, March 23rd, 2009

I recently received a request for a post on how to reduce the XML response size of a WCF service easily. When developing for mobile devices (like the iPhone), it’s crucial to keep loading times as small as possible. Reducing the size of the XML response can be done in two ways: either the actual data or the encapsulating XML elements is/are treated. Changing the actual data probably has a severe impact on you’re applications inner workings, that’s why we’ll focus on the latter. Here’s how:

[DataContract(Name = "p")]
public class Product
{
   [DataMember(Name = "n")]
   public string Name { get; set; }
 
   [DataMember(Name = "a")]
   public int Amount { get; set; }
}

By adding the name attribute we can specify how the XML element will be called, by default it uses the name of the class or property. The original response is 64 characters long, while the tweaked is only 35 characters, a reduction in size of more than 40%. This also works when the response is or contains a list or products.

// Original response
<Product>
   <Name>MacBook</Name>
   <Amount>123</Amount>
</Product>
 
// Response after tweaking
<p>
   <n>MacBook</n>
   <a>123</a>
<p>

In the end it’s a trade-off between overall readability and performance, if you’re consuming the service in .NET with WCF, then you won’t even know that the response has been tampered with, since it’s all done in the background. If you’re calling the WCF service from for instance Objective-C and are parsing the result, you’ll have to adjust the parsing to use the new XML element names.

In the case of an application for a mobile device, the benefits (faster loading) outweigh the disadvantages. You even get an added bonus: less bandwidth consumption on the server.

Removing svc extension of WCF REST service

Sunday, March 1st, 2009

What if we had a REST service implemented with WCF to retrieve some info about a user. The method would be called with the following url: “http://domain/service.svc/user/john”. Although this works perfectly and conforms to the REST guidelines, for some the svc extension is a thorn in the eye. Turns out it’s very easy to strip the svc extension with a HTTPModule. The module adds an eventhandler for the BeginRequest event of the application, each time a request is received the module checks if it is a call without the svc extension. If this is the case, it reroutes the request to service.svc with the specified parameters. To the outside world it will appear as if “http://domain/service/user/john” is called, while this resource actually does not exist.

public void Init(HttpApplication context)
{
   context.BeginRequest += delegate
   {
      HttpContext ctx = HttpContext.Current;
      string path = ctx.Request.AppRelativeCurrentExecutionFilePath.ToLower();
 
      if (path.Contains("/service/"))
      {
         int i = path.IndexOf('/', 2);
         if (i &gt; 0)
         {
            string service = path.Substring(0, i) + ".svc";
            string parameters = path.Substring(i, path.Length - i);
            ctx.RewritePath(service, parameters, string.Empty, false);
         }
      }
   };
}

In our case service would equals “~/service.svc” and the paramaters variable would equal “/user/john”.

Hooking the HTTPModule into the web.config is done in the system.web/httpmodules element. In this case the module class is called ServiceRedirector.

<system.web>
   <httpModules>  
      <add name="ServiceRedirector" type="ServiceRedirector"/>
   </httpModules>
</system.web>

The HTTPModule above could be extended to support multiple services, but I leave that as an exercise for the reader.