Blog Post

Use ASP.NET MVC ActionFilters to Render AJAX Responses!

In my previous blog post on ASP.NET MVC, I walked through an example based on the MVC Preview 2 bits which showed how to make your own custom view engines and ActionFilters.  I also proved (or at least hope I proved) just how powerful these parts of the framework can be, especially when used in conjunction with each other.  The truth is that - while I thought they made great examples on how to extend the base parts of the framework - the whole thing seemed kind of kludgie to me.  What I mean is that it felt kind of awkward having to use the ActionFilter to change which ViewEngine is being used on the fly.  I don't know, maybe I just feel like view engines should be more closely tied to the controller and shouldn't just be chosen willy-nilly like that!

This was all before the introduction of the ActionResult in MVC Preview 3.  Oh man, was this a great addition!  Expanding the notion of being "loosely coupled", the controller action's job is no longer to execute logic and chose which view to display-- ok, well, it is...  only now its main responsibility is returning an ActionResult, which is basically a command object that tells the framework what to do instead the controller taking that action itself.  This not only helps us to decouple the controller (allowing for easier testing, etc.), it also lets us know what the controller wants the framework to do before it happens.  When you think of it, this is pretty powerful stuff, and gives us access to a whole new part of the process in which can inject additional logic.  And inject it we shall...

The SerializableViewDataAttribute Revisited

In my previous post, the attribute that I adorned my Actions with was pretty stupid.  It just said, "Is this an AJAX request? If so, set our custom view engine."  Pretty much all of the meaningful (and interesting) logic happened in our custom view engine.  Now, with the introduction of the ActionResult we no longer have to wait until the view engine phase to get access to (and override) the way our data is returned to the client - we can hijack it in the attribute, and manipulate the Action's result!  Before I confuse you any more, here's the code:

SerializableViewDataAttribute: Preview 3 style
   public class SerializableViewDataAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            // Get the (lowercase) render mode from the querystring
            var method = filterContext.HttpContext.Request.QueryString["renderMode"] ?? string.Empty;
            method = method.ToLowerInvariant();

            // Get the view data from the context (using a custom extension method defined elsewhere)
            var viewData = filterContext.GetViewData();
            
            // If this isn't a serializable request or it has no data, just return
            if(string.IsNullOrEmpty(method) || viewData == null) return;

            // Decide which method to use
            switch (method)
            {
                case("xml"):
                    filterContext.Result = getXmlResult(viewData);
                    break;
                case("json"):
                    filterContext.Result = getJsonResult(viewData);
                    break;
                case ("partial"):
                    // If this is supposed to be a partial request, just change the view name.
		    // Obviously, this implies that this view exists (in addition to your
		    // original view that the controller was pointing to to begin with.
                    var viewResult = ((ViewResult)filterContext.Result);
                    viewResult.ViewName = "Partial" + viewResult.ViewName;
                    break;
            }
        }

        private static ActionResult getJsonResult(object viewData)
        {
            // Since there's a JsonResult Action, 
            // all we have to do is pass in the data
            return new JsonResult { Data = viewData };
        }

        private static ActionResult getXmlResult(object viewData)
        {
            // There's no "XmlResult" so we have to serialize it ourselves
            var sb = new StringBuilder();
            using (var writer = new StringWriter(sb))
            {
                new XmlSerializer(viewData.GetType()).Serialize(writer, viewData);
            }

            // ...then pass it into a ContentResult
            return new ContentResult { 
                     ContentType = "text/xml",  // Be sure to set the ContentType!
                     Content = sb.ToString()
                 };
        }

    }

As you can see, it is a lot like the logic that was used to create my custom view engine in the last post.  In fact, I essentially copied and pasted it (and added support for partial rendering)!  Also, now that all of this logic lives in the ActionFilter we have no more need for that pesky custom view engine.  So long, cruft!

