Uri Hendler - 250 - Jul 17, 2014

Is there a way to automatically match a format to a content type?
e.g. if I append “format=ics” (or “.ics”) to the query string, but the actual content type for icalendar is “text/calendar”.

I see that ServiceStack does this automatically for the pre-defined MIME types (in the ServiceStack.MimeTypes class), so if you do “format=json”, it figures out that the response content type should be “application/json”.

It would be nice to be able to do a simple GET request via the browser, like “/api/events.ics” and have ServiceStack set the ResponseContentType property automatically, so my custom format plugin can correctly serialize the response.

Is this possible for other formats, or do I need to add the “Accept: text/calendar” header to the request?

The built-in functionality only works for registered different Content Types registered with HostContext.ContentTypes, e.g for CSV:
https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/Formats/CsvFormat.cs#L12-L13
So if you register a new ContentType for “text/calendar” it will work for “/api/events.calendar”. 

Likewise for the custom v-card format: http://mono.servicestack.net/ServiceStack.Northwind/vcard-format.htm
it would be /events.x-vcard

If that’s not suitable you can try inspecting the /pathinfo.ext with a request filter and setting req.ResponseContentType from there.

Uri Hendler:

Using .calendar would be fine, but the client expects to be able to use .ics to request iCalendar data.

Using a global request filter to set the RequestContentType isn’t a complete solution.

I also had to add:
appHost.ContentTypes.Register(“application/ics”, SerializeToStream, null);

Then I can change the RequestContentType to “text/calendar” in the request filter.

Without this, a request with a .ics extension returns a 400 (RequestBindingException) and the request filter never fires.

Sir Thomas:

I have a few custom formatters, and use this in my formatter class (atom/rss is one of them):

http://pastebin.com/PfgFBiwu

Like you mention, it requires multiple actions (registration, global filter, etc).  The way I see it, it allows for multiple extension types to all return the same format type.