ASP.NET Web API, MVC, ViewModels and Formatters

There are probably a few more terms I can throw in there, but over the past few days, I’ve been struggling to bridge the gap from how I build applications in ASP.NET MVC and how I see folks building them in ASP.NET Web API (and other HTTP-centric frameworks).

These days, the de facto standard for building MVC applications looks something like this for GETs:

image

And for POSTs:

image

We’re using the same ViewModel for both GET and POST, where in one case the ViewModel is used in the View to build a form, and in the other case, the exact same model is used on the POST side to model bind from HTTP variables into something we can reason with.

The ViewModel usually isn’t the persistence model, as that the concerns of what your persistence layer needs often contradict what your presentation layer needs.

In this model, we have many different pieces at play here:

  • Controller – responsible for deciding what to do with a request. Show a view? Redirect?
  • ViewModel – Represents the information model for the View in GET, and a deserialization target in a POST
  • View – Responsible for translating a ViewModel into instructions for generating HTML for the view engines
  • ModelBinder – Responsible for supplying the input model to a controller action

One key piece here I want to highlight is the View. A ViewModel can’t be translated straight to HTML, and shouldn’t. It’s not an object model suited to act as complete instructions on translating the information model to the HTML media type. In fact, you don’t see really any HTML instructions on ViewModels. There are pieces in the ViewModel that can help with HTML generation (like validation attributes), but you don’t see anything like “make this a REALLY HUGE text box”, nor should you. That’s the view’s responsibility.

What’s missing is that View piece in Web API. The piece that takes the model built by a view (that is Media Type-agnostic) and provides instructions on how to then take that into

Bridging to ASP.NET Web API

Coming back to ASP.NET Web API, what objects are in play there? We have some familiar, and not so familiar:

  • Controller – Responsible for deciding what to do with a request, at the HTTP level
  • Media Type Model – Represents the information needed for a specific media type
  • Formatter – Responsible for translating a media type model to the specific media type

What’s bothering me about this model is that I now don’t have that layer to give instructions to the Formatter on how to serialize. Another thing we’ve done here is conflated the responsibilities of the “ViewModel” of this land with not only the information but also instructions.

What do I mean by “instructions”? Putting XML serialization attributes on your model created by your API controller action is mixing the media type in with your model. Having JSON mixed around directly in our controller action. Things like this, that have Json objects created directly in our actions.

I think the above abstractions are the wrong abstractions. We’re coupling the model built inside the controller action with the needs of a generic formatter. We could build a custom formatter, but that’s like building a custom view engine.

Going back to MVC, a View bridges the gap from Resource to View Engine. I believe that a Formatter in Web API is a View Engine. It is a generic translator of instructions into a specific media type (HTML). Formatters attempt to be intelligent on how to build out other media types (JSON, XML etc.), but ultimately, making them too smart means embedding media-specific information into our model. So what’s my thought? I’d like to see something like:

  • Controller – Responsible for deciding what to do with a request, at the HTTP level
  • Resource Model – Represents informational model of the resource, including links (at a conceptual level, not a technical level)
  • Media Type Template – Responsible for translating a Resource Model into instructions for a specific Media Type Formatter
  • Formatter – Responsible for using the media type template and resource model to build the response

Why the change from Media Type Model to Resource Model? I don’t want to couple the model in my controller action to a specific media type, that’s why! The conneg piece of Web API is what’s supposed to determine this. Imagine if you will that the resource model generated from the controller action is checked against media type templates to see what is possible to return back to the client.

You could use custom formatters in Web API, but looking at examples, they’re at the wrong abstraction layer, talking to things straight to streams etc.

Do we need generic Media Type Templates? No! When we were building views for different media types in MVC, we built the exact same model from the controller action that fed Telerik reports, PDF reports and HTML, all from the same controller action and model. The concept of views bridged the gap in each case to take the information model from the controller action and provide instructions to the “media type generator” on how to generate that PDF, report, or HTML view.