For the benefit of those who may not have read the explanation of this logic in my previous blog post, I'll go ahead and repeat (as well as expand on) it here.  This version should actually be a lot easier to understand since the logic is now contained in one place instead of spread out between the ActionFilter and the ViewEngine.  Here's a basic run-down of what's going on:

  1. The first thing to note is that we're overriding the OnActionExecuted method of the ActionFilter.  What this implies is that the controller action to which this attribute is applied has already completed, so we now have access to everything it's done: ViewData, TempData, ViewName, etc.  We could also have overridden the OnResultExecuting method as well; this would be somewhat similar to the difference between the PreRender and Render events when using Web Forms.
  2. Once the "event" has been triggered, the first thing we want to do is figure out what, exactly, is expected of us - AKA, which serialization mode (if any) we should be using.  In this implementation, I have decided to glean this information from the querystring, but you can just as easily use any other environment variable you'd like (such as the Route Data, cookies... whatever!).
  3. Next, I get the ViewData from the context, if any, using the filterContext.GetViewData() extension method.  Though this method is defined elsewhere and you can't see it in this snippet, it's not really all that interesting - it's just a convenience method that drills down into filterContext.Controller.ViewData (or ViewData.Model, if available) and returns it.
  4. Check the render method that we got in Step #2 and if that or the ViewData is invalid, there's nothing for us to do, so we're done and we just return.
  5. Assuming we didn't bail out in Step #4, we then go on to overwrite the existing ActionResult (or its properties), depending on what the user has asked for.  This particular version supports:
    1. JSON:  Along with the introduction of the ActionResult came the JsonResult, which is a super-cool implementation of ActionResult that serializes whatever data you give to it into JSON to be rendered down to the browser.  As you can see in this example, this makes handling requests for JSON data really simple and easy.
    2. XML:  Though there is no "XmlResult" as there is for JSON, the MVC framework still provides a ContentResult which is a lot like the JsonResult in spirit.  Both of them allow us to send data in some form back to the browser without requiring a View to render it with.  Going back to our example - you can see that it takes a bit of work, but the end result is a raw batch of just XML sent back to the client for processing.
    3. Partial Rendering:  I included this render mode as a bit of a teaser - I should have a follow-up post going in-depth about using partial rendering in ASP.NET MVC.  For now, I'll just say that you can think of it a lot like the ASP.NET AJAX UpdatePanel server control...
  6. That's it!  If we've gotten to this step and not hit any of the three types above, this particular filter will just let the request continue on and have no effects what-so-ever.  That probably means it'll just end up rendering out a fully-rendered page like any other normal (non-AJAX) request.  The important part to note here is that this filter only injects behavior when it is appropriate.  Otherwise, things proceed as normal and noone even needs to know that these actions are AJAX-ified unless you want them to.

I don't know about you, but the power that this kind of stuff gives us just makes my head spin!  Hopefully you find the above useful; if you do, please feel free to contact me and let me know, especially if you end up using it in one of your apps!

As always, you can check out all of the source code in my repository: http://code.jesschadwick.com/

This particular piece of code can most easily be found at this direct link.


Posted 07-02-2008 6:16 AM by [Infragistics] Jess Chadwick
Filed under:

Comments

TrackBack wrote ASP.NET MVC Archived Blog Posts, Page 1
on 07-02-2008 6:38 AM

ASP.NET MVC Archived Blog Posts, Page 1

http:// wrote Interesting topic
on 11-13-2008 6:52 AM

<p>Excellent blog! Interesting article and very informative!<a href="lowsalego.com/map.html" rel="nofollow" target="_new" mce_href="lowsalego.com/map.html"></a></p>

kbios wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 04-28-2009 6:07 AM

<a href=" dublin.craigslist.org/.../1143726511.html  ">the rules a *** survival guide</a> wrsyoy <a href=" dublin.craigslist.org/.../1143726731.html  ">*** pussies videos</a> sea

xfyag wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 04-28-2009 8:50 AM

<a href=" dublin.craigslist.org/.../1143727010.html  ">lesbians teenage ***</a> shhy <a href=" dublin.craigslist.org/.../1143727328.html  ">*** hentai orgasms</a> enya

jdurc wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 04-28-2009 11:37 AM

<a href=" dublin.craigslist.org/.../1143727816.html  ">private *** sex torrent</a> mwwf <a href=" dublin.craigslist.org/.../1143728129.html  ">kyla cole *** galleries</a> aaknmq

