Подтвердить что ты не робот

ASP.NET MVC Как передать объект JSON из представления в контроллер в качестве параметра

У меня есть сложный объект JSON, который отправляется в View без каких-либо проблем (как показано ниже), но я не могу понять, как Serialize эти данные возвращаются к объекту .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 с помощью свойств.

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, но задавался вопросом, есть ли способ сделать это nativly, хотя ASP.NET MVC? Или каковы наилучшие методы для передачи данных таким образом?

4b9b3361

Ответ 1

Изменить

Этот метод больше не понадобится с приходом 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", это будет spring в действие и сопоставляет значения с объектом типа, который вы указываете.

Ответ 2

Вы говорите: "Я не использую формы для манипулирования данными". Но вы делаете POST. Таким образом, вы, фактически, используете форму, даже если она пуста.

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

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

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

  • Вы не передаете JSON на сервер. Вы передаете JSON в jQuery.
  • Связывание модели происходит так же, как это происходит в любом другом случае.

Ответ 3

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

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

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

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

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

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

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

Ответ 4

Существует класс 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.
}

Ответ 5

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

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

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

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

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

Ответ 6

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

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

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

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