Add a HTML MediaTypeFormater to the Web API
The Web Api is great but does not provide a simple way to provide a browser friendly representation. If a MediaTypeFormatter was created that would handle "application/xhtml+xml", "text/html" and "*/*" by using the standard view engines that come as part of ASP.Net MVC, it would be simple to provide a browsable, HTML version of the API. To this a developer could add help text per resource and a test harness to the layout/master page, using the familiar Razor or Web Forms based approach.
Automatically generating help (as the WCF Web Api didi) is all well and good for a very simple API, but the proposed approach would allow a client developer to explore the API very easily through their browser and allow the API developer to provide comprehensive online help (rather than a simple description that the WCF Web API supportted).
We shipped support for automatic help page generation in the ASP.NET and Web Tools 2012.2 release. It’s built as an MVC Area instead of using an HTML formatter. If you still think an HTML formatter for Web API would be useful then please create a separate suggestion and vote it up!
Ryan Riley commented
Needs docs, but check out http://nuget.org/packages/WebApiContrib.Formatting.Razor/
Moto Williams, I agree with you, I'm not sure why this was marked as completed when the functionality Daniel mentions does not address the feature as originally stated... it addresses one of the benefits of the feature... but not the core purpose, which was o be able to generate an HTML representation. I have implemented a proof of concept version that works by extending JSON.Net.
This seriously can't be marked at completed right? Implementing help page generation isn't what this request is about at all. Sure that is a possible scenario that is enabled by the request but not the point of this request.
I really baffled to why there is resistance to this when the other frameworks in the space just do this.
Is there anywhere that I can contribute to the discussion on how this is to be implemented?
In the last 8 months I have changed my opinion on what I would like to see... rather than using a templating engine, I believe it would be much better to have a HtmlMediaFormatter that serialized to an HTML representation directly, controlled by attributes on the model classes... Just like the JSON and XML media formatters do.
For instance, each object might be held in <dl class="ClassName"></dl>. Each property of a class might be wrapped in a <dt>PropertyName</dt><dd>PropertyValue</dd>. A collection would be held in a <ul></ul>. Perhaps resulting in a representation such as:
This approach saves a lot of developer time as we don't need to create Razor templates for each and every model class that needs serialising.
Obviously, creating an HtmlSerializer from scratch would be painful, however I have created a prototype HtmlWriter derived from Newtonsoft.Json.Utilities.JsonWriter that can be passed into jsonSerializer.Serialize(). This means the same powerful attributes being used to control the formatting of the JSON will control the formatting of the HTML.
I'm happy to pass on the prototype for discussion.
Good spot Roger, though the ideal is that we only need a single controller handling all representations. Your solution I presume requires two, one in the Web API world and one in the MVC world. Of course they could both hand off to a common class to do the real work, but it is still only a workaround. Nice idea though and I'm glad it solves your problem.
I found a simple solution to what I'm trying to do, which is to add a constraint on the MVC route, which is first in the route list. The constrain checks httpContext.Request.AcceptTypes to see if the request is text/html, if so, the MVC controller is returned, otherwise the request moves down to the API route. Same exact Uri, different result. Nice.
To follow up on my last comment. The goal is that I can have the same route return HTML, JSON, etc., but send the HTML request to the MVC handler instead of the API handler.
I don't mind using a separate MVC route for returning HTML. With that said, is there a route constraint that I can add to my API route that will allow the API route to be skipped if the request header Accept is for XHTML instead of JSON, XML, etc? An example would be superb!
"Go use MVC" doesn't work for me... I already am using it.
I use my own api for the "ajaxy" parts of my site and I'd like to be able to return partial views from my api with the HTML that needs to be added to the page.
I don't like having to maintain multiple templates in different languages that emitt the same html.
@Ryan I'm not sure if you are saying it is a good idea or not... I agree a standard HTML-based formatter would always be a compromise. That is why my ideal is an HTML MediaTypeFormatter that hands off the returned object to the same rendering engine used by MVC (i.e. the part that is given the model, finds the right view via convention and renders the output). This would allow the API developer to decide exactly what form his HTML should take but also take advantage of all the HTML Helpers, discovery of views and child controls via conventions. This would make the process a lot less painless without tieing the representation to some arbitary standard HTML.
An alternative could be a rich HtmlSerializer class that uses attributes in the same manner that the XmlSerializer does to give very good control over the output format... but hooking up to the existing MVC rendering engine would probably be easier ;-)
Ryan Riley commented
The problem with a standard HTML-based formatter is that you really need some form of HtmlBuilder. No one will agree on the standard serialization format HTML would provide, so you would in every case do better to build your own formatters for each case. Thus, MVC is likely a better solution as it is targeted at composing HTML as a respresentation format. That said, you can certainly use HTML as a message format. See Mike Amundsen's book Building Hypermedia APIs with HTML5 and Node. It's just not a cut-and-dried answer as are the other in-the-box formatters.
You can find some HTML builder DSLs online. Dan already pointed at Howard's Razor-based formatter. WebApiContrib.codeplex.com has an old and now broken attempt I did that let you choose different view engines. If you are using F#, WebSharper and Wing Beats are good options.
Statements of “go use MVC for this” completely miss the point. I agree with @Piers and this should be in the box for the cases of returning html representations of an object at the URI that the request was made. Other frameworks have (or have in the next release) conneg that also support markup requests. Also not every client out there is going to be able to use a client side tempting engine to convert JSON or Xml responses to markup.
There is some request/response slight-of-hand that can be done using RewritePath inside a HttpModule and but that isn’t going to be very useful in a self-host (non IIS) situations.
As for the couple of RazorMediaTypeFormatter samples, also as stated before that is just duplicate effort that is pushed down to the developer. I don’t think there is a way to keep your compiled views in memory and despite flags on the CSharpCodeProvider I alwayed ende up littering my directory with compiled view assembleis.
@tugbert the point is that we're looking to serve HTML as just another representation from the same URI. As there does not appear to be a way to use content negotiation to direct to MVC or Web API, then the HTML would have to be served from a different URI. If it was possible then as Eddy points out, we'd end up writing two Controllers. Yes, you are right we could use a simple Razor formatter, but then you lose the benefits that come with the View mechanisim in MVC such as helpers and shared controls. The code is all there.. its a shame not to be able to use it.
This shouldn't be OOB. As Dan indicated, if you need HTML, go use ASP.NET MVC. Providing one will bring out nothing but confusion. You will feel yourself fork in the road between Web API and MVC.
As Dan commented below, Howard implemented a RazorHtmlMediaTypeFormatter. If you really need one, go use it.
Eddy Recio commented
Web API looks awesome, but now I have an MVC controller and a Web API Controller with duplicate code, where ideally the same object is represented as either Html, JSON, etc based on content negotiation. Basically the same way the browser works. Additionally, filters, validation, etc are all duplicated. Ideally, Web API would enable both Razor (view engine) as well as the UrlHelper and HtmlHelper to work within views by converting the appropriate context objects, they look nearly identical in many cases, but different base types and interfaces.
Thanks for the feedback Daniel. What I was hoing for was an HTML format being served from exactly the same URI as the JSON and XML. Hosting the Razor engine as shown in that blog post could do that, though it doesn't give all the flexibility of MVC. I guess I need to wait and see what you do with help... if help can be served off the same URI (without needing "/help" appended to the URI) that would be good... if that help also included a representation of the resource that would be brilliant. I have used my ROM/ShouldersOfGiants API framework in a few projects now, and the feedback I get for having the API browsable via a browser (rather than hacking in fiddler) and having inline help is that is extremely useful for client developers. They get to grips with the API very quickly and can explore how it works very simply. One of my blog posts shows some screen shots of this in action:
See https://github.com/howarddierking/RestBugs/blob/master/RestBugs%20Solution/RestBugs.Services/Infrastructure/RazorHtmlMediaTypeFormatter.cs for an example Razor formatter.