wqwbs wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 04-28-2009 2:25 PM

<a href=" dublin.craigslist.org/.../1143728454.html  ">amatuer *** photos</a> gvthvl <a href=" dublin.craigslist.org/.../1143728951.html  ">*** hardcore galleries</a> ujku

djbuu wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 04-28-2009 5:18 PM

<a href=" dublin.craigslist.org/.../1143729365.html  ">*** porn video samples</a> aqyvm <a href=" dublin.craigslist.org/.../1143729672.html  ">mature *** seduces young girl</a> lkkp

cfnjb wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 04-28-2009 7:58 PM

<a href=" dublin.craigslist.org/.../1143730208.html  ">lesbians drinking *** milk</a> rvlg <a href=" dublin.craigslist.org/.../1143730842.html  ">kelly lebrock *** dickinson</a> ppndf

ruoev wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 04-28-2009 10:29 PM

<a href=" dublin.craigslist.org/.../1143731128.html  ">sapphic *** teens</a> eqq <a href=" dublin.craigslist.org/.../1143731388.html  ">mature *** teachers and schoolgirls</a> ayhi

ueeqb wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 04-29-2009 3:38 AM

<a href=" dublin.craigslist.org/.../1143732457.html  ">cuckold *** relationship</a> qke <a href=" dublin.craigslist.org/.../1143732767.html  ">horny sexy lesbians</a> lvr

anogy wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 04-29-2009 6:11 AM

<a href=" dublin.craigslist.org/.../1143733230.html  ">plaid skirt ***</a> ntht <a href=" dublin.craigslist.org/.../1143733517.html  ">*** sistas clips</a> mun

ceytc wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 04-29-2009 8:51 AM

<a href=" dublin.craigslist.org/.../1143733876.html  ">*** cervical cancer</a> qhz <a href=" dublin.craigslist.org/.../1143734301.html  ">*** illustrated free pictures galleries</a> nyfw

ztzby wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 04-29-2009 4:57 PM

<a href=" dublin.craigslist.org/.../1143735738.html  ">black *** novels</a> fjxa <a href=" dublin.craigslist.org/.../1143736003.html  ">jordan capri *** clips</a> jmvezb

sreww wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 04-30-2009 1:16 AM

<a href=" dublin.craigslist.org/.../1143737618.html  ">nipples sucking ***</a> pvjmjj <a href=" dublin.craigslist.org/.../1143737902.html  ">*** events chicago</a> ede

ewihy wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 04-30-2009 6:50 AM

<a href=" dublin.craigslist.org/.../1143738775.html  ">nerd girls lesbians</a> xdqsn <a href=" dublin.craigslist.org/.../1143739078.html  ">*** demo video</a> cijc

iewhp wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 04-30-2009 12:35 PM

<a href=" dublin.craigslist.org/.../1143739833.html  ">naked lesbians fucking each other</a> yrqbko

infbe wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 04-30-2009 6:01 PM

<a href=" dublin.craigslist.org/.../1143738245.html  ">*** teen kissing pics</a> ggpwz <a href=" dublin.craigslist.org/.../1143738471.html  ">lesbians tounge kissing</a> ffdnuu

kdica wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 04-30-2009 8:32 PM

<a href=" dublin.craigslist.org/.../1143736298.html  ">korean lesbians naked</a> lmznsp <a href=" dublin.craigslist.org/.../1143736591.html  ">*** archive mpeg</a> dbn

rxsnl wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-04-2009 9:29 PM

<a href=" www.dezinedepot.com/.../19580 ">allaura eden ***</a> zexs

ssphh wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-05-2009 12:09 AM

<a href=" www.dezinedepot.com/.../19581 ">*** sexy cheerleaders</a> nzedvl

wwxjf wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-05-2009 7:59 AM

<a href=" www.dezinedepot.com/.../19595 ">strap on *** *** sex</a> lxp

okwod wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-05-2009 1:36 PM

<a href=" www.dezinedepot.com/.../19600 ">all access lesbians</a> txmqr

ewfdg wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-05-2009 4:18 PM

<a href=" forum.reverbnation.com/.../3826 ">buy tamiflu</a> gnm

