ASP.NET MVC Как передать объект JSON из представления в контроллер в качестве параметра - PullRequest
52 голосов
/ 18 февраля 2009

У меня есть сложный объект JSON, который отправляется в View без каких-либо проблем (как показано ниже), но я не могу понять, как сериализировать эти данные обратно в объект .NET, когда они передаются обратно в контроллер через вызов AJAX , Детали различных частей ниже.

   var ObjectA = {
        "Name": 1,
        "Starting": new Date(1221644506800),

        "Timeline": [
            {
                "StartTime": new Date(1221644506800),
                "GoesFor": 200

            }
            ,
            {
                "StartTime": new Date(1221644506800),
                "GoesFor": 100

            }

        ]
    };

Я не уверен, как этот объект может быть передан в метод контроллера, у меня есть этот метод ниже, где объект Timelines отражает вышеупомянутый объект JS, используя Properties.

public JsonResult Save(Timelines person)

Я использую jQuery:

        var encoded = $.toJSON(SessionSchedule);

        $.ajax({
            url: "/Timeline/Save",
            type: "POST",
            dataType: 'json',
            data: encoded,
            contentType: "application/json; charset=utf-8",
            beforeSend: function() { $("#saveStatus").html("Saving").show(); },
            success: function(result) {
                alert(result.Result);
                $("#saveStatus").html(result.Result).show();
            }
        });

Я видел этот вопрос, который похож, но не совсем так, как я не использую формы для манипулирования данными. Как передать сложный тип с помощью json контроллеру ASP.NET MVC

Я также видел ссылки на использование JsonFilter для десериализации JSON вручную, но мне было интересно, есть ли способ сделать это нативно, хотя ASP.NET MVC? Или каков наилучший способ передачи данных таким образом?

Ответы [ 6 ]

50 голосов
/ 04 марта 2009

Изменить:

Этот метод больше не требуется с появлением MVC 3, так как он будет обрабатываться автоматически - http://weblogs.asp.net/scottgu/archive/2010/07/27/introducing-asp-net-mvc-3-preview-1.aspx

<ч />

Вы можете использовать этот ObjectFilter:

    public class ObjectFilter : ActionFilterAttribute {

    public string Param { get; set; }
    public Type RootType { get; set; }

    public override void OnActionExecuting(ActionExecutingContext filterContext) {
        if ((filterContext.HttpContext.Request.ContentType ?? string.Empty).Contains("application/json")) {
            object o =
            new DataContractJsonSerializer(RootType).ReadObject(filterContext.HttpContext.Request.InputStream);
            filterContext.ActionParameters[Param] = o;
        }

    }
}

Затем вы можете применить его к своим методам контроллера следующим образом:

    [ObjectFilter(Param = "postdata", RootType = typeof(ObjectToSerializeTo))]
    public JsonResult ControllerMethod(ObjectToSerializeTo postdata) { ... }

Таким образом, в основном, если тип содержимого публикации «application / json», это вступит в действие и отобразит значения в указанный вами тип объекта.

12 голосов
/ 18 февраля 2009

Вы говорите: «Я не использую формы для манипулирования данными». Но вы делаете ПОЧТУ. Следовательно, вы фактически используете форму, даже если она пустая.

$. Ajax dataType сообщает jQuery, какой тип сервера будет возвращать , а не то, что вы передаете. POST может только пройти форму. jQuery преобразует данные в пары ключ / значение и передает их в виде строки запроса. Из документов:

Данные для отправки на сервер. это преобразуется в строку запроса, если нет уже строка Это добавлено к URL для GET-запросов. Смотрите processData возможность предотвратить это автоматическое обработка. Объект должен быть ключ / значение пар. Если значение является массивом, jQuery сериализует несколько значений с одинаковыми ключ т.е. {foo: ["bar1", "bar2"]} становится '& foo = bar1 & foo = bar2'.

Таким образом:

  1. Вы не передаете JSON на сервер. Вы передаете JSON в jQuery.
  2. Привязка модели происходит так же, как и в любом другом случае.
10 голосов
/ 07 апреля 2011

Другой дубль с простым плагином jQuery

Несмотря на то, что ответы на этот вопрос давно назрели, но я все еще публикую хорошее решение, с которым я пришел некоторое время назад, и упрощает отправку сложного JSON на контроллер Asp.net MVC действия, поэтому они привязаны к модели с любыми параметрами сильного типа.

Этот плагин также поддерживает даты , поэтому они без проблем преобразуются в DateTime.

Все подробности можно найти в моем блоге , где я изучаю проблему и предоставляю код, необходимый для ее решения.

Все, что вам нужно сделать, это использовать этот плагин на стороне клиента. Запрос Ajax будет выглядеть так:

$.ajax({
    type: "POST",
    url: "SomeURL",
    data: $.toDictionary(yourComplexJSONobject),
    success: function() { ... },
    error: function() { ... }
});

Но это только часть всей проблемы. Теперь мы можем отправить сложный JSON обратно на сервер, но, поскольку это будет модель, связанная со сложным типом, который может иметь атрибуты проверки свойств, вещи могут потерпеть неудачу в этот момент. У меня есть решение для этого . Мое решение использует функциональные возможности jQuery Ajax, в которых результаты могут быть успешными или ошибочными (как показано в верхнем коде). Поэтому, когда валидация завершится неудачей, error будет вызвана функция, как и должно быть.

4 голосов
/ 18 февраля 2009

Существует класс JavaScriptSerializer , который вы также можете использовать. Это позволит вам десериализовать JSON в объект .NET. Существует универсальный Deserialize<T>, хотя вам потребуется, чтобы объект .NET имел подпись, аналогичную подписи javascript. Кроме того, есть также метод DeserializeObject, который просто делает простой object. Затем вы можете использовать отражение, чтобы получить нужные вам свойства.

Если ваш контроллер принимает FormCollection, и вы ничего не добавили к data, json должен быть в form[0]:

public ActionResult Save(FormCollection forms) {
  string json = forms[0];
  // do your thing here.
}
2 голосов
/ 10 ноября 2010

Этот ответ является продолжением ответа DaRKoN_, в котором использовался объектный фильтр:

[ObjectFilter(Param = "postdata", RootType = typeof(ObjectToSerializeTo))]
    public JsonResult ControllerMethod(ObjectToSerializeTo postdata) { ... }

У меня была проблема с выяснением, как отправить несколько параметров в метод действия, и чтобы один из них был объектом json, а другой - простой строкой. Я новичок в MVC, и я только что забыл, что я уже решил эту проблему с не-ajaxed представлениями.

Что бы я сделал, если бы мне понадобились, скажем, два разных объекта на виде. Я хотел бы создать класс ViewModel. Скажем, мне нужен объект person и объект address, я бы сделал следующее:

public class SomeViewModel()
{
     public Person Person { get; set; }
     public Address Address { get; set; }
}

Тогда я бы привязал представление к SomeViewModel. Вы можете сделать то же самое с JSON.

[ObjectFilter(Param = "jsonViewModel", RootType = typeof(JsonViewModel))] // Don't forget to add the object filter class in DaRKoN_'s answer.
public JsonResult doJsonStuff(JsonViewModel jsonViewModel)
{
     Person p = jsonViewModel.Person;
     Address a = jsonViewModel.Address;
     // Do stuff
     jsonViewModel.Person = p;
     jsonViewModel.Address = a;
     return Json(jsonViewModel);
}

Тогда в представлении вы можете использовать простой вызов с JQuery, например:

var json = { 
    Person: { Name: "John Doe", Sex: "Male", Age: 23 }, 
    Address: { Street: "123 fk st.", City: "Redmond", State: "Washington" }
};

$.ajax({
     url: 'home/doJsonStuff',
     type: 'POST',
     contentType: 'application/json',
     dataType: 'json',
     data: JSON.stringify(json), //You'll need to reference json2.js
     success: function (response)
     {
          var person = response.Person;
          var address = response.Address;
     }
});
1 голос
/ 19 апреля 2011

в ответ на комментарий Дэна выше:

Я использую этот метод для реализации то же самое, но я почему-то я получаю исключение на Метод ReadObject: «Ожидаемый элемент 'root' из пространства имен '' .. Обнаружено 'None' с именем '', пространством имен ''. " Есть идеи почему? - Дэн Эпплиард 6 апреля '10 в 17: 57

У меня была такая же проблема (MVC 3 build 3.0.11209.0), и пост ниже решил ее для меня. По сути, сериализатор json пытается прочитать поток, который не находится в начале, поэтому изменение положения потока на 0 фиксирует его ...

http://nali.org/asp-net-mvc-expecting-element-root-from-namespace-encountered-none-with-name-namespace/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...