Azioni del controller ASP.NET MVC che restituiscono JSON o HTML parziale


406

Sto cercando di creare azioni del controller che restituiranno JSON o HTML parziale a seconda di un parametro. Qual è il modo migliore per ottenere il risultato restituito in una pagina MVC in modo asincrono?

Risposte:


519

Nel tuo metodo di azione, restituisci Json (oggetto) per restituire JSON alla tua pagina.

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

Quindi chiama il metodo di azione usando Ajax. È possibile utilizzare uno dei metodi di supporto da ViewPage come

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

SomeMethod sarebbe un metodo javascript che quindi valuta l'oggetto Json restituito.

Se vuoi restituire una stringa semplice, puoi semplicemente usare ContentResult:

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

ContentResult per impostazione predefinita restituisce un testo / semplice come contentType.
Questo è sovraccarico, quindi puoi anche fare:

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

9
scusa phil! questo in realtà non risponde alla domanda vero? è sicuramente utile, ma come dice Brad, è necessario scoprire in qualche modo cosa stanno chiedendo e restituire il risultato di conseguenza.
Simon_Weaver,

vedere la mia un po 'legati domanda (bene quello che mi ha portato qui) a stackoverflow.com/questions/482363/...
Simon_Weaver

9
se trovi una risposta, collegala alla domanda stessa. Inoltre, non penso che questa sia la risposta giusta.
Cherian,


Qual è il nome completo di quella classe Json?
Josh Withee,

112

Penso che dovresti considerare gli AcceptTypes della richiesta. Lo sto usando nel mio progetto attuale per restituire il tipo di contenuto corretto come segue.

La tua azione sul controller può testarlo come sull'oggetto richiesta

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

È quindi possibile implementare l'aspx della vista per soddisfare il caso di risposta parziale xhtml.

Quindi in jQuery puoi recuperarlo passando il parametro type come 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

Spero che questo aiuti James


5
Grazie James, ciò potrebbe essere molto utile per creare una sorta di sito Web e un'API REST utilizzando le stesse azioni del controller.
NathanD

Se nel mio controller ho molti metodi come questo, posso farlo in modo più generico?
Seph

In quale spazio dei nomi è la classe Json? Qual è la dipendenza per project.json? Grazie in anticipo
Andrei,

1
Questa è la classe JsonResult da System.Web.Mvc (in System.Web.Mvc.dll) @Andrei
James Green

Grazie, l'ho trovato. Forse aggiorni la risposta per riflettere la nuova API? A proposito, sto usando dotnet core dove è Microsoft.AspNetCore.Mvc.JsonResult.
Andrei,

78

Un altro bel modo di gestire i dati JSON è usare la funzione getJSON di JQuery. Puoi chiamare il

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

Metodo dal metodo jquery getJSON semplicemente ...

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

15
Questo non risponde affatto alla domanda.
Aaronaught,

2
@Aaronaught In realtà la prima parte return Json(new {foo="bar", baz="Blech"});fa!
SparK

Considera anche $ .post stackoverflow.com/questions/751218/… (impostazioni predefinite ASP.Net MVC per disabilitare JSON Ricevi richieste per motivi di sicurezza)
Greg

50

Ho riscontrato un paio di problemi nell'implementazione delle chiamate GET ajax GET con JQuery che mi hanno causato mal di testa, quindi condividendo le soluzioni qui.

  1. Assicurati di includere il tipo di dati "json" nella chiamata ajax. Ciò analizzerà automaticamente l'oggetto JSON restituito per te (dato che il server restituisce json valido).
  2. Includi il JsonRequestBehavior.AllowGet; senza questo MVC stava restituendo un errore HTTP 500 (con dataType: jsonspecificato sul client).
  3. Aggiungi cache: falsealla chiamata $ .ajax, altrimenti alla fine otterrai risposte HTTP 304 (anziché HTTP 200) e il server non elaborerà la tua richiesta.
  4. Infine, il json fa distinzione tra maiuscole e minuscole, quindi il case degli elementi deve corrispondere sul lato server e sul lato client.

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

Codice MVC di esempio:

[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

Per rispondere all'altra metà della domanda, puoi chiamare:

return PartialView("viewname");

quando si desidera restituire HTML parziale. Dovrai solo trovare un modo per decidere se la richiesta richiede JSON o HTML, magari in base a una parte / parametro URL.


2
quindi la domanda non rimane senza risposta?
Simon_Weaver,

2
Questo non risponde alla domanda.
Aaronaught,

sta cercando una richiesta Ajax per ottenere l'html utilizzando PartialView richiede un aggiornamento della pagina a meno che non si restituisca la vista da un metodo di azione utilizzando una chiamata Ajax
Chris McGrath

7

Soluzione alternativa con framework di codifica

Azione ritorno json

controllore

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

Pagina del rasoio

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

Azione restituire html

controllore

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

Pagina del rasoio

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


4

PartialViewResult e JSONReuslt ereditano dalla classe base ActionResult. quindi, se il tipo restituito viene deciso, dichiarare in modo dinamico l'output del metodo come 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);
            }
        }

potresti aggiungere qualche informazione in più su ciò che fa?
RealCheeseLord,

Poiché il codice mostra che è di ritorno JSON, il tipo di ritorno dovrebbe essere JsonResult e non ActionResult
noobprogrammer

0

Approccio flessibile per produrre output diversi in base alla richiesta

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

Il Request.IsAjaxRequest()metodo è abbastanza semplice: controlla semplicemente le intestazioni HTTP per la richiesta in arrivo per vedere se il valore dell'intestazione X-Requested-With è XMLHttpRequest, che viene automaticamente aggiunto dalla maggior parte dei browser e dei framework AJAX.

Metodo di estensione personalizzato per verificare se la richiesta è per json o meno in modo che possiamo chiamarla da qualsiasi luogo, proprio come il metodo di estensione 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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.