web-dev-qa-db-fra.com

Quand utiliser JsonResult sur ActionResult

Je n'ai pas pu trouver de réponse concrète à cette question. J'ai vu les messages et les messages suivants de this question et ailleurs, mais tout ce que je retiens de la lecture est que JsonResult a un type de contenu codé en dur et qu'il n'y a vraiment aucun gain de performances.

Si les deux résultats peuvent renvoyer Json, pourquoi auriez-vous besoin d'utiliser JsonResult plutôt que ActionResult.

public ActionResult()
{
    return Json(foo)
}

public JsonResult()
{
    return Json(bar)
}

Quelqu'un peut-il expliquer un scénario où ActionResult ne peut tout simplement pas faire le travail et JsonResult doit être utilisé. Sinon, pourquoi JsonResult existe-t-il en premier lieu.

22
CSharper

Quand utiliser JsonResult sur ActionResult

Je retourne généralement des résultats concrets (par exemple JsonResult, ViewResult) et il y a mes avantages:

Il existe des liens où les gens soutiennent cette approche:

Il y a une citation de Pro ASP.NET MVC 3 Framework :

Remarque Notez que le type de retour pour la méthode d'action dans la liste est ViewResult. La méthode se compilerait et fonctionnerait aussi bien si nous avions spécifié le type plus général ActionResult. En fait, certains programmeurs MVC définiront le résultat de chaque méthode d'action comme ActionResult, même lorsqu'ils savent qu'il renverra toujours un type plus spécifique. Nous avons été particulièrement diligents dans cette pratique dans les exemples qui suivent pour montrer clairement comment vous pouvez utiliser chaque type de résultat, mais nous avons tendance à être plus détendus dans les projets réels.

J'utiliserais ActionResult par rapport à une action concrète uniquement si une action devait renvoyer différents types de résultats. Mais ce n'est pas cette situation courante.

Je voudrais également ajouter que ActionResult est une classe abstraite, vous ne pouvez donc pas simplement créer une instance de ce type et la renvoyer. JsonResult est concret, vous pouvez donc créer son instance et revenir d'une méthode d'action. Il existe de nombreux autres types dérivés de ActionResult et essentiellement tous sont tilisés pour remplacer la méthode ExecuteResult .

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

Cette méthode est invoquée par ControllerActionInvoker et implémente la logique d'écriture des données dans l'objet response.

ControllerActionInvoker ne connaît pas les résultats concrets afin qu'il puisse gérer tout résultat dérivé de ActionResult et implémente ExecuteResult.

Dans les deux cas, vous retournez une instance de type JsonResult dans votre exemple et Json(model) c'est simplement une méthode d'usine qui crée une instance de JsonResult.

Il y a une autre question SO Est-il préférable que le type de données d'une méthode soit aussi spécifique que possible ou plus général? où les meilleures pratiques pour les paramètres de méthode et les valeurs de retour sont discutées .

L'idée générale est de fournir des types abstraits comme paramètres afin que votre méthode puisse gérer une plus large gamme de paramètres; renvoyant suffisamment de types concrets pour que vos clients n'aient pas besoin de les convertir ou de les convertir.

19
Ilya Palkin

Vous avez peut-être remarqué que les noms de tous les types de retour courants dans un contrôleur MVC se terminent par "résultat" et, le plus souvent, la plupart des actions renvoient un ActionResult. Si vous regardez la documentation , vous pouvez voir que plusieurs types de résultats, plus spécifiques, héritent de la classe abstraite ActionResult. Pour cette raison, vous pouvez maintenant renvoyer un ActionResult dans toutes vos actions, et même renvoyer différents types. Exemple:

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

Tout cela facilite le retour de contenu différent, en fonction de la demande. Alors pourquoi utiliseriez-vous JsonResult plutôt que ActionResult? Peut-être qu'il n'y a donc pas de malentendus, et vous en effet seulement pouvez retourner JSON, peut-être pour la lisibilité, ou une autre préférence personnelle.

4
Tobias

Il adhère simplement au principe Polymorphisme.

En définissant la signature de méthode comme renvoyant un résumé ActionResult qui est le type de base pour JsonResult, ViewResult, ContentResult (et autres), vous obtenez le possibilité de renvoyer l'un des types ci-dessus en laissant le implémentation de l'action décider quel ActionResult retourner.

Par exemple:

public ActionResult GetData(int id)
{
     var data = .... // some data

     if (Request.AcceptTypes.Contains("json"))
          return Json(data);
     else
          return View(data);
}

Il s'agit en fait d'une pratique courante dans OOP pour définir le type renvoyé de la méthode aussi abstrait que possible. Vous pouvez également le trouver dans .NET BCL, l'utilisation de IEnumerable<> Dans Linq par exemple:

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

La méthode Where() est déclarée comme retournant IEnumerable<T> Afin que vous puissiez appeler la méthode sur n'importe quel type qui implémente l'interface IEnumerable<T>, Que ce soit un Array , List, HashSet ou Dictionary.

3
haim770

En fait, il n'y a aucune raison d'utiliser JsonResult comme type de retour des méthodes Action. Dans ce cas, il est préférable d'utiliser la classe abstraite ActionResult pour suivre les principes polymorphes.

En appelant return Json(value) vous appelez en fait la méthode d'assistance de la classe Controller qui ressemble à:

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

Comme nous pouvons le voir - Json méthode d'assistance, elle instancie JsonResult de toute façon.

2
Dmitry Zaets