Действия контроллера ASP.NET MVC, возвращающие JSON или частичный HTML

Я пытаюсь создать действия контроллера, которые будут возвращать либо JSON, либо частичный html в зависимости от параметра. Как лучше всего получить результат, возвращаемый на страницу MVC асинхронно?


person NathanD    schedule 22.10.2008    source источник


Ответы (11)


В вашем методе действия верните Json (объект), чтобы вернуть 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");
person Haacked    schedule 22.10.2008
comment
прости, Фил! это на самом деле не отвечает на вопрос, не так ли? это определенно полезно, но, как говорит Брэд, вам нужно каким-то образом узнать, что они просят, и вернуть результат соответственно. - person Simon_Weaver; 27.01.2009
comment
см. мой несколько связанный (ну тот, который привел меня сюда) вопрос на stackoverflow.com/questions/482363/ - person Simon_Weaver; 27.01.2009
comment
если найдете ответ, дайте ссылку в самом вопросе. Также я не думаю, что проверять это, потому что ответ правильный. - person Cherian; 18.02.2009
comment
stackoverflow.com/questions/320291/ связан - person Cherian; 18.02.2009
comment
Каково полное имя этого класса Json? - person Josh Withee; 19.12.2018
comment
@Haacked: Я прочитал ваш блог Json Hijacking, не могли бы вы объяснить, почему изменение Get на Post предотвращает атаку? Я задал этот вопрос здесь: stackoverflow.com/questions/61995800/ - person Hooman Bahreini; 28.05.2020
comment
Потому что атака зависит от злоумышленника, использующего тег скрипта с src, установленным для вашего кода. Если ваш код отвечает только на POST, он не будет загружен в чей-то тег скрипта. - person Haacked; 29.05.2020

Я думаю, вам следует рассмотреть AcceptTypes запроса. Я использую его в своем текущем проекте, чтобы вернуть правильный тип контента, как показано ниже.

Ваше действие на контроллере может проверить его, как на объекте запроса

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

Затем вы можете реализовать aspx представления, чтобы удовлетворить случай частичного ответа xhtml.

Затем в jQuery вы можете получить его, передав параметр типа как 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

Надеюсь, это поможет Джеймсу

person James Green    schedule 29.09.2009
comment
Спасибо, Джеймс, это может быть очень полезно для создания своего рода веб-сайта и REST API с использованием одних и тех же действий контроллера. - person NathanD; 01.10.2009
comment
Если у меня много таких методов в моем контроллере, могу ли я сделать это в более общем плане? - person Seph; 10.06.2012
comment
В каком пространстве имен находится класс Json? Какая зависимость для project.json? заранее спасибо - person Andrei; 23.07.2016
comment
Это класс JsonResult из System.Web.Mvc (в System.Web.Mvc.dll) @Andrei - person James Green; 26.07.2016
comment
Спасибо, нашел. Может быть, обновить ответ, чтобы отразить новый API? Кстати, я использую ядро ​​dotnet, где это Microsoft.AspNetCore.Mvc.JsonResult. - person Andrei; 26.07.2016

Еще один хороший способ работать с данными JSON - использовать функцию JQuery getJSON. Вы можете позвонить в

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

Метод из метода jquery getJSON просто ...

$.getJSON("../SomeActionMethod", { id: someId },
    function(data) {
        alert(data.foo);
        alert(data.baz);
    }
);
person SaaS Developer    schedule 22.10.2008
comment
Это вообще не отвечает на вопрос. - person Aaronaught; 14.09.2011
comment
@Aaronaught На самом деле первая часть return Json(new {foo="bar", baz="Blech"}); делает! - person SparK; 21.03.2016
comment
Также рассмотрите $ .post stackoverflow.com/questions/751218/ (ASP.Net MVC по умолчанию отключил запросы JSON Get по соображениям безопасности) - person Greg; 24.04.2018

Я обнаружил пару проблем с реализацией вызовов MVC ajax GET с помощью JQuery, которые вызвали у меня головные боли, поэтому поделитесь решениями здесь.

  1. Обязательно укажите тип данных json в вызове ajax. Это автоматически проанализирует возвращенный объект JSON (при условии, что сервер возвращает действительный json).
  2. Включите JsonRequestBehavior.AllowGet; без этого MVC возвращал ошибку HTTP 500 (с dataType: json, указанным на клиенте).
  3. Добавьте cache: false к вызову $ .ajax, иначе вы в конечном итоге получите ответы HTTP 304 (вместо ответов HTTP 200), и сервер не обработает ваш запрос.
  4. Наконец, json чувствителен к регистру, поэтому корпус элементов должен совпадать на стороне сервера и на стороне клиента.

Пример 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);
  }
});

Пример кода 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);
}
person Shane    schedule 18.07.2013

Чтобы ответить на вторую половину вопроса, вы можете позвонить:

return PartialView("viewname");

когда вы хотите вернуть частичный HTML. Вам просто нужно найти способ решить, нужен ли запрос JSON или HTML, возможно, на основе части / параметра URL.

person Brad Wilson    schedule 23.10.2008
comment
так разве вопрос не остался без ответа? - person Simon_Weaver; 27.01.2009
comment
Это не ответ на вопрос. - person Aaronaught; 14.09.2011
comment
он ищет запрос ajax для получения html с помощью PartialView, требуется обновление страницы, если вы не возвращаете представление из метода действия с помощью вызова ajax - person Chris McGrath; 03.04.2012

Альтернативное решение с фреймворком кодирования

Возврат действия json

Контроллер

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

Страница Razor

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

Действие return html

Контроллер

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

Страница Razor

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

Возможно, вы захотите взглянуть на эту очень полезную статью, которая очень хорошо освещает это!

Просто подумал, что это может помочь людям, которые ищут хорошее решение этой проблемы.

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

person Paul Hinett    schedule 12.01.2010

PartialViewResult и JSONReuslt наследуются от базового класса ActionResult. поэтому, если тип возвращаемого значения определен, динамически объявляйте вывод метода как ActionResult.

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


        }
person Anil Vaddepally    schedule 08.08.2017

Для тех, кто перешел на MVC 3, есть удобный способ Использование MVC3 и Json

person Sarath    schedule 17.03.2011
comment
вы также можете использовать ту же технику, что и в этой статье в MVC 2 - person longhairedsi; 13.04.2011

Гибкий подход для получения различных результатов в зависимости от запроса

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

Метод Request.IsAjaxRequest() довольно прост: он просто проверяет заголовки HTTP для входящего запроса, чтобы узнать, равно ли значение заголовка X-Requested-With XMLHttpRequest, который автоматически добавляется большинством браузеров и фреймворков AJAX.

Пользовательский метод расширения, чтобы проверить, предназначен ли запрос для json или нет, чтобы мы могли вызывать его из любого места, точно так же, как метод расширения Request.IsAjaxRequest ():

using System;
using System.Web;

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

Источник: https://www.safaribooksonline.com/library/view/programming-aspnet-mvc/9781449321932/ch06.html#_javascript_rendering.

person Mannan Bahelim    schedule 28.03.2018

person    schedule
comment
не могли бы вы добавить немного дополнительной информации о том, что это делает? - person RealCheeseLord; 07.09.2017
comment
Поскольку ваш код показывает, что он возвращает JSON, тип возврата должен быть JsonResult, а не ActionResult - person noobprogrammer; 06.05.2020