Acciones del controlador ASP.NET MVC que devuelven JSON o html parcial

406

Estoy tratando de crear acciones de controlador que devuelvan JSON o html parcial dependiendo de un parámetro. ¿Cuál es la mejor manera de obtener el resultado devuelto a una página MVC de forma asincrónica?

NathanD
fuente

Respuestas:

519

En su método de acción, devuelva Json (objeto) para devolver JSON a su página.

public ActionResult SomeActionMethod() {
  return Json(new {foo="bar", baz="Blech"});
}

Luego simplemente llame al método de acción usando Ajax. Puede usar uno de los métodos de ayuda de ViewPage, como

<%= Ajax.ActionLink("SomeActionMethod", new AjaxOptions {OnSuccess="somemethod"}) %>

SomeMethod sería un método de JavaScript que luego evalúa el objeto Json devuelto.

Si desea devolver una cadena simple, puede usar ContentResult:

public ActionResult SomeActionMethod() {
    return Content("hello world!");
}

ContentResult por defecto devuelve un texto / sin formato como su tipo de contenido.
Esto se puede cargar, por lo que también puede hacer:

return Content("<xml>This is poorly formatted xml.</xml>", "text/xml");
Hackeado
fuente
99
lo siento phil! esto realmente no responde la pregunta ¿verdad? definitivamente es útil, pero como dice Brad, debe saber de alguna manera lo que están pidiendo y devolver el resultado en consecuencia.
Simon_Weaver
vea mi pregunta algo relacionada (bueno, la que me llevó aquí) en stackoverflow.com/questions/482363/…
Simon_Weaver
99
Si encuentra una respuesta, vincúlela en la pregunta misma. Además, no creo que verifique esto, ya que la respuesta es lo correcto.
Cherian
stackoverflow.com/questions/320291/… está relacionado
Cherian
¿Cuál es el nombre completo de esa clase Json?
Josh Withee
112

Creo que debería considerar los AcceptTypes de la solicitud. Lo estoy usando en mi proyecto actual para devolver el tipo de contenido correcto de la siguiente manera.

Su acción en el controlador puede probarlo como en el objeto de solicitud

if (Request.AcceptTypes.Contains("text/html")) {
   return View();
}
else if (Request.AcceptTypes.Contains("application/json"))
{
   return Json( new { id=1, value="new" } );
}
else if (Request.AcceptTypes.Contains("application/xml") || 
         Request.AcceptTypes.Contains("text/xml"))
{
   //
}

Luego puede implementar el aspx de la vista para atender el caso de respuesta parcial xhtml.

Luego, en jQuery puede buscarlo pasando el parámetro de tipo como json:

$.get(url, null, function(data, textStatus) {
        console.log('got %o with status %s', data, textStatus);
        }, "json"); // or xml, html, script, json, jsonp or text

Espero que esto ayude a James

James Green
fuente
55
Gracias James, eso podría ser muy útil para crear una especie de sitio web y una API REST utilizando las mismas acciones del controlador.
NathanD 01 de
Si tengo muchos métodos como este en mi controlador, ¿hay alguna manera de que pueda hacer esto de manera más genérica?
Seph
¿En qué espacio de nombres está la clase Json? ¿Cuál es la dependencia de project.json? Gracias de antemano
Andrei
1
Esa es la clase JsonResult de System.Web.Mvc (en System.Web.Mvc.dll) @Andrei
James Green el
Gracias, lo encontré. ¿Quizás actualizar la respuesta para reflejar la nueva API? Por cierto, estoy usando dotnet core donde es Microsoft.AspNetCore.Mvc.JsonResult.
Andrei
78

Otra buena manera de tratar con datos JSON es usar la función getQSON de JQuery. Puedes llamar al

public ActionResult SomeActionMethod(int id) 
{ 
    return Json(new {foo="bar", baz="Blech"});
}

Método del método jquery getJSON simplemente ...

$.getJSON("../SomeActionMethod", { id: someId },
    function(data) {
        alert(data.foo);
        alert(data.baz);
    }
);
Desarrollador SaaS
fuente
15
Esto no responde a la pregunta en absoluto.
Aaronaught
2
@Aaronaught En realidad, la primera parte lo return Json(new {foo="bar", baz="Blech"});hace!
SparK
Considere también $ .post stackoverflow.com/questions/751218/… (ASP.Net MVC predeterminado para deshabilitar JSON Obtener solicitudes por razones de seguridad)
Greg
50

Encontré un par de problemas al implementar llamadas MVC ajax GET con JQuery que me causaron dolores de cabeza, por lo que compartir soluciones aquí.

  1. Asegúrese de incluir el tipo de datos "json" en la llamada ajax. Esto analizará automáticamente el objeto JSON devuelto por usted (dado que el servidor devuelve json válido).
  2. Incluir el JsonRequestBehavior.AllowGet; sin esto MVC estaba devolviendo un error HTTP 500 (con dataType: jsonespecificado en el cliente).
  3. Agregue cache: falsea la llamada $ .ajax, de lo contrario obtendrá respuestas HTTP 304 (en lugar de respuestas HTTP 200) y el servidor no procesará su solicitud.
  4. Finalmente, el json distingue entre mayúsculas y minúsculas, por lo que la carcasa de los elementos debe coincidir en el lado del servidor y del lado del cliente.

JQuery de muestra:

$.ajax({
  type: 'get',
  dataType: 'json',
  cache: false,
  url: '/MyController/MyMethod',
  data: { keyid: 1, newval: 10 },
  success: function (response, textStatus, jqXHR) {
    alert(parseInt(response.oldval) + ' changed to ' + newval);                                    
  },
  error: function(jqXHR, textStatus, errorThrown) {
    alert('Error - ' + errorThrown);
  }
});

Código MVC de muestra:

[HttpGet]
public ActionResult MyMethod(int keyid, int newval)
{
  var oldval = 0;

  using (var db = new MyContext())
  {
    var dbRecord = db.MyTable.Where(t => t.keyid == keyid).FirstOrDefault();

    if (dbRecord != null)
    {
      oldval = dbRecord.TheValue;
      dbRecord.TheValue = newval;
      db.SaveChanges();
    }
  }

    return Json(new { success = true, oldval = oldval},
                JsonRequestBehavior.AllowGet);
}
Shane
fuente
13

Para responder la otra mitad de la pregunta, puede llamar:

return PartialView("viewname");

cuando quieres devolver HTML parcial. Solo tendrá que encontrar alguna forma de decidir si la solicitud desea JSON o HTML, tal vez en función de una parte / parámetro de URL.

Brad Wilson
fuente
2
Entonces, ¿la pregunta queda sin respuesta?
Simon_Weaver
2
Esto no responde la pregunta.
Aaronaught
está buscando una solicitud ajax para obtener el html usando PartialView requiere una actualización de la página a menos que devuelva la vista de un método de acción usando una llamada ajax
Chris McGrath
7

Solución alternativa con marco de codificación

Action return json

Controlador

    [HttpGet]
    public ActionResult SomeActionMethod()
    {
        return IncJson(new SomeVm(){Id = 1,Name ="Inc"});
    }

Página de afeitar

@using (var template = Html.Incoding().ScriptTemplate<SomeVm>("tmplId"))
{
    using (var each = template.ForEach())
    {
        <span> Id: @each.For(r=>r.Id) Name: @each.For(r=>r.Name)</span>
    }
}

@(Html.When(JqueryBind.InitIncoding)
  .Do()
  .AjaxGet(Url.Action("SomeActionMethod","SomeContoller"))
  .OnSuccess(dsl => dsl.Self().Core()
                              .Insert
                              .WithTemplate(Selector.Jquery.Id("tmplId"))
                              .Html())
  .AsHtmlAttributes()
  .ToDiv())

Acción return html

Controlador

    [HttpGet]
    public ActionResult SomeActionMethod()
    {
        return IncView();
    }

Página de afeitar

@(Html.When(JqueryBind.InitIncoding)
  .Do()
  .AjaxGet(Url.Action("SomeActionMethod","SomeContoller"))
  .OnSuccess(dsl => dsl.Self().Core().Insert.Html())
  .AsHtmlAttributes()
  .ToDiv())
Vlad
fuente
4

PartialViewResult y JSONReuslt heredan de la clase base ActionResult. así que si se decide el tipo de retorno, declare dinámicamente la salida del método como ActionResult.

public ActionResult DynamicReturnType(string parameter)
        {
            if (parameter == "JSON")
                return Json("<JSON>", JsonRequestBehavior.AllowGet);
            else if (parameter == "PartialView")
                return PartialView("<ViewName>");
            else
                return null;


        }
Anil Vaddepally
fuente
3

Para las personas que se han actualizado a MVC 3, esta es una buena manera de usar MVC3 y Json

Sarath
fuente
1
También puede usar la misma técnica que este artículo en MVC 2
longhairedsi
2
    public ActionResult GetExcelColumn()
    {            
            List<string> lstAppendColumn = new List<string>();
            lstAppendColumn.Add("First");
            lstAppendColumn.Add("Second");
            lstAppendColumn.Add("Third");
  return Json(new { lstAppendColumn = lstAppendColumn,  Status = "Success" }, JsonRequestBehavior.AllowGet);
            }
        }
sakthi
fuente
¿podría agregar un poco más de información sobre lo que esto hace?
RealCheeseLord
Como su código muestra que es JSON de retorno, el tipo de retorno debe ser JsonResult y no ActionResult
noobprogrammer
0

Enfoque flexible para producir diferentes resultados basados ​​en la solicitud

public class AuctionsController : Controller
{
  public ActionResult Auction(long id)
  {
    var db = new DataContext();
    var auction = db.Auctions.Find(id);

    // Respond to AJAX requests
    if (Request.IsAjaxRequest())
      return PartialView("Auction", auction);

    // Respond to JSON requests
    if (Request.IsJsonRequest())
      return Json(auction);

    // Default to a "normal" view with layout
    return View("Auction", auction);
  }
}

El Request.IsAjaxRequest()método es bastante simple: simplemente comprueba los encabezados HTTP para la solicitud entrante para ver si el valor del encabezado X-Requested-With es XMLHttpRequest, que se agrega automáticamente por la mayoría de los navegadores y marcos AJAX.

Método de extensión personalizado para verificar si la solicitud es para json o no para que podamos llamarla desde cualquier lugar, al igual que el método de extensión Request.IsAjaxRequest ():

using System;
using System.Web;

public static class JsonRequestExtensions
{
  public static bool IsJsonRequest(this HttpRequestBase request)
  {
    return string.Equals(request["format"], "json");
  }
}

Fuente: https://www.safaribooksonline.com/library/view/programming-aspnet-mvc/9781449321932/ch06.html#_javascript_rendering

Mannan Bahelim
fuente