AutoFormatResult

This attribute is a ActionFilterAttribute.
Result will be formatted according to the content-type request.

    [AutoFormatResult]
    public ActionResult About()
    {
        var locations = new[] { "United Kingdom", "Belgium", "United States" };
        return View(locations);
    }


If we request this page using our web browser we'll get the normal HTML result we expect.

To return other formats we just need to set our accept headers to the appropriate media type. So setting to application/json will return JSON and text/xml will return XML.

application/json
[
   "United Kingdom",
   "Belgium",
   "United States"
]

text/xml
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
               xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <string>United Kingdom</string>
    <string>Belgium</string>
    <string>United States</string>
</ArrayOfString>


Adding your own formatter is simply a case of implementing MediaTypeViewResultFormatter, or IViewResultFormatter if you want more control. Below is the PartialViewResultFormatter (not added by default) that automatically returns a Partial View if the request is made via AJAX or is a Child Action:

public class PartialViewResultFormatter : IViewResultFormatter
{
    private readonly string partialViewPrefix;

    public PartialViewResultFormatter(string partialViewPrefix = "_")
    {
        Ensure.Argument.NotNull(partialViewPrefix, "partialViewPrefix"); // can be empty
        this.partialViewPrefix = partialViewPrefix;
    }

    public bool IsSatisfiedBy(ControllerContext controllerContext)
    {
        return controllerContext.HttpContext.Request.AcceptTypes.Contains("text/html")
            && (controllerContext.HttpContext.Request.IsAjaxRequest() || controllerContext.IsChildAction);
    }

    public ActionResult CreateResult(ControllerContext controllerContext, ActionResult currentResult)
    {
        var viewResult = currentResult as ViewResult;

        if (viewResult == null)
            return null;

        var viewName = viewResult.ViewName.NullIfEmpty() 
            ?? controllerContext.RequestContext.RouteData.GetRequiredString("action");

        if (viewName.IsNullOrEmpty())
            throw new InvalidOperationException("View name cannot be null.");

        var partialViewName = string.Concat(partialViewPrefix, viewName);

        // check if partial exists, otherwise we'll use the same view
        var partialExists = viewResult.ViewEngineCollection.FindPartialView(controllerContext, partialViewName).View != null;

        var partialViewResult = new PartialViewResult
        {
            ViewData = viewResult.ViewData,
            TempData = viewResult.TempData,
            ViewName = partialExists ? partialViewName : viewName,
            ViewEngineCollection = viewResult.ViewEngineCollection,
        };

        return partialViewResult;
    }
}

You then need to register the formatter when your application starts:
protected void Application_Start()
{
    // ...

    ViewResultFormatters.Formatters.Add(new PartialViewResultFormatter());
}

Last edited Jun 12, 2013 at 11:26 AM by jefflequeux, version 1

Comments

No comments yet.