Creating a RESTful Web Service Using ASP.Net MVC Part 24 – MVC 3 and More

February 7, 2011 22:23 by admin

Recently MVC 3 was released which is a good reason for me to update our RESTful web service framework. This latest version is compiled against ASP.Net MVC 3 and .Net 4. I have also taken the opportunity to introduce some new features that have either been requested or come out of actual implementations.

License

The first thing I’ve changed is nothing to do with the code. I’ve changed the license to the most permissive I could find, the MIT License. Basically, use my code for what ever you want, but don’t blame me!

Allowed Verbs

The previous version of the web service defined an interface that a controller could implement to indicate it could support providing information for the Allow Header. This defined a property AllowedVerbs that would be used to retrieve the contents to be put into the Allow Header. This has been replaced with a method:

string GetAllowedVerbs(ActionExecutedContext actionExecutedContext);

This allows an ActionExecutedContext to be passed in, which contains some interesting information that can be used to determine what verbs to add to the list. For example, in this simple snippet, the code checks which Action was actually performed:

public string GetAllowedVerbs(ActionExecutedContext actionExecutedContext)
{
    string verbs = "GET";

    // Extra verbs are allowed depending on whether an id is supplied or not
    if (actionExecutedContext.ActionDescriptor.ActionName.Equals("List", StringComparison.InvariantCultureIgnoreCase))
    {
        verbs += ", POST";
    }
    else
    {
        verbs += ", PUT, DELETE";
    }

    return verbs;
}

A more sophisticated implementation could use reflection (and caching) to dynamically build up the allowed verbs from the attributes on the controller’s methods… perhaps combining those with the user’s permissions.

Ignore Missing XSLT

Previously, whenever an XML representation was being served, the model object would be serialised then passed through a transform before being returned to the client. If the transform did not exist, an error would be raised. However, being pragmatic, this transform is not always necessary. In fact, if the model classes are only used to hold data in a form useful for the web service (as opposed to in a form used by the rest of the system) it is very likely those objects serialise to just the form your clients need, resulting in a lot of transforms that do nothing.

In this version, the XmlFormatHandler has a new property, IgnoreMissingXslt. If this is set to true, the handler will use a transform if it is present, but if it is not present, the raw XML created by serialising the model object will be returned and no error raised. You can set this flag at application start up using:

FormatManager.Current.ResponseFormatHandlers.Clear();
FormatManager.Current.ResponseFormatHandlers.Add(new XmlFormatHandler { IgnoreMissingXslt = true });

XSLT Naming Convention

One further change I made in this area was changing the names of the transforms that the framework looks for when serialising and deserialising model objects. Previously, given a view name such as ItemGet, the framework would look for ItemGetInternalToExternal.xslt. Now it will simply look for ItemGet.xslt (bringing the naming convention in line with those for the ASPX files). I’m sure you’ll agree that is “nicer”. For incoming representations it looks for a transform based on just the class name being deserialised. So whereas before we might have ProductXmlExternalToInternal.xslt, now we just have Product.xslt.

JSON Position = 0

An issue was raised with the JSON deserialisation. A change has been introduced into ASP.Net or .Net 4 generally that means that the stream made available for deserialisation has already been advanced beyond the data content’s location. Setting the stream’s position back to zero, before passing the stream to the serialiser, fixes that issue.

JSON.Net

In two projects I have worked on it has become apparent that serialising to JSON is very convenient for some clients (i.e. JavaScript running in browsers) and that .Net’s built in JSON serialiser is just not up to scratch (especially when compared with the XmlSerialiser). Therefore, this release introduces a new Format Handler which uses James Newton King’s excellent JSON.Net implementation. I submitted a few patches that mean it now sits even more comfortably alongside the XmlSerializer (e.g. support for the XyzSpecified pattern for indicating if a property has been deserialised or should be serialised). Again this can be registered at Application start up:

FormatManager.Current.ResponseFormatHandlers.Clear();
FormatManager.Current.ResponseFormatHandlers.Add(new JsonNetFormatHandler { JsonSerializerSettings = CreatesJsonSerializerSettings(), Formatting = Formatting.Indented });

So now your model classes can dictate how they will be exposed in both XML and JSON:

[XmlElement("DebugInformation"), JsonProperty(PropertyName = "debugInformation")]
public string DebugInformation

The latest version is available here: RESTfulMVCWebService24.zip (265.96 kb)


Comments (6) -

June 1. 2011 17:03

Brett

Thanks for all the effort on the blog.  I am working on a ASP.NET MVC 3 Web Service and have found your blog to be a time saver.   I think v24 has a small issue.  You simplified the naming of the XSLT files, but I think you forgot to rename the one under  /views/home to ListGet.xslt from the old format.  I had to rename mine to get it to work.

Brett

June 1. 2011 20:07

Piers

Thanks Brett, I'm working on a new post which shows how to implement a web service from scratch.

Piers

June 9. 2011 17:50

Electric Cig Man

I find it remarkable and quite admirable that you decided to provide this code freely. Life would be so much happier if all followed in your footsteps. Thank you!

Electric Cig Man

August 16. 2011 12:25

Michael S

I enjoyed building my own web service based on your ShouldersOfGiants.Web.Mvc and your web service example.
But I would appreciate if a small documentation about the key features is available, reading your example code and drawing conclusions simply lead also in a wrong direction.

Finally a detail needs clarification: in one of my XSLTs for creating output XML I use this line:
<concept xmlns="example.com/abc1"> ....
But the xmlns attribute doesn't appear in the output - while any other attribute added to the concept element does. Do you filter out this attribute somewhere?

Michael

Michael S

August 18. 2011 16:37

Michael S

I withdraw my "missing xmlns attribute" issue above, apparently Firefox strips it off.

Michael S

August 18. 2011 23:57

admin

Thanks for your comments Michael. I'm currently, very slowly preparing an overview post that should cover everything and thinking about putting the project on CodePlex... finding the spare time is the main issue!

admin

Add comment

  Country flag

biuquote
  • Comment
  • Preview
Loading