ombdo wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-05-2009 6:50 PM

<a href=" forum.reverbnation.com/.../3827 ">tamiflu without a prescription</a> nux

qncyq wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-05-2009 9:18 PM

<a href=" forum.reverbnation.com/.../3828 ">buy tamiflu online</a> zmm

weumm wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-05-2009 11:53 PM

<a href=" forum.reverbnation.com/.../3829 ">tamiflu for sale</a> hgh

jqqrt wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-06-2009 2:17 AM

<a href=" forum.reverbnation.com/.../3830 ">swine flu mexico tamiflu</a> kryxjs

zbeyp wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-06-2009 4:54 AM

<a href=" forum.reverbnation.com/.../3831 ">tamiflu canada</a> ybammc

qfrrd wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-06-2009 10:09 AM

<a href=" forum.reverbnation.com/.../3833 ">tamiflu dosage</a> pdfu

pbkmc wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-06-2009 5:30 PM

<a href=" forum.urbis.com/.../409 ">teen girls licking</a> csvopi <a href=" forum.reverbnation.com/.../4213 ">hot teens flashing ***</a> qbrjcc

zwmen wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-06-2009 6:08 PM

<a href=" forum.reverbnation.com/.../3836 ">tamiflu cost</a> gap

tubrj wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-06-2009 8:43 PM

<a href=" forum.reverbnation.com/.../3837 ">tamiflu online</a> pqbhtb

lywlw wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-06-2009 9:12 PM

<a href=" forum.reverbnation.com/.../4131 ">smoking teen girls</a> wmewfl <a href=" forum.reverbnation.com/.../4244 ">*** that looks thirteen</a> kzae

wydsk wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-06-2009 11:12 PM

<a href=" forum.reverbnation.com/.../3838 ">buy tamiflu online</a> mnoe

secfl wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-07-2009 1:05 AM

<a href=" forums.batchblue.com/.../166 ">teen girls uncovered</a> pciugk <a href=" forum.sproutit.com/.../543 ">sexy teen celebrities</a> bdi

cgwyh wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-07-2009 4:12 AM

<a href=" forum.reverbnation.com/.../3840 ">where to buy tamiflu</a> hqn

pqyoq wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-07-2009 4:53 AM

<a href=" forums.heywatch.com/.../508 ">teen girls teasing</a> ebz <a href=" forums.layertennis.com/.../797 ">teen sluts fucking dogs</a> iqghdz

lburo wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-07-2009 6:47 AM

<a href=" forums.layertennis.com/.../811 ">teen scream sex</a> zpipnk <a href=" forum.reverbnation.com/.../4114 ">teen girl porn movies</a> gxyd

pedaa wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-07-2009 8:35 AM

<a href=" forums.heywatch.com/.../484 ">teens with hot asses</a> faod <a href=" forum.reverbnation.com/.../4126 ">tight ass teen movie</a> zap

lauvd wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-07-2009 9:22 AM

<a href=" forum.urbis.com/.../444 ">porn college teen creamers</a> qttmup <a href=" forum.sproutit.com/.../503 ">teen porn cites</a> dpxfp

keiud wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-07-2009 12:42 PM

<a href=" forum.reverbnation.com/.../4219 ">teen nudity pics</a> ruvqw <a href=" forums.layertennis.com/.../831 ">puerto rican teen pics</a> cwnxa

icboi wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-07-2009 2:45 PM

<a href=" forum.urbis.com/.../412 ">teen sex education videos</a> rhogd <a href=" forum.reverbnation.com/.../4121 ">teenaage ***</a> fhofw

yzyah wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-07-2009 5:18 PM

<a href=" forums.heywatch.com/.../520 ">trixies teens ***</a> jqus <a href=" forum.reverbnation.com/.../4188 ">teens who ***</a> jhlaa

ywasn wrote re: Use ASP.NET MVC ActionFilters to Render AJAX Responses!
on 05-07-2009 8:08 PM

<a href=" forums.batchblue.com/.../167 ">hottest teen ***</a> ujxd <a href=" forum.urbis.com/.../427 ">teen goth porn</a> iokaj