Custom objects as arguments in controller methods defined by MapRoutes

若如初见. 提交于 2019-12-03 09:10:51

IMHO the response format is a cross cutting concern and it's not the controller to mess with it. I would suggest you to write an ActionFilter for this job:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public sealed class RespondToAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var resultFormat = filterContext.RouteData.Values["resultFormat"] as string ?? "html";
        ViewResult viewResult = filterContext.Result as ViewResult;
        if (viewResult == null)
        {
            // The controller action did not return a view, probably it redirected
            return;
        }
        var model = viewResult.ViewData.Model;
        if (string.Equals("json", resultFormat, StringComparison.OrdinalIgnoreCase))
        {
            filterContext.Result = new JsonResult { Data = model };
        }
        // TODO: you could add some other response types you would like to handle
    }
}

which then simplifies your controller action a bit:

[RespondTo]
public ActionResult Index(int id)
{
    var messages = new string[0];
    if (id > 0)
    {
        // TODO: Fetch messages from somewhere
        messages = new[] { "message1", "message2" };
    }
    return View(messages);
}

The ActionFilter is a reusable component that you could apply to other actions.

Your pseudo code will work correctly. Default ModelBinder automatically converts the string in the url to Models.ResultFormat enum. But it would be better to make ActionFilter, as said Darin Dimitrov.

This is the ActionFilter I came up with:

public sealed class AlternateOutputAttribute :
                    ActionFilterAttribute, IActionFilter
{
    void IActionFilter.OnActionExecuted(ActionExecutedContext aec)
    {
        ViewResult vr = aec.Result as ViewResult;

        if (vr == null) return;

        var aof = aec.RouteData.Values["alternateOutputFormat"] as String;

        if (aof == "json") aec.Result = new JsonResult
        {
            JsonRequestBehavior = JsonRequestBehavior.AllowGet,
            Data = vr.ViewData.Model,
            ContentType = "application/json",
            ContentEncoding = Encoding.UTF8
        };
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!