Платформа проверки ASP.NET MVC при публикации через jquery $ .ajax?

Есть много очень хороших сообщений и объяснений, как реализовать проверку с помощью ASP.NET MVC, и я предпочитаю одно из них:

Однако мне очень нравится вызывать ActionMethods через метод jquery $ .ajax. Одна из причин, по которой я хочу использовать $ .ajax, заключается в том, что будет много частичных представлений, загружаемых на страницу динамически (даже форма для создания объекта) через вызовы $ .ajax, и я не могу просто вернуть представление - Я потеряю весь динамически загружаемый контент.

Чтобы дать вам лучшее представление о проблеме, я опубликую простой код, чтобы объяснить, как я хотел бы вызывать действия контроллеров и обрабатывать ответы в клиенте, код jquery.

Контроллеры ActionMethod:

    public ActionResult CreateCustomer(string name, string accountNumber)
    {
        try
        {
            CustomerService.InsertCustomer(name, accountNumber);

            return Json(new ActionInfo()
            {
                Success = true,
                Message = "Customer Is Successfully Created"
            });

        }
        catch (Exception ex)
        {
            return Json(new ActionInfo()
            {
                Success = false,
                Message = ex.Message
            });
        }
    }

Вызов и обработка в клиентском коде:

$.ajax({
type: "POST",
url: $form.attr('action'),// /MyController/CreateCustomer
data: $form.serialize(),
error: HandleUnespectedError,
dataType: "json",
success: function(response) {

    if (response.Success)
        alert("Success: " + response.Message);
    else
        alert("Error: " + response.Message);
}});

Есть ли хороший способ заставить некоторые из этих платформ проверки работать так, как мне нужно? Я знаю, что могу добавлять ошибки проверки в ActionInfo, а затем обрабатывать их в клиенте, но это уже было бы я полагаю, построение моей единственной проверки.


person Misha N.    schedule 09.10.2009    source источник


Ответы (2)


У меня был большой успех при проверке через AJAX с использованием атрибутов аннотаций данных. Чтобы проверить достоверность ваших данных, вам нужно будет использовать свойство контроллера ModelState, которое имеет собственное свойство, называемое IsValid. Я настоятельно рекомендую взглянуть на руководство по проверке атрибутов аннотаций данных с официального сайта ASP.NET MVC.

Во-первых, вы захотите изменить действие вашего контроллера, чтобы он принимал объект модели в качестве параметра, а не отдельное имя и номер учетной записи. Это значительно упростит выполнение проверки, которую я продемонстрирую ниже. Исходя из вашего примера, я могу предположить, что ваш объект модели называется или будет называться Customer. У вас может быть следующий код для определения объекта модели и действия вашего контроллера ...

// model object
public class Customer
{
  public Int32 Id {get; set;}
  public String Name {get; set;}
  public String AccountNumber {get; set;}
}

// controller
public class CustomerController : Controller
{
  public ActionResult CreateCustomer( [Bind(Exclude = "Id")] Customer customer )
  {
     // controller action code
  }
}


Убедитесь, что имена полей формы соответствуют именам свойств объекта Customer, чтобы ASP.NET MVC мог автоматически связывать их. Атрибут «Bind» в этом случае сообщает ASP.NET MVC игнорировать свойство «Id» класса Customer при привязке полей формы к свойствам модели. Поскольку это новый клиент, у нас еще нет идентификатора, поэтому мы можем спокойно оставить идентификатор без значения по умолчанию и оставить уровень данных, чтобы выяснить, как лучше его сгенерировать.

После того, как контроллер построил объект модели для метода действия, его достоверность можно легко проверить с помощью свойства ModelState.IsValid. Как и следовало ожидать, он вернет true, если свойства модели допустимы, или false, если одно или несколько свойств недействительны.

Из исходного вопроса кажется, что метод CustomerService.InsertCustomer выдает исключения при сбое проверки. Это совершенно не нужно. InsertCustomer должен выполнить только те операции с данными, которые необходимы для вставки новой записи. Если вы не хотите абстрагироваться от особых исключений реализации, таких как SqlException, InsertCustomer на самом деле не нужно перехватывать или генерировать какие-либо исключения, но, скорее всего, он может просто позволить любым исключениям пузыриться до контроллера (или того, кто может быть вызывающим).

Конечным результатом всего этого может быть действие контроллера, которое выглядит следующим образом:

public ActionResult CreateCustomer( [Bind(Exclude = "Id")] Customer customer )
{
  // model is invalid
  if (!ModelState.IsValid)
  {
    return Json(new ActionInfo()
    {
      Success = false,
      Message = "Validation failed" // you will probably want a more robust message :-)
    });
  }

  // service method accepts a Customer object rather than arbitrary strings  
  CustomerService.InsertCustomer(customer);

  return Json(new ActionInfo()
  {
    Success = true,
    Message = "Customer created successfully."
  });

}


Если вы хотите сообщить о неожиданных ошибках, например об исключениях, связанных с базой данных, вы, безусловно, можете добавить блок try / catch вокруг вызова InsertCustomer и вернуть необходимый результат для отображения сообщения об ошибке обратно клиенту.

person Justin Holzer    schedule 15.10.2009
comment
Эй, тёдуд! Большое спасибо за усилия :) Я полностью согласен с вами в отношении сущности Customer для привязки (хотел сделать это, не знаю, почему я поставил метод с простыми параметрами) и для обработки исключений наверняка. С помощью xVal я могу легко реализовать проверку клиента, и если кто-то ее избегает, я пойму ее в действии. Но как в этом случае представить сообщения проверки рядом с полями? - person Misha N.; 15.10.2009
comment
Для этого вам нужно вернуть частичное представление, а не JSON из действия вашего контроллера. В частичном представлении вы должны использовать вспомогательный метод Html.ValidationMessage () для отображения сообщения об ошибке для каждого поля. Сообщения об ошибках на уровне поля, которые были сгенерированы вашими атрибутами примечаний к данным, доступны вашему контроллеру через свойство ModelState. Например, чтобы получить первое сообщение об ошибке для поля с именем name, вы должны получить его через ModelState["Name"].Errors[0].ErrorMessage. Также обратите внимание на метод Ajax.BeginForm. Я использовал его с большим успехом в прошлом. - person Justin Holzer; 15.10.2009
comment
Это то, что я понял, либо я верну JSON, либо частичное представление, и это то, что мне не нравится ... Однако я посмотрю, как с этим справиться, используя MS, встроенные в функции Ajax, хотя мои хотелось бы этого избежать :) Спасибо - person Misha N.; 16.10.2009
comment
Не уверен, почему вы хотите этого избежать, но я уверен, что у вас есть свои причины. Я засвидетельствую, что использование Ajax.BeginForm с частичными представлениями для меня хорошо сработало. Я считаю, что он в любом случае использует JQuery под капотом, хотя я могу ошибаться в этом. - person Justin Holzer; 16.10.2009

Прошло больше года после того, как вы задали свой вопрос, но я рассмотрел проверку на стороне сервера с помощью вызовов Ajax в моем запись в блоге, которая может вас заинтересовать. Я вижу, что вы возвращаете неудачные результаты как успешные HTTP-вызовы. Я поступил иначе (думаю, это более правильно, поскольку $.ajax имеет возможность success и error ответа). И ваш конкретный пример - прекрасный пример, который можно реализовать с помощью функций, которые я объясняю в своем сообщении в блоге.

По сути, вместо того, чтобы всегда возвращать успешный ответ (но со свойствами, установленными, чтобы сообщить клиенту, что обработка на стороне сервера не удалась), я скорее создаю исключение на сервере и обрабатываю его соответствующим образом на клиенте. Я использую собственный класс ModelStateException вместе с фильтром действий HandleModelStateException.

person Robert Koritnik    schedule 27.11.2010