Правильный способ использования AJAX Post в jquery для передачи модели из строго типизированного представления MVC3

101

Я начинающий веб-программист, поэтому, пожалуйста, простите меня, если некоторые из моих "жаргонов" неверны. У меня есть проект, использующий ASP.NET с использованием фреймворка MVC3.

Я работаю над представлением администратора, в котором администратор будет изменять список оборудования. Одна из функций - кнопка «обновить», которую я хочу использовать jquery для динамического редактирования записи на веб-странице после отправки сообщения в контроллер MVC.

Я предполагаю, что этот подход «безопасен» в настройках единственного администратора, где существует минимальная проблема, связанная с рассинхронизацией веб-страницы с базой данных.

Я создал строго типизированное представление и надеялся передать данные модели в элемент управления MVC с помощью сообщения AJAX.

В следующем посте я обнаружил что-то похожее на то, что я собираюсь делать: JQuery Ajax и ASP.NET MVC3, вызывающие нулевые параметры.

Я буду использовать образец кода из сообщения выше.

Модель:

public class AddressInfo 
{
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string ZipCode { get; set; }
    public string Country { get; set; }
}

Контроллер:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Check(AddressInfo addressInfo)
    {
        return Json(new { success = true });
    }
}

скрипт в представлении:

<script type="text/javascript">
var ai = {
    Address1: "423 Judy Road",
    Address2: "1001",
    City: "New York",
    State: "NY",
    ZipCode: "10301",
    Country: "USA"
};

$.ajax({
    url: '/home/check',
    type: 'POST',
    data: JSON.stringify(ai),
    contentType: 'application/json; charset=utf-8',
    success: function (data.success) {
        alert(data);
    },
    error: function () {
        alert("error");
    }
});
</script>

У меня еще не было возможности воспользоваться этим. Но мне было интересно, был ли это «лучший» метод передачи данных модели обратно в элемент управления MVC с использованием AJAX?

Следует ли мне беспокоиться о раскрытии информации о модели?

Джон Стоун
источник

Ответы:

72

Вы можете пропустить объявление var и строку. В противном случае это будет работать нормально.

$.ajax({
    url: '/home/check',
    type: 'POST',
    data: {
        Address1: "423 Judy Road",
        Address2: "1001",
        City: "New York",
        State: "NY",
        ZipCode: "10301",
        Country: "USA"
    },
    contentType: 'application/json; charset=utf-8',
    success: function (data) {
        alert(data.success);
    },
    error: function () {
        alert("error");
    }
});
Крейг М
источник
Спасибо, что указали на небольшую корректировку. Есть ли какие-то опасения по поводу раскрытия структуры модели с точки зрения безопасности?
Джон Стоун
Для меня ничто не бросается в глаза как проблема безопасности. Если вас это действительно беспокоит, вы всегда можете создать привязку пользовательской модели на стороне mvc.
Craig M
8
Для меня это не удалось. Мне пришлось использовать JSON.stringify ({...}), чтобы вызов работал в MVC5.
Johncl
Я заметил, что мне нужно делать то же самое при работе с контроллерами API. Этот ответ был написан 4 года назад, до того, как появились контроллеры API.
Craig M,
1
Черт возьми, у меня был dataType вместо contentType, который всегда меня понимает !!
Фил
175

Я нашел 3 способа реализовать это:

Класс C #:

public class AddressInfo {
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string ZipCode { get; set; }
    public string Country { get; set; }
}

Действие:

[HttpPost]
public ActionResult Check(AddressInfo addressInfo)
{
    return Json(new { success = true });
}

JavaScript вы можете сделать это тремя способами:

1) Строка запроса:

$.ajax({
    url: '/en/Home/Check',
    data: $('#form').serialize(),
    type: 'POST',
});

Данные здесь - это строка.

"Address1=blah&Address2=blah&City=blah&State=blah&ZipCode=blah&Country=blah"

2) Массив объектов:

$.ajax({
    url: '/en/Home/Check',
    data: $('#form').serializeArray(),
    type: 'POST',
});

Данные здесь представляют собой массив пар ключ / значение:

=[{name: 'Address1', value: 'blah'}, {name: 'Address2', value: 'blah'}, {name: 'City', value: 'blah'}, {name: 'State', value: 'blah'}, {name: 'ZipCode', value: 'blah'}, {name: 'Country', value: 'blah'}]

3) JSON:

$.ajax({
      url: '/en/Home/Check',
      data: JSON.stringify({ addressInfo:{//missing brackets
          Address1: $('#address1').val(),
          Address2: $('#address2').val(),
          City: $('#City').val(),
          State: $('#State').val(),
          ZipCode: $('#ZipCode').val()}}),
      type: 'POST',
      contentType: 'application/json; charset=utf-8'
});

Данные здесь представляют собой сериализованную строку JSON. Обратите внимание, что имя должно совпадать с именем параметра на сервере !!

