Actions du contrôleur ASP.NET MVC qui retournent JSON ou html partiel

406

J'essaye de créer des actions de contrôleur qui renverront JSON ou html partiel selon un paramètre. Quelle est la meilleure façon d'obtenir le résultat renvoyé sur une page MVC de manière asynchrone?

NathanD
la source

Réponses:

519

Dans votre méthode d'action, retournez Json (objet) pour renvoyer JSON sur votre page.

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

Ensuite, appelez simplement la méthode d'action en utilisant Ajax. Vous pouvez utiliser l'une des méthodes d'assistance de ViewPage telles que

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

SomeMethod serait une méthode javascript qui évalue ensuite l'objet Json renvoyé.

Si vous souhaitez renvoyer une chaîne simple, vous pouvez simplement utiliser ContentResult:

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

ContentResult renvoie par défaut un texte / plain comme contentType.
Ceci est surchargeable, vous pouvez donc également faire:

return Content("<xml>This is poorly formatted xml.</xml>", "text/xml");
Piraté
la source
9
désolé phil! cela ne répond pas vraiment à la question, n'est-ce pas? c'est certainement utile, mais comme le dit brad, vous devez savoir en quelque sorte ce qu'ils demandent et retourner le résultat en conséquence.
Simon_Weaver
voir ma question quelque peu connexe (enfin celle qui m'a mené ici) à stackoverflow.com/questions/482363/…
Simon_Weaver
9
si vous trouvez une réponse, liez-la dans la question elle-même. De plus, je ne pense pas que vérifier cela car la réponse est la bonne chose.
Cherian
Quel est le nom complet de cette classe Json?
Josh Withee
112

Je pense que vous devriez considérer les AcceptTypes de la demande. Je l'utilise dans mon projet actuel pour renvoyer le type de contenu correct comme suit.

Votre action sur le contrôleur peut le tester comme sur l'objet de requête

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

Vous pouvez ensuite implémenter l'aspx de la vue pour répondre au cas de réponse partielle xhtml.

Ensuite, dans jQuery, vous pouvez le récupérer en passant le paramètre type comme 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

J'espère que cela aide James

James Green
la source
5
Merci James, cela pourrait être très utile pour créer une sorte de site Web et une API REST en utilisant les mêmes actions de contrôleur.
NathanD
Si j'ai de nombreuses méthodes comme celle-ci dans mon contrôleur, y a-t-il un moyen de le faire de manière plus générique?
Seph
Dans quel espace de noms se trouve la classe Json? Quelle est la dépendance de project.json? Merci à l' avance
Andrei
1
C'est la classe JsonResult de System.Web.Mvc (dans System.Web.Mvc.dll) @Andrei
James Green
Merci, je l'ai trouvé. Peut-être mettre à jour la réponse pour refléter la nouvelle API? Btw, j'utilise le noyau dotnet où c'est Microsoft.AspNetCore.Mvc.JsonResult.
Andrei
78

Une autre façon intéressante de traiter les données JSON est d'utiliser la fonction JQuery getJSON. Vous pouvez appeler le

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

Méthode de la méthode jquery getJSON par simplement ...

$.getJSON("../SomeActionMethod", { id: someId },
    function(data) {
        alert(data.foo);
        alert(data.baz);
    }
);
Développeur SaaS
la source
15
Cela ne répond pas du tout à la question.
Aaronaught
2
@Aaronaught En fait, la première partie le return Json(new {foo="bar", baz="Blech"});fait!
SparK
Considérez également $ .post stackoverflow.com/questions/751218/… (ASP.Net MVC par défaut pour désactiver JSON Get request pour des raisons de sécurité)
Greg
50

J'ai trouvé quelques problèmes lors de l'implémentation des appels MVC ajax GET avec JQuery qui m'ont causé des maux de tête, donc partager des solutions ici.

  1. Assurez-vous d'inclure le type de données "json" dans l'appel ajax. Cela analysera automatiquement l'objet JSON retourné pour vous (étant donné que le serveur renvoie un json valide).
  2. Inclure le JsonRequestBehavior.AllowGet; sans ce MVC renvoyait une erreur HTTP 500 (avec dataType: jsonspécifié sur le client).
  3. Ajoutez cache: falseà l'appel $ .ajax, sinon vous obtiendrez finalement des réponses HTTP 304 (au lieu des réponses HTTP 200) et le serveur ne traitera pas votre demande.
  4. Enfin, le json est sensible à la casse, donc le boîtier des éléments doit correspondre du côté serveur et du côté client.

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

Exemple de code MVC:

[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
la source
13

Pour répondre à l'autre moitié de la question, vous pouvez appeler:

return PartialView("viewname");

lorsque vous souhaitez renvoyer du HTML partiel. Vous n'aurez qu'à trouver un moyen de décider si la demande veut JSON ou HTML, peut-être en fonction d'une partie / paramètre d'URL.

Brad Wilson
la source
2
alors la question n'est-elle pas restée sans réponse?
Simon_Weaver
2
Cela ne répond pas à la question.
Aaronaught
il recherche une demande ajax pour obtenir le html à l'aide de PartialView nécessite un rafraîchissement de la page à moins que vous ne retourniez la vue à partir d'une méthode d'action en utilisant un appel ajax
Chris McGrath
7

Solution alternative avec cadre d'encodage

Action return json

Manette

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

Page rasoir

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

Action retour html

Manette

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

Page rasoir

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

PartialViewResult et JSONReuslt héritent de la classe de base ActionResult. donc si le type de retour est décidé dynamiquement, déclarer la sortie de la méthode comme 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
la source
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
la source
pourriez-vous ajouter un peu plus d'informations sur ce que cela fait?
RealCheeseLord
Puisque votre code indique qu'il s'agit d'un JSON de retour, le type de retour doit être JsonResult et non ActionResult
noobprogrammer
0

Approche flexible pour produire différentes sorties en fonction de la demande

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

La Request.IsAjaxRequest()méthode est assez simple: elle vérifie simplement les en-têtes HTTP pour la demande entrante pour voir si la valeur de l'en-tête X-Requested-With est XMLHttpRequest, qui est automatiquement ajoutée par la plupart des navigateurs et des frameworks AJAX.

Méthode d'extension personnalisée pour vérifier si la demande concerne json ou non afin que nous puissions l'appeler de n'importe où, tout comme la méthode d'extension Request.IsAjaxRequest ():

using System;
using System.Web;

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

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

Mannan Bahelim
la source