c# - jsonrequestbehavior - return json mvc 5
Cuándo usar JsonResult sobre ActionResult (4)
Cuándo usar
JsonResult
sobreActionResult
Por lo general, devuelvo resultados concretos (por ejemplo, ViewResult
, ViewResult
) y existen mis ventajas:
- La interfaz del controlador da más información sobre su comportamiento. Es más fácil trabajar con vistas parciales o compartidas cuando especifica
PartialViewResult
yViewResult
como tipo de resultado con precisión. - Es más fácil de probar ya que no es necesario emitir resultados a tipos concretos en sus pruebas de unidad .
Hay algunos enlaces donde las personas apoyan este enfoque:
- ¿Cuál es la diferencia entre ActionResult y ViewResult para el método de acción?
- ¿Deben los métodos del controlador MVC de ASP.NET devolver ActionResult?
- ViewResult vs ActionResult
Hay una cita de Pro ASP.NET MVC 3 Framework :
Nota Tenga en cuenta que el tipo de retorno para el método de acción en el listado es
ViewResult
. El método se compilaría y funcionaría igual de bien si hubiéramos especificado el tipo más general deActionResult
. De hecho, algunos programadores de MVC definirán el resultado de cada método de acción comoActionResult
, incluso cuando saben que siempre devolverá un tipo más específico. Hemos sido particularmente diligentes en esta práctica en los ejemplos que siguen para aclarar cómo puede usar cada tipo de resultado, pero tendemos a ser más relajados en proyectos reales.
ActionResult
sobre uno concreto solo si una acción debe devolver diferentes tipos de resultados. Pero no es esa situación común.
También me gustaría agregar que ActionResult
es una clase abstracta, por lo que no puede simplemente crear una instancia de este tipo y devolverla. JsonResult
es concreto, por lo que puede crear su instancia y regresar de un método de acción. Hay muchos otros tipos que se derivan de ActionResult
y básicamente todos ellos se utilizan para anular el método ExecuteResult
.
public abstract class ActionResult
{
public abstract void ExecuteResult(ControllerContext context);
}
ControllerActionInvoker
invoca este método e implementa la escritura lógica de datos en el objeto de response
.
ControllerActionInvoker
no conoce los resultados concretos, por lo que puede manejar cualquier resultado derivado de ActionResult
e implementa ExecuteResult
.
En ambos casos, devuelve una instancia del tipo JsonResult
en su ejemplo y Json(model)
es simplemente un método de fábrica que crea una instancia de JsonResult
.
Hay otra pregunta de SO ¿Es mejor que el tipo de datos de un método sea lo más específico posible o más general? donde se discuten las mejores prácticas para parámetros de método y valores de retorno .
La idea general es proporcionar tipos abstractos como parámetros para que su método pueda manejar un rango más amplio de parámetros; devolver tipos suficientemente concretos para que sus clientes no tengan que lanzarlos o convertirlos.
No he podido encontrar una respuesta concreta con respecto a esta pregunta. He visto publicaciones y publicaciones posteriores de this pregunta y en otros lugares, pero todo lo que realmente he leído es que JsonResult tiene un tipo de contenido codificado y realmente no hay ningún aumento de rendimiento.
Si ambos resultados pueden devolver a Json, ¿por qué necesitaría usar JsonResult sobre ActionResult?
public ActionResult()
{
return Json(foo)
}
public JsonResult()
{
return Json(bar)
}
¿Alguien puede explicar un escenario donde ActionResult simplemente no puede hacer el trabajo y se debe usar JsonResult? Si no es así, ¿por qué JsonResult existe en primer lugar?
Es posible que haya notado que los nombres de todos los tipos de devolución comunes en un controlador MVC terminan con "resultado" y, en la mayoría de los casos, la mayoría de las acciones devuelven un ActionResult. Si observa la documentation , puede ver que varios tipos de resultados, más especalizados, heredan de la clase abstracta ActionResult. Debido a esto, ahora puede devolver un ActionResult en todas sus acciones, e incluso devolver diferentes tipos. Ejemplo:
public ActionResult View(int id)
{
var result = _repository.Find(id);
if(result == null)
return HttpNotFound(); //HttpNotFoundResult, which inherits from HttpStatusCodeResult
return View(result); //ViewResult
}
Todo esto hace que sea más fácil devolver contenido diferente, según la solicitud. Entonces, ¿por qué usarías JsonResult sobre ActionResult? Tal vez no haya malentendidos, y de hecho solo puede devolver JSON, quizás por legibilidad, o alguna otra preferencia personal.
Simplemente se adhiere al principio del polimorfismo simple.
Al definir la firma del método como devolver un ActionResult
abstracto, que es el tipo base para JsonResult
, ViewResult
, ContentResult
(y otros), se le permite devolver cualquiera de los tipos anteriores permitiendo que la implementación de la acción decida qué ActionResult
devolver .
Por ejemplo:
public ActionResult GetData(int id)
{
var data = .... // some data
if (Request.AcceptTypes.Contains("json"))
return Json(data);
else
return View(data);
}
En realidad, es una práctica común en OOP definir el tipo devuelto del método lo más abstracto posible. También puede encontrarlo en .NET BCL, el uso de IEnumerable<>
en Linq, por ejemplo:
public static IEnumerable<T> Where<T>
(
this IEnumerable<T> source,
Func<T, bool> predicate
);
El método Where()
se declara que devuelve IEnumerable<T>
para que pueda llamar al método en cualquier tipo que esté implementando la IEnumerable<T>
, ya sea una Array
, List
, HashSet
o Dictionary
.
En realidad, no hay razones para usar JsonResult
como tipo de retorno de métodos de acción. En este caso, es mejor usar la clase abstracta ActionResult
para seguir los principios polimórficos.
Al llamar a return Json(value)
, en realidad está llamando al método auxiliar de la clase Controller que se ve así:
protected internal virtual JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior)
{
return new JsonResult
{
Data = data,
ContentType = contentType,
ContentEncoding = contentEncoding,
JsonRequestBehavior = behavior
};
}
Como podemos ver, el método de ayuda de JsonResult
instancia a JsonResult
todos modos.