430

我正在尝试创建控制器操作,该操作将根据参数返回 JSON 或部分 html。将结果异步返回到 MVC 页面的最佳方法是什么?

4

11 回答 11

545

在您的操作方法中,返回 Json(object) 以将 JSON 返回到您的页面。

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

然后只需使用 Ajax 调用操作方法。您可以使用 ViewPage 中的一种辅助方法,例如

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

SomeMethod 将是一个 javascript 方法,然后评估返回的 Json 对象。

如果要返回纯字符串,只需使用 ContentResult:

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

ContentResult 默认返回 text/plain 作为其 contentType。
这是可重载的,因此您还可以执行以下操作:

return Content("<xml>This is poorly formatted xml.</xml>", "text/xml");
于 2008-10-22T21:38:33.177 回答
114

I think you should consider the AcceptTypes of the request. I am using it in my current project to return the correct content type as follows.

Your action on the controller can test it as on the request object

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

You can then implement the aspx of the view to cater for the partial xhtml response case.

Then in jQuery you can fetch it passing the type parameter as 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

Hope this helps James

于 2009-09-29T14:38:38.313 回答
82

另一种处理 JSON 数据的好方法是使用 JQuery getJSON 函数。您可以致电

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

Method from the jquery getJSON method by simply...

$.getJSON("../SomeActionMethod", { id: someId },
    function(data) {
        alert(data.foo);
        alert(data.baz);
    }
);
于 2008-10-22T22:08:09.670 回答
53

I found a couple of issues implementing MVC ajax GET calls with JQuery that caused me headaches so sharing solutions here.

  1. Make sure to include the data type "json" in the ajax call. This will automatically parse the returned JSON object for you (given the server returns valid json).
  2. Include the JsonRequestBehavior.AllowGet; without this MVC was returning a HTTP 500 error (with dataType: json specified on the client).
  3. Add cache: false to the $.ajax call, otherwise you will ultimately get HTTP 304 responses (instead of HTTP 200 responses) and the server will not process your request.
  4. Finally, the json is case sensitive, so the casing of the elements needs to match on the server side and client side.

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

Sample 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);
}
于 2013-07-18T22:14:38.307 回答
12

To answer the other half of the question, you can call:

return PartialView("viewname");

when you want to return partial HTML. You'll just have to find some way to decide whether the request wants JSON or HTML, perhaps based on a URL part/parameter.

于 2008-10-23T01:25:39.817 回答
7

Alternative solution with incoding framework

Action return json

Controller

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

Razor page

@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 return html

Controller

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

Razor page

@(Html.When(JqueryBind.InitIncoding)
  .Do()
  .AjaxGet(Url.Action("SomeActionMethod","SomeContoller"))
  .OnSuccess(dsl => dsl.Self().Core().Insert.Html())
  .AsHtmlAttributes()
  .ToDiv())
于 2013-05-06T06:39:03.307 回答
6

You may want to take a look at this very helpful article which covers this very nicely!

Just thought it might help people searching for a good solution to this problem.

http://weblogs.asp.net/rashid/archive/2009/04/15/adaptive-rendering-in-asp-net-mvc.aspx

于 2010-01-12T00:50:22.540 回答
5

PartialViewResult and JSONReuslt inherit from the base class ActionResult. so if return type is decided dynamically declare method output as ActionResult.

public ActionResult DynamicReturnType(string parameter)
        {
            if (parameter == "JSON")
                return Json("<JSON>", JsonRequestBehavior.AllowGet);
            else if (parameter == "PartialView")
                return PartialView("<ViewName>");
            else
                return null;


        }
于 2017-08-08T05:35:38.450 回答
3

For folks who have upgraded to MVC 3 here is a neat way Using MVC3 and Json

于 2011-03-17T10:19:30.670 回答
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);
            }
        }
于 2017-09-07T11:13:25.347 回答
1

Flexible approach to produce different outputs based on the request

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

The Request.IsAjaxRequest() method is quite simple: it merely checks the HTTP headers for the incoming request to see if the value of the X-Requested-With header is XMLHttpRequest, which is automatically appended by most browsers and AJAX frameworks.

Custom extension method to check whether the request is for json or not so that we can call it from anywhere, just like the Request.IsAjaxRequest() extension method:

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

于 2018-03-28T09:35:43.620 回答