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)