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?

NathanD
fonte

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");
Haacked
fonte
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
stackoverflow.com/questions/320291/... está relacionada
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

James Green
fonte
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);
    }
);
Desenvolvedor SaaS
fonte
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);
}
Shane
fonte
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.

Brad Wilson
fonte
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())
Vlad
fonte
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;


        }
Anil Vaddepally
fonte
3

Para as pessoas que fizeram o upgrade para o MVC 3, aqui está uma maneira interessante de usar o MVC3 e o Json

Sarath
fonte
1
você também pode usar a mesma técnica que este artigo em 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
fonte
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

Mannan Bahelim
fonte