A humble WCF feature request (or four)
Since Steve Maine’s excellent and informative blog appears to be down tonight, I’m posting my request here for all to see. I’d like to see two things for WCF in .NET 3.5.
First is response message encoding specified per service operation. If we’re really creating a RESTful service, then it makes sense to be able to change encoding formats for given URI “extensions”, and not having to create different endpoints for each format. So what I mean is that “http://aaronlerch.com/blog/tags/WCF.rss” should return RSS, “http://aaronlerch.com/blog/tags/WCF.json” should return JSON, and “http://aaronlerch.com/blog/tags/WCF.xml” should return XML. Simple as that. Twitter’s API does this, as I’m sure many others do, and I really like it. It fits with the URI paradigm of readability and just makes logical sense. I could only find one post out there that even hints at this ability (emphasis mine):
[ServiceContract]
public interface IGameStatistics
{
[OperationContract]
[WebGet(UriTemplate = "Rankings/{player}")]
SyndicationFeedFormatter<SyndicationFeed> GetPlayerStats(string player);
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json,
UriTemplate = "PlayerSearch?GameType={gameType}&SortAscending={ascending}")]
Player[] Search(int gameType, bool ascending);
}
I’m fairly certain this functionality will be in the final shipping bits, if not the next CTP/Beta, but I wanted to voice my opinion just in case.
Secondly, along similar lines to #1, I want to be able to specify an XSLT transform that gets applied to the POX response from a service operation. I’d even be satisfied with extensibility points added to the plumbing code that exists to support the WebGet/WebInvoke attributes. But best case scenario I’d like to be able to write something like this:
[ServiceContract]
public interface IBlogService
{
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Xml, XsltResource = "blogtag.xslt", UriTemplate = "tags/{tag}")]
BlogEntry[] GetTaggedBlogEntries(string tag);
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "tags/{tag}.json")]
BlogEntry[] GetTaggedBlogEntriesAsJson(string tag);
etc…
}
I request this because implementing the same type of friendly URI usage in ASP.NET requires all sorts of fun URL rewriting. That, and my web service would need to be hosted elsewhere, or on another port, or in a different web, etc. Why not combine the two? If I can specify an XSLT transform (optionally) I can combine my HTML site with my XML service and leverage the work I’ve already done to achieve URI bliss.
This is actually something I think I could accomplish on my own with the tools and extension points currently available, and I I’m going to explore that. I hesitate to do too much work since in the next release it could all be for naught. (Okay, honestly I just hesitate to do too much work. Period.
)
And hey, while I’m at it, why can’t I request one more thing? I’d like to tag the same service operation with multiple WebGet/WebInvoke attributes, using the parameters from the best match for the behavior that actually gets applied. That would sure simplify things:
[ServiceContract]
public interface IBlogService
{
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Xml, XsltResource = "blogtag.xslt", UriTemplate = "tags/{tag}")]
[WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "tags/{tag}.json")]
[WebGet(ResponseFormat = WebMessageFormat.Xml, UriTemplate = "tags/{tag}.xml")]
BlogEntry[] GetTaggedBlogEntries(string tag);
}
And one more! How about using type converters to allow me to tag a service operation and specify an RSS response format, but automate the conversion from BlogEntry[] (for example) to the appropriate syndication feed. I haven’t done much at all with this, however, so I’m risking a comment of “um, you can do that already” or “um, that makes no sense”.
What do you think – are these requests value-added?
August 22nd, 2007 at 11:29 pm
Good thought – except that the ACCEPT header can specify wildcard values, which would not play well with the well-defined interfaces WCF offers. Besides, I think being explicit about encoding, etc. is a good thing – I just want to do it at the ServiceOperation level, not the endpoint binding level.
Your blog post has some good points about the UriTemplate limitations. I think I read that the limitations will get better over time, but can’t find my source (might’ve been Steve Maine’s blog
August 22nd, 2007 at 11:29 pm
I’m not too sure about your first request to allow extensions in the Uri. Isn’t the Accept HTTP header supposed to be used to indicate what type of media you want back? The fact that the average browser does not let you specify the Accept header directly shouldn’t encourage to re-invent the wheel.
Having said that, if the UriTemplate allowed us to do
UriTemplate=”/blog/tags/WCF{MediaType}” then it would not be a problem.
I do like your second suggestion though. The ability to apply an XSLT transform on the serialized return values would be excellent.
I posted a few weeks ago about a number of other limitations that I have come across with UriTemplate.
http://www.bizcoder.com/index.php/2007/07/24/systemuritemplate/
May 27th, 2008 at 11:45 am
[...] the bit between the one forward slash and another, or one querystring parameter. A few bloggers requested more flexibility in UriTemplates, and the WCF team answered with the soon-to-be-released 3.5 SP1. The ability to define variables [...]
October 31st, 2008 at 7:29 pm
I’ve done something similar to what you are looking for, except that instead of having to have two methods (one for XML and one for JSON) you can have a single method, and depending on the content type that the client requests (via the “Accept” HTTP Request header), the appropriate format is automatically returned.
I do it by hooking in my own IDispatchMessageFormatter
All the code etc:
http://damianblog.com/2008/10/31/wcf-rest-dynamic-response/
/Damian