When to use JsonResult over ActionResult

前端 未结 4 715
时光取名叫无心
时光取名叫无心 2020-12-29 23:57

I\'ve been unable to find a concrete answer regarding this question. I\'ve viewed posts and subsequent posts from this question and elsewhere but all I\'ve really come out o

相关标签:
4条回答
  • 2020-12-30 00:13

    When to use JsonResult over ActionResult

    I usually return concrete results (e.g. JsonResult, ViewResult) and there are my pros:

    • Controller's interface gives more information about it's behavior. It is easier to work with partial or shared views when you specify PartialViewResult and ViewResult as result type precisely.
    • It is easier to test since it is not needed to cast result to concrete types in your unit tests.

    There are some links where people support this approach:

    • What's the difference between ActionResult and ViewResult for action method?
    • Must ASP.NET MVC Controller Methods Return ActionResult?
    • ViewResult vs ActionResult

    There is a quote from Pro ASP.NET MVC 3 Framework:

    Note Notice that that the return type for the action method in the listing is ViewResult. The method would compile and work just as well if we had specified the more general ActionResult type. In fact, some MVC programmers will define the result of every action method as ActionResult, even when they know it will always return a more specific type. We have been particularly diligent in this practice in the examples that follow to make it clear how you can use each result type, but we tend to be more relaxed in real projects.

    I would use ActionResult over concrete one only if an action should return different types of results. But it is not that common situation.

    I'd like also to add that ActionResult is an abstract class so you cannot simply create an instance of this type and return it. JsonResult is concrete so you can create its instance and return from an action method. There are many other types that derived from ActionResult and basically all of them are used to override ExecuteResult method.

    public abstract class ActionResult
    {
        public abstract void ExecuteResult(ControllerContext context);
    } 
    

    This method is invoked by ControllerActionInvoker and implements logic writing data to response object.

    ControllerActionInvoker does not know about concrete results so that it can handle any result that is derived from ActionResult and implements ExecuteResult.

    In both cases you return an instance of JsonResult type in your example and Json(model) it is simply a Factory Method that creates an instance of JsonResult.

    There is another SO question Is it better to have a method's datatype be as specific as possible or more general? where best practices for method parameters and return values are discussed.

    The general idea is providing abstract types as parameters so that your method can handle wider range of parameter; returning concrete enough types so that your clients do not need to cast or convert them.

    0 讨论(0)
  • 2020-12-30 00:13

    Actually there is no reasons to use JsonResult as return type of Action methods. In this case it is better to use abstract class ActionResult to follow polymorphic principles.

    By calling return Json(value) you are actually calling helper method of Controller class which looks like:

    protected internal virtual JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior)
    {
        return new JsonResult
        {
            Data = data,
            ContentType = contentType,
            ContentEncoding = contentEncoding,
            JsonRequestBehavior = behavior
        };
    }
    

    As we can see - Json helper method it instantiate JsonResult anyway.

    0 讨论(0)
  • 2020-12-30 00:23

    It's just adhering simple Polymorphism principle.

    By defining the method signature as returning an abstract ActionResult which is the base type for JsonResult, ViewResult, ContentResult (and others) you're given the ability to return any of the above types by letting the implementation of the action decide which ActionResult to return.

    For example:

    public ActionResult GetData(int id)
    {
         var data = .... // some data
    
         if (Request.AcceptTypes.Contains("json"))
              return Json(data);
         else
              return View(data);
    }
    

    It is actually a common practice in OOP to define the returned type of the method as abstract as possible. You can find it in .NET BCL as well, the IEnumerable<> usage in Linq for example:

    public static IEnumerable<T> Where<T>
                           (
                           this IEnumerable<T> source,
                           Func<T, bool> predicate
                           );
    

    The Where() method is declared as returning IEnumerable<T> so that you can call the method on any type that is implementing the IEnumerable<T> interface, be it an Array, List, HashSet or Dictionary.

    0 讨论(0)
  • 2020-12-30 00:27

    You may have noticed that the names of all the common return types in an MVC controller end with "result", and more often than not, most actions return an ActionResult. If you look at the documentation, you can see that several, more specalized result types, inherit from the abstract class ActionResult. Because of this, you can now return an ActionResult in all of your actions, and even return different types. Example:

    public ActionResult View(int id)
    {
        var result = _repository.Find(id);
        if(result == null)
            return HttpNotFound(); //HttpNotFoundResult, which inherits from HttpStatusCodeResult
        return View(result); //ViewResult
    }
    

    All of this makes it easier to return different content, based on the request. So why would you use JsonResult over ActionResult? Perhaps so there are no misunderstandings, and you indeed only can return JSON, perhaps for readability, or some other personal preference.

    0 讨论(0)
提交回复
热议问题