My ideal world

In my ideal world, my controller action in Web API would care nothing about specific media types. It would know how to build my rich, media-type-ignorant resource model, and that’s it. Web API would then try to line up to figure out what potential formatters are available for my resource model, taking into account accept headers and what media type templates (views) are available for this resource model.

Because wouldn’t it be nice if I could build a single resource model that could actually be used with multiple media types, not just JSON or XML? How about JSON, XML and HTML, and PDF? To do so, the responsibilities of the model generated by the view should only contain the informational model of the resource, and not have media type concerns leaking in.

You could have defaults to make things easier, but what’s really missing here in the Web API landscape is the concept of a view (not the MVC-specific implementation). Something that is responsible for providing (optional) instructions on taking the resource model and telling the formatter how to serialize the model. Looking at Formatters how they are today, you have to take over too much to bridge that gap.

But I could be totally off base here.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.
This entry was posted in ASP.NET MVC, ASP.NET Web API. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Jaime Jhon

    In other words….fubumvc?

    • Anonymous

      Cool story

    • mob

      Pretty much what I was thinking as I read this…

  • http://bob.archer.net/ PilotBob

    >
    Because wouldn’t it be nice if I could build a single resource model that could actuallybe used with multiple media types, not just JSON or XML? How about JSON, XML and HTML, and PDF? To do so, the responsibilities of the model generated by the view should only contain the informational model of the resource, and not have media type concerns leaking in.

    Interestingly that is exactly how Ruby on Rails works. You can add a format to the request /mycontroller/action.json and it the action will respond to that using a different formatter. You can customize it or just use the default depending on the action.

  • Anonymous

    I agree. I’ve been using Web API in my project and I really like it. However, the fact that I can’t use a “View formatter” bothers me. Someone on SO answered a question about this and said you shouldn’t be sending HTML. I agree, but in this case, it’s not that you’re sending HTML, it’s that you’re representing your model using a view (a formatter).

    I think part of this may be that MS has separated Web API from MVC… so you’d really need to write a middle man that would leverage MVC to render the view. For myself, I am mostly alright with keeping the API separate from my MVC controllers for this project.

    • http://blogs.msdn.com/gblock Glenn Block

      Darrel has a new formatter that he’s just contributed to contrib that will let you have a Razor view.

      • Anonymous

        This makes me pretty happy, thanks.

  • Grauenwolf

    There seems to be a typo. I keep seeing the word from model from Model-View-Controller spelled “ViewModel”.

    • Anonymous

      This is to be explicit about what kind of model this model is – it’s not the Rails version of a Model (persistent object).

  • http://gorodinski.com/ Lev Gorodinski

    Do you think it would be possible to use a single media type agnostic resource model to feed all media type specific views? This pattern can become brittle for media types that are sufficiently different to warrant distinct resource model classes, even though they intend to represent the same resource. I suppose the view concept can provide yet another option for returning representations, in addition to media type specific annotation, a custom formatter and an entirely distinct model class. 

    • http://blogs.msdn.com/gblock Glenn Block

      I think it depends on how you design the model and how specific the formatters are. For example I’ve successfully taken a Contact model with links and rendered it to many different formats. 

      For example to write to a vcard I have a specific formatter that reads the contact and writes out the card elements. I could have that formatter understand IContact and the model just implements it. For a png, I had the formatter take the contact id and use if to find an associated image.

      For json, it just writes it out to JSON and adds on the links.

      etc….

      • http://gorodinski.com/ Lev Gorodinski

        What are your thoughts on 
        http://www.wrml.org/ or any DSL for hypermedia APIs? I like the concept, though perhaps WRML tries to impose too much. But, a DSL could allow for formatting to become an explicit first class citizen without being intertwined with general purpose language stuff.

  • http://twitter.com/hhariri Hadi Hariri

    Add a few filters to ASP.NET MVC and you have this, always working with the same model.

  • Jeff Harris

    This is one of the reasons why I switched from WebAPI to ServiceStack…it’s not perfect, but it feels like it has the extension points I was looking for — and it seems to be more opinionated towards a serialization-agnostic model.

  • Rick Strahl

    Maybe I’m being overly simplistic, but isn’t the whole point of a ‘service’/'api’ to provide data and *not* a View? The view is on the client and that’s the whole point of using a REST API in the first place for *most representations*. Web API’s conneg does a pretty good job of  making the data you serve agnostic to the client’s request based on headers and you can extend with formatters (even if it doesn’t fit a ‘view-like’ implementation).

    ‘Data’ in this context does get a little murky admittedly, when you talk about raw data like images/pdf/html etc., but I think that in that case maybe MVC endpoints would be a better fit. Especially if used in combination with Web API so that it represents a single implementation to the user of the API.Sounds to me you’re looking too much at ‘what if’ scenarios here rather than sticking with YAGNI :-)

    • http://www.bizcoder.com Darrel Miller

      Depends.  If you are doing Web API in a RPC over HTTP kind of way then yes you are probably just returning data.  But if you are using Web API to do REST (with the hypermedia constraint) then in effect you are returning views.  Just presentation technology agnostic views.

      • Anonymous

         Not really, Hypermedia is still just returning “intelligent” data. You still need to have view in HTML/Javascript.

        I agree with Rick, the whole point of the post is to show what you can do with fubumvc and not with MSFT’s implementation.

        Since ASP.NET MVC is fully open source, these guys need to justify existence of fubumvc!

  • http://blogs.msdn.com/gblock Glenn Block

    Nice post Jimmy. In general my notion of a MediaTypeModel is agnostic to the specific media type. It’s more a model that carries all the information necessary to write to “some” media type. 

    The model can break down though in some instances. For example a few folks have written a HAL formatter. HAL has a very specific representation format and is agnostic to the domain. Thus having a HAL model makes sense for HAL, though it doesn’t necessarily make sense for raw JSON for for say an image.

    That leads me to believe there needs to be some transformative layer that can take a model and transform it into some media type specific model like a HalResource so it can be written to HAL.

    Today there’s not a clear place for this in web apis arch. My first guy is to think maybe this is the job of a filter, but I am not sure yet. It may just be that the formatter can take a series of transformation strategies that can take the model and transform it into a more specific model that carries the semantics of the media type.

  • Pingback: The Morning Brew - Chris Alcock » The Morning Brew #1082

  • Pingback: ASP.NET Web API, MVC, ViewModels and Formatters | Tek's free zone

  • Santos Victorero

    Very nice post!

    I struggled with this issue when I started working with Web Apis & it is because there is a completely different approach (set-of-mind) in designing User-Driven applications using MVC style & Machine-to-Machine applications using Hypermedia. What we call views in MVC is called Control Data (HTML Forms, XForms, etc) with Hypermedia although we could use View Engines to generate those.  

    Chapter 5 of the Rest in Practice book ( http://www.amazon.com/dp/0596805829/ref=rdr_ext_tmb ) specially the section “Hypermedia Dead Ends”  helped me a lot in understanding this issue.  

  • Matt Mercer

    openRasta is where it’s been at, ( pees all over serviceStack imo, serviceStack promises a lot out of the box, but just isn’t as extensible as openRasta ) .. I agree about the concept of a intermediary tranlator is sometimes needed, throwing a domain object at a html view where you have strict control over the output is fine, but implicit overbinding to default json serialization is a common problem with conneg apis

  • Pingback: Distributed Weekly 150 — Scott Banwart's Blog

  • http://www.facebook.com/profile.php?id=100000326093959 Srigopal Chitrapu

    Now if we want to provide REST Services as a seperate application should we deploy seperate ASP.NET Web Application?

  • Nabeel

    How to build Service Oriented Architecture while using Web API with MVC?
    Should we use seperate WCF Services layer or utilize Web API for this purpose?