='{"addressInfo":{"Address1":"blah","Address2":"blah","City":"blah","State":"blah", "ZipCode", "blah", "Country", "blah"}}'
Джазарет
источник
1
Только что наткнулся на этот отличный, исчерпывающий ответ, который разрешил вопросы, о которых я еще не знал. +1, спасибо!
SeanKilleen
№2 было тем, что я искал. Это должен быть ответ.
TheGeekZn
РЕДАКТИРОВАТЬ: пришлось использовать data: $('input, textarea, select').serialize(),для моей работы.
TheGeekZn
Привет, Джазарет !! как передать дату модели с 3-м подходом ??
Гурупрасад Рао,
1
Извините за задержку @GuruprasadRao Чтобы передать дату, вы можете указать дату и время в виде строки в коде javascript, и MVC преобразует ее в объект DateTime.
Jazaret 03
12

У меня это сработало так:

$.post("/Controller/Action", $("#form").serialize(), function(json) {       
        // handle response
}, "json");

[HttpPost]
public ActionResult TV(MyModel id)
{
    return Json(new { success = true });
}
Санчитос
источник
8

то, что у вас есть, в порядке - однако, чтобы сэкономить на вводе, вы можете просто использовать для своих данных

данные: $ ('# formId'). serialize ()

см. http://www.ryancoughlin.com/2009/05/04/how-to-use-jquery-to-serialize-ajax-forms/ для подробностей, синтаксис довольно простой.

Адам Тюлипер - MSFT
источник
Насколько я понимаю, чтобы использовать функцию сериализации, каждый член класса должен использоваться в объекте формы. Если это так, я могу быть СОЛОМ.
Джон Стоун
1
ах, да ... если нет, тогда сериализовать нельзя. вы всегда можете манипулировать DOM и создать форму с этими элементами и сериализовать ее - но ... вероятно, было бы проще просто ввести поля вручную.
Адам Тюлипер - MSFT
@TahaRehmanSiddiqui serialize действительно работает в IE, что не работает? Вы получаете сообщение об ошибке?
Адам Тюлипер - MSFT
каждое свойство моей модели выходит за рамки нуля
Таха Рехман Сиддики
@TahaRehmanSiddiqui соответствует ли «имя» полей вашей формы именам свойств вашей модели?
MongooseNX
0

Если вы используете MVC 5, прочтите это решение!

Я знаю, что вопрос конкретно касается MVC 3, но я наткнулся на эту страницу с MVC 5 и хотел опубликовать решение для кого-либо еще в моей ситуации. Я пробовал вышеуказанные решения, но они не сработали для меня, фильтр действий не был достигнут, и я не мог понять, почему. Я использую версию 5 в своем проекте и в итоге получил следующий фильтр действий:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Filters;

namespace SydHeller.Filters
{
    public class ValidateJSONAntiForgeryHeader : FilterAttribute, IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationContext filterContext)
        {
            string clientToken = filterContext.RequestContext.HttpContext.Request.Headers.Get(KEY_NAME);
            if (clientToken == null)
            {
                throw new HttpAntiForgeryException(string.Format("Header does not contain {0}", KEY_NAME));
            }

            string serverToken = filterContext.HttpContext.Request.Cookies.Get(KEY_NAME).Value;
            if (serverToken == null)
            {
                throw new HttpAntiForgeryException(string.Format("Cookies does not contain {0}", KEY_NAME));
            }

            System.Web.Helpers.AntiForgery.Validate(serverToken, clientToken);
        }

        private const string KEY_NAME = "__RequestVerificationToken";
    }
}

- Обратите внимание на using System.Web.Mvcиusing System.Web.Mvc.Filters , а не на httpбиблиотеки (я думаю, что это одна из вещей, которые изменились с MVC v5. -

Затем просто примените фильтр [ValidateJSONAntiForgeryHeader] к своему действию (или контроллеру), и он должен вызываться правильно.

На моей странице макета прямо выше у </body>меня есть@AntiForgery.GetHtml();

Наконец, на моей странице Razor я выполняю вызов ajax следующим образом:

var formForgeryToken = $('input[name="__RequestVerificationToken"]').val();

$.ajax({
  type: "POST",
  url: serviceURL,
  contentType: "application/json; charset=utf-8",
  dataType: "json",
  data: requestData,
  headers: {
     "__RequestVerificationToken": formForgeryToken
  },
     success: crimeDataSuccessFunc,
     error: crimeDataErrorFunc
});
Blubberbo
источник
1
Вы извлекаете все значения формы вручную? А почему бы и нет data: $("#the-form").serialize()?
Sinjai
1
@Sinjai Мне бы снова пришлось взглянуть на свой код, но я считаю, что я занимаюсь и другой обработкой. ".serialize ()" также будет работать, если вам просто нужны входные значения
blubberbo
Не беспокойтесь, мне просто было любопытно.
Sinjai