Ações do controlador ASP.NET MVC que retornam JSON ou html parcial


406

Estou tentando criar ações do controlador que retornarão JSON ou html parcial, dependendo de um parâmetro. Qual é a melhor maneira de obter o resultado retornado a uma página MVC de forma assíncrona?

Respostas:


519

No seu método de ação, retorne Json (objeto) para retornar JSON à sua página.

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

Em seguida, basta chamar o método de ação usando o Ajax. Você pode usar um dos métodos auxiliares do ViewPage, como

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

SomeMethod seria um método javascript que avalia o objeto Json retornado.

Se você deseja retornar uma string simples, basta usar o ContentResult:

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

O ContentResult, por padrão, retorna um texto / planície como seu contentType.
Isso é sobrecarregável, então você também pode fazer:

return Content("<xml>This is poorly formatted xml.</xml>", "text/xml");

9
desculpe phil! isso realmente não responde à pergunta, não é? é definitivamente útil, mas como Brad diz que você precisa descobrir de alguma forma o que eles estão pedindo e retornar o resultado de acordo.
Simon_Weaver

ver meu algo relacionado (bem o que me trouxe até aqui) pergunta em stackoverflow.com/questions/482363/...
Simon_Weaver

9
se você encontrar uma resposta, vincule-a na própria pergunta. Também não acho que verificar isso como a resposta é a coisa certa.
187 Cherian


Qual é o nome completo dessa classe Json?
Josh Withee

112

Eu acho que você deve considerar os AcceptTypes da solicitação. Estou usando-o no meu projeto atual para retornar o tipo de conteúdo correto da seguinte maneira.

Sua ação no controlador pode testá-lo como no objeto de solicitação

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"))
{
   //
}

Você pode implementar o aspx da visualização para atender ao caso de resposta xhtml parcial.

Em jQuery, você pode buscá-lo passando o parâmetro type 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 isso ajude James


5
Obrigado James, isso poderia ser muito útil para criar um tipo de site e uma API REST usando as mesmas ações do controlador.
NathanD

Se eu tiver muitos métodos como esse no meu controlador, existe alguma maneira de fazer isso de forma mais genérica?
Seph

Em qual namespace está a classe Json? Qual é a dependência do project.json? Agradecemos antecipadamente #
Andrei

1
Essa é a classe JsonResult de System.Web.Mvc (em System.Web.Mvc.dll) @Andrei
James Green

Obrigado, encontrei. Talvez atualize a resposta para refletir a nova API? Btw, eu estou usando dotnet core, onde é Microsoft.AspNetCore.Mvc.JsonResult.
Andrei

78

Outra boa maneira de lidar com dados JSON é usar a função JQuery getJSON. Você pode ligar para o

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

Método do método jquery getJSON simplesmente ...

$.getJSON("../SomeActionMethod", { id: someId },
    function(data) {
        alert(data.foo);
        alert(data.baz);
    }
);

15
Isso não responde à pergunta.
Aaronaught 14/09/11

2
@Aaronaught Na verdade, a primeira parte return Json(new {foo="bar", baz="Blech"});faz!
SparK 21/03

Considere também $ .post stackoverflow.com/questions/751218/... (padrão ASP.Net MVC para desativar JSON Obter pedidos por razões de segurança)
Greg

50

Encontrei alguns problemas ao implementar chamadas MVC ajax GET com JQuery, o que me causou dores de cabeça, portanto, compartilhando soluções aqui.

  1. Certifique-se de incluir o tipo de dados "json" na chamada ajax. Isso analisará automaticamente o objeto JSON retornado para você (dado que o servidor retorna json válido).
  2. Inclua o JsonRequestBehavior.AllowGet; sem esse MVC estava retornando um erro HTTP 500 (com dataType: jsonespecificado no cliente).
  3. Adicione cache: falseà chamada $ .ajax, caso contrário, você obterá respostas HTTP 304 (em vez de respostas HTTP 200) e o servidor não processará sua solicitação.
  4. Por fim, o json faz distinção entre maiúsculas e minúsculas, portanto, a caixa dos elementos precisa corresponder no lado do servidor e no cliente.

Amostra JQuery:

$.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 amostra:

[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);
}

13

Para responder a outra metade da pergunta, você pode ligar para:

return PartialView("viewname");

quando você deseja retornar HTML parcial. Você só precisará encontrar uma maneira de decidir se a solicitação deseja JSON ou HTML, talvez com base em uma parte / parâmetro da URL.


2
então a pergunta não permanece respondida?
Simon_Weaver

2
Isso não responde à pergunta.
Aaronaught 14/09

ele está à procura de um pedido ajax para obter o html usando PartialView requer uma atualização de página, a menos que você é voltar a vista de um método de ação usando uma chamada ajax
Chris McGrath

7

Solução alternativa com estrutura de codificação

Ação return json

Controlador

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

Página de barbear

@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())

Ação return html

Controlador

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

Página de barbear

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


4

PartialViewResult e JSONReuslt herdam da classe base ActionResult. portanto, se o tipo de retorno for decidido, declare dinamicamente a saída do 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;


        }


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);
            }
        }

você poderia adicionar um pouco mais de informações sobre o que isso faz?
RealCheeseLord

Como seu código mostra que é JSON de retorno, o tipo de retorno deve ser JsonResult e não ActionResult
noobprogrammer

0

Abordagem flexível para produzir diferentes resultados com base na solicitação

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);
  }
}

O Request.IsAjaxRequest()método é bastante simples: ele simplesmente verifica nos cabeçalhos HTTP a solicitação de entrada para ver se o valor do cabeçalho X-Requested-With éXMLHttpRequest , que é automaticamente anexado pela maioria dos navegadores e estruturas AJAX.

Método de extensão personalizado para verificar se a solicitação é para json ou não, para que possamos chamá-la de qualquer lugar, assim como o método de extensão Request.IsAjaxRequest ():

using System;
using System.Web;

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

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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.