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


100

Я початківець веб-програміст, тож пробачте мене, якщо деякі мої "жаргони" невірні. У мене є проект, що використовує 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.
Крейг М

8
Це не вдалося для мене. Мені довелося використовувати JSON.stringify ({...}) для виклику на роботу в MVC5.
Джонкл

Я помітив, що мені потрібно робити те саме, працюючи з контролерами API. Ця відповідь була написана 4 роки тому, до того, як існували контролери API.
Крейг М

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

EDIT: довелося використовувати data: $('input, textarea, select').serialize(),для моєї роботи.
TheGeekZn

Гей, Джазарет !! як передати дату до моделі з третім підходом ??
Гурупрасад Рао

1
Вибачте за затримку @GuruprasadRao Щоб передати дату, ви можете мати дату та час, щоб вона була рядком у коді javascript, і MVC переведе її на об’єкт DateTime.
Джазарет

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/ , синтаксис є досить базовим.


Для використання функції серіалізації я розумію, що кожного члена класу потрібно використовувати в об'єкті форми. Якщо це правильно, я можу бути SOL.
Джон Стоун

1
Ага .. якщо не ви не можете використовувати серіалізацію, то. ви завжди можете маніпулювати DOM, хоча і створити форму з цими елементами та серіалізувати її - але ... швидше за все, буде чистіше просто ввести поля вручну.
Адам Туліпер - MSFT

@TahaRehmanSiddiqui серіалізація дійсно працює в IE, що не працює? Ви отримуєте помилку?
Адам Туліпер - MSFT

кожне майно моєї моделі виходить недійсним
Taha Rehman Siddiqui

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

1
Ви отримуєте всі значення форми вручну? Чому ні data: $("#the-form").serialize()?
Сінджай

1
@Sinjai Мені доведеться ще раз переглянути свій код, але я вважаю, що я теж роблю якусь іншу обробку. ".serialize ()" також буде працювати, якщо вам просто потрібні вхідні значення
blubberbo

Не хвилюйтесь, мені було просто цікаво.
Sinjai
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.