ASP.NET MVC-Controller-Aktionen, die JSON oder teilweise HTML zurückgeben


406

Ich versuche, Controller-Aktionen zu erstellen, die je nach Parameter entweder JSON oder partielles HTML zurückgeben. Wie kann das Ergebnis am besten asynchron auf eine MVC-Seite zurückgegeben werden?

Antworten:


519

Geben Sie in Ihrer Aktionsmethode Json (Objekt) zurück, um JSON auf Ihre Seite zurückzugeben.

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

Rufen Sie dann einfach die Aktionsmethode mit Ajax auf. Sie können eine der Hilfsmethoden aus der ViewPage verwenden, z

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

SomeMethod wäre eine Javascript-Methode, die dann das zurückgegebene Json-Objekt auswertet.

Wenn Sie eine einfache Zeichenfolge zurückgeben möchten, können Sie einfach das ContentResult verwenden:

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

ContentResult gibt standardmäßig einen Text / eine Ebene als Inhaltstyp zurück.
Dies ist überladbar, sodass Sie auch Folgendes tun können:

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

9
Entschuldigung, Phil! Dies beantwortet nicht wirklich die Frage, oder? Es ist definitiv nützlich, aber wie Brad sagt, müssen Sie irgendwie herausfinden, wonach sie fragen, und das Ergebnis entsprechend zurückgeben.
Simon_Weaver

Siehe meine etwas verwandte (auch die, die mich hierher geführt hat) Frage unter stackoverflow.com/questions/482363/…
Simon_Weaver

9
Wenn Sie eine Antwort finden, verknüpfen Sie sie in der Frage selbst. Ich denke auch nicht, dass es richtig ist, dies zu überprüfen, da die Antwort das Richtige ist.
Cherian


Wie lautet der vollqualifizierte Name dieser Json-Klasse?
Josh Withee

112

Ich denke, Sie sollten die AcceptTypes der Anfrage berücksichtigen. Ich verwende es in meinem aktuellen Projekt, um den richtigen Inhaltstyp wie folgt zurückzugeben.

Ihre Aktion auf dem Controller kann sie wie auf dem Anforderungsobjekt testen

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

Sie können dann den Aspx der Ansicht implementieren, um den partiellen xhtml-Antwortfall zu berücksichtigen.

Dann können Sie es in jQuery abrufen und den Typparameter als json übergeben:

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

Hoffe das hilft James


5
Vielen Dank, James, das könnte sehr nützlich sein, um eine Art Website und eine REST-API mit denselben Controller-Aktionen zu erstellen.
NathanD

Wenn ich viele solcher Methoden in meinem Controller habe, gibt es eine Möglichkeit, dies generischer zu tun?
Seph

In welchem ​​Namespace befindet sich die Json-Klasse? Was ist die Abhängigkeit für project.json? Vielen Dank im Voraus
Andrei

1
Das ist die JsonResult-Klasse von System.Web.Mvc (in System.Web.Mvc.dll) @Andrei
James Green

Danke, habe es gefunden. Aktualisieren Sie möglicherweise die Antwort, um die neue API widerzuspiegeln? Übrigens verwende ich Dotnet Core, wo es Microsoft.AspNetCore.Mvc.JsonResult ist.
Andrei

78

Eine weitere gute Möglichkeit, mit JSON-Daten umzugehen, ist die Verwendung der JQuery-Funktion getJSON. Sie können die anrufen

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

Methode aus der jquery getJSON-Methode durch einfaches ...

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

15
Dies beantwortet die Frage überhaupt nicht.
Aaronaught

2
@Aaronaught Eigentlich macht der erste Teil return Json(new {foo="bar", baz="Blech"});!
SparK

Beachten Sie auch $ .post stackoverflow.com/questions/751218/… (ASP.Net MVC deaktiviert standardmäßig JSON Get Requests aus Sicherheitsgründen)
Greg

50

Ich habe einige Probleme beim Implementieren von MVC Ajax GET-Aufrufen mit JQuery festgestellt, die mir Kopfschmerzen bereiteten, sodass ich hier Lösungen austauschte.

  1. Stellen Sie sicher, dass der Datentyp "json" in den Ajax-Aufruf aufgenommen wird. Dadurch wird das zurückgegebene JSON-Objekt automatisch für Sie analysiert (vorausgesetzt, der Server gibt einen gültigen JSON zurück).
  2. Schließen Sie das ein JsonRequestBehavior.AllowGet; ohne diese MVC gab einen HTTP 500-Fehler zurück (mitdataType: json auf dem Client angegeben).
  3. Hinzufügen cache: false Sie dem Aufruf $ .ajax hinzu, andernfalls erhalten Sie letztendlich HTTP 304-Antworten (anstelle von HTTP 200-Antworten) und der Server verarbeitet Ihre Anfrage nicht.
  4. Schließlich unterscheidet der JSON zwischen Groß- und Kleinschreibung, sodass das Gehäuse der Elemente auf der Server- und der Client-Seite übereinstimmen muss.

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

Beispiel für einen MVC-Code:

[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

Um die andere Hälfte der Frage zu beantworten, können Sie anrufen:

return PartialView("viewname");

wenn Sie teilweise HTML zurückgeben möchten. Sie müssen nur einen Weg finden, um zu entscheiden, ob die Anforderung JSON oder HTML möchte, möglicherweise basierend auf einem URL-Teil / Parameter.


2
Bleibt die Frage nicht unbeantwortet?
Simon_Weaver

2
Dies beantwortet die Frage nicht.
Aaronaught

Er sucht nach einer Ajax-Anfrage, um das HTML mit PartialView abzurufen. Erfordert eine Seitenaktualisierung, es sei denn, Sie geben die Ansicht von einer Aktionsmethode mit einem Ajax-Aufruf zurück
Chris McGrath

7

Alternative Lösung mit Incoding-Framework

Aktion return json

Regler

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

Rasiermesserseite

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

Aktion HTML zurückgeben

Regler

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

Rasiermesserseite

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


4

PartialViewResult und JSONReuslt erben von der Basisklasse ActionResult. Wenn also der Rückgabetyp dynamisch festgelegt wird, deklarieren Sie die Methodenausgabe als 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);
            }
        }

Könnten Sie ein wenig mehr Informationen darüber hinzufügen, was dies bewirkt?
RealCheeseLord

Da Ihr Code die Rückgabe von JSON anzeigt, sollte der Rückgabetyp JsonResult und nicht ActionResult sein
noobprogrammer

0

Flexibler Ansatz zur Erzeugung unterschiedlicher Ausgaben basierend auf der Anforderung

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

Das Request.IsAjaxRequest() Methode ist recht einfach: Sie überprüft lediglich die HTTP-Header auf eingehende Anforderungen, um festzustellen, ob der Wert des X-Requested-With-Headers lautetXMLHttpRequest , der von den meisten Browsern und AJAX-Frameworks automatisch angehängt wird.

Benutzerdefinierte Erweiterungsmethode, um zu überprüfen, ob die Anforderung für json ist oder nicht, damit wir sie von überall aufrufen können, genau wie bei der Erweiterungsmethode Request.IsAjaxRequest ():

using System;
using System.Web;

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

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.