简体   繁体   中英

Return JSON from any ASP.NET MVC controller action based on a parameter

During development I often write my controller methods like this so I can ensure the contents of the model are properly populated and to aid in development of the view.

public ActionResult SomeMethod(int id, bool asJson = false)
{
    var model = SomeBackendService.GetModel(id);
    if(asJson)
        return Json(model, JsonRequestBehavior.AllowGet);
    return View(model);
}

I change them once the view development is done, but then sometimes I find myself wishing I could get the results as JSON later on.

Ideally, I'd like to set a Web.config key that would allow the the controller method to be requested as JSON without recoding each method for each controller. I'd like the following method to return the model as JSON when requested with a certain querystring parameter.

public ActionResult SomeMethod(int id)
{
    var model = SomeBackendService.GetModel(id);
    return View(model);
}

I'm guessing the road I need to travel down is to implement my own view engine, but I'm not sure that is correct.

Actually, I figured out how to do this using a custom DisplayModeProvider.

It occurred to me that I can just all I really need to do is to use a view that will render the JSON. So I created a custom DisplayProvider to override the TransformPath method:

public class JsonOnlyDisplayProvider : DefaultDisplayMode
{
    public JsonOnlyDisplayProvider(string suffix) : base(suffix) { }        

    protected override string TransformPath(string virtualPath, string suffix)
    {
        return "~/Views/Shared/JsonOnly.cshtml";
    }
}

Then I modified the Application_Start method in Global.asax to insert the new provider with a ContextCondition that evaluates the AppSetting and querystring parameter.

protected void Application_Start()
{        
    DisplayModeProvider.Instance.Modes.Insert(0, 
        new JsonOnlyDisplayProvider(DisplayModeProvider.DefaultDisplayModeId)
    {
        ContextCondition = context => 
            (context.Request.QueryString["asJson"] == "true" && 
             !string.IsNullOrEmpty(ConfigurationManager.AppSettings["AllowJson"]) && 
             ConfigurationManager.AppSettings["AllowJson"] == "true")
    });
}

The last step was to create the generic view that would spew out the JSON. (Granted, this approach does not add the appropriate headers...I'm open to suggestions on how to get that sorted)

JsonOnly.cshtml

@{
    Layout = null;
    if (Model != null)
    {
        @Html.Raw(Json.Encode(Model))
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM