Правильный способ обработки вызовов Ajax в ASP.Net MVC 3

При кодировании вызовов Ajax в ASP.Net MVC у нас есть много вариантов в отношении выдачи вызовов, обработки их на сервере и решения проблем и сбоев на клиенте. У некоторых вещей есть правильный ответ, но я не смог найти четких рекомендаций. Итак, из конца в конец, каков правильный способ сделать вызов ajax?

Включая

  • Каков наилучший способ вставить URL-адрес действия для URL-адреса в вызов ajax?
  • Каковы же факторы при выборе JsonBehavior?
  • Каков наилучший способ обработки ошибок на стороне сервера?
    • Если обратный вызов ошибки на стороне клиента() вызван любыми ошибками (например, неожиданным исключением OutOfMemoryException) или только предсказуемыми ошибками (т.е. недопустимым вводом)?
    • Каков наилучший способ экспорта ошибок таким образом, что будет вызван обратный вызов error().
    • Лучший способ обеспечения обратного вызова ошибки - получить правильный код состояния и текст ответа.
    • Если ошибки валидации приводят к ошибке StatusCode или они должны быть частью проверяющего объекта проверки.
  • Каков наилучший способ обработки ошибок на стороне клиента?
    • Если неожиданные ошибки на стороне сервера отображаются так же, как и сводка валидации? Может быть, просто диалог "что-то не так"? Должен ли клиент различать эти два?

Любые другие вещи имеют сильные мнения?

Ответы

Ответ 1

Стиль вопроса/ответа

Каков наилучший способ вставить URL-адрес действия для URL-адреса в вызов Ajax?
Там нет соглашения об этом, и это также во многом зависит от того, как ваш контент был доведен до клиента. Было ли это с помощью представлений/частичных представлений (в этом случае вы могли бы создавать URL-адреса с помощью вспомогательных методов Html/Url или были бы чисто сгенерированы на клиенте (templating и т.д.). Это довольно распространено, что нам просто нужны некоторые обычные HTML-элементы для расширения с помощью поведения Ajax (например, форм, кнопок и ссылок). В этой ситуации лучше всего предоставить правильные URL-адреса, которые мы также можем прочитать из них, и использовать их в наших сценариях (например, href в ссылках). пользователи, на которые указывают вещи. Преобразуем их в запросы GET/POST/DELETE/PUT больше не важно. Я бы посоветовал избегать URL-адресов жесткого кодирования в ваших сценариях, потому что вы можете изменить маршрутизацию или предоставить другие способы с помощью Html помощников, где это возможно, намного лучше с точки зрения обслуживания. При добавлении URL-адресов к элементам, которые их не поддерживают автоматически (атрибут href или src), вы всегда можете добавить их как пользовательские особенно если вы используете атрибут данных (например, data-href или аналогичный). Прочитайте Сообщение Джона Ресига об этом.

Каковы соображения при выборе JsonBehavior?
Лучше всего делать запросы POST, когда вам нужно вернуть Json. В запросах GET вы должны знать о возможных последствиях JSON Hijacking, которые также объясняют, почему вы должны явно указать, что вы разрешаете получать запросы с результатами JSON.

Каков наилучший способ обработки ошибок на стороне сервера?
Лучший способ обработки ошибок сервера (который не может и не должен быть подавлен) - это фактически информировать пользователя об ошибке. Детали этого обычно не важны, так как пользователи не развиты, а говорят, что что-то пошло не так. Особенно, если вы можете предложить им какое-то решение. И с помощью Ajax он делает ставку, чтобы возвращать ошибки как ошибки, которые могут обрабатываться с помощью функций JavaScript-обработчика ошибок. Я написал сообщение в котором подробно описывается весь процесс, а также представлен код, который показывает, как правильно обрабатывать ошибки проверки. Я лично считаю, что возвращение ошибок с успехом неверно. поэтому я этого не делаю. Но это аргументация. Мои действия с контроллером довольно упрощены с помощью кода, который я использую:

[HandleModelStateException]
public ActionResult AddUser(User user)
{
    if (!this.ModelState.IsValid)
    {
        throw new ModelStateException(this.ModelState);
    }
    // process valid data
}

Должен ли вызванный обратный вызов ошибки на стороне клиента любыми ошибками (т.е. неожиданным OutOfMemoryException) или только предсказуемыми ошибками (т.е. недопустимым вводом)?
Как указывалось ранее, сообщения об ошибках должны сообщаться пользователям, когда они получат неожиданные результаты от того, что они инициировали. Не подавляйте ошибки, о которых следует сообщить им. Но не вдавайтесь в подробности. Исключение из памяти является слишком сложным, чтобы объяснить обычным пользователям компьютеров. Сообщите что-то человеческое, дружелюбное и короткое.

Каков наилучший способ экспортировать ошибки таким образом, что будет вызван обратный вызов error().
Посмотрите мой пост в блоге и проверьте код, чтобы узнать, как создавать ошибки, которые обрабатываются функцией error()

Лучший способ обеспечения обратного вызова ошибки - получить правильный код состояния и текст ответа.
Тот же пост в блоге

Если ошибки валидации приводят к ошибке StatusCode или они должны быть частью ответного объекта проверки.
Ошибки проверки являются фактическими предупреждениями по своей природе и должны рассматриваться как таковые. Вот почему вы можете увидеть шаблон проверки положительной формы на некоторых сайтах, которые также сообщают, когда данные действительны, а не просто информируют пользователей о том, что они сделали еще одну ошибку. Ошибки проверки обычно уходят корнями в недопустимый пользовательский интерфейс и недостаточную информацию.

Каков наилучший способ обработки ошибок на стороне клиента?
Это во многом зависит от вашего приложения, но я предлагаю вам следовать проверенным шаблонам, потому что пользователи, скорее всего, узнают упражнение и не будут путать их. Как вы думаете, почему OpenOffice использует почти идентичный интерфейс, как Microsoft Office? Потому что пользователи знают, как это работает, поэтому он с большей вероятностью будет знаком с приложением быстро и безболезненно. Но если вы можете, не обращайтесь с пользователями как с глупыми людьми. Используйте положительную проверку. Некоторые ошибки также должны отображаться как ошибки. Ой. Btw. Я использую ненавязчивую информацию в своем приложении, где информация, такая как успешная операция, сообщается пользователям, но не вторгается в их работу. Через некоторое время он автоматически исчезает. Подобно тому, что делает GMail. Он просто сообщает вам, что почта была отправлена, и эта информация не нуждается в подтверждении.
jQuery ajax() functin поддерживает функции успеха и ошибки, поэтому разумно использовать оба метода. Опять же: возврат ошибок к успеху неверен. Нам не нужны функции ошибок, чем вообще. Мой фильтр действий HandleModelState возвращает ошибки с конкретным кодом ошибки 400, который может быть использован, и его результатом.

$.ajax({
    url: $(this).attr("href"),
    data: someDataObj,
    type: "POST",
    success: function(data){
        // process data
    },
    error: function(xhr, status, err){
        if (xhr.status = 400) {
            // handle my error in xhr.resposeText
        }
        else {
            // handle other errors that are cause by unknown processing
        }
    }
});

Если непредвиденные ошибки на стороне сервера отображаются так же, как сводка проверки? Может быть, просто диалог "что-то не так"? Должен ли клиент различать эти два?
Людям не нравятся большие красные предупреждения. Если что-то является предупреждением по своей природе, его следует рассматривать более дружелюбно, чем фактические ошибки, которые препятствуют правильному функционированию вашего приложения. Валидация, в частности, должна быть очень дружелюбной. Ошибки должны быть подтверждены пользователями, предупреждения, возможно, не должны. Зависит от их характера. Но если они должны быть, то это, вероятно, ошибки.

Надеюсь, это облегчит вам кое-что.

Ответ 2

Каков наилучший способ вставить URL-адрес действия для URL-адреса в вызов ajax?

Лично я использую атрибуты data5 * HTML5 для элементов DOM, которые я AJAXify. Например:

<div id="foo" data-url="@Url.Action("foo")">Foo Bar</div>

а затем:

$('#foo').click(function() {
    var url = $(this).data('url');
    // TODO: perform the AJAX call
});

Конечно, если элемент DOM представляет собой привязку или форму, я бы использовал собственное свойство (действие или href).

Каковы соображения при выборе JsonBehavior?

Нет конкретных соображений. Имейте в виду, что запрос GET может кэшироваться клиентскими браузерами, поэтому вам может потребоваться указать { cache: false } на клиенте. Да и, конечно, AllowGet на сервере для Json.

Каков наилучший способ обработки ошибок на стороне сервера?

Лично я использую FluentValidation.NET для обработки ошибок проверки на моделях просмотра. Также могут возникать ошибки, исходящие из уровня сервиса.

Каков наилучший способ обработки ошибок на стороне клиента?

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

{ error = 'some error message', result: null }

или

{ error = null, result: { foo: 'bar' } }

в зависимости от того, была ли ошибка и на клиенте:

success: function(data) {
    if (data.error != null && data.error != '') {
        // error
    } else {
        // use data.result
    }
}

Я использую обратный вызов error для всего, что является необработанными исключениями на сервере, и в этом случае просто покажите общее сообщение об ошибке. Глобальный обработчик ошибок можно указать с помощью $.ajaxSetup.

Чтобы облегчить создание этих результатов JSON на сервере и DRY мои действия, я использую настраиваемые фильтры действий, которые будут проверять, был ли запрос запрошен AJAX, и если это был запрос AJAX-запроса, были ли ошибки проверки, добавленные в ModelState и если они заменяют результат действия пользовательской ошибкой JsonResult, чтобы обработать случай ошибки.

Ответ 3

Вот как я делаю вещи в некоторых недавних проектах:

1) Я вставляю ajax url в представлении с помощью вызова Url.Action.

2) Jqgrid использует GET для извлечения данных сетки, поэтому в действиях контроллера сетки заливки мне нужно использовать переключатель JsonRequestBehavior.AllowGet в вызове метода Json.

3) Недавно я переключился на Microsoft ненавязчивую проверку на стороне клиента, у которой есть аккуратный метод ModelState.IsValid, который вы можете запустить на стороне сервера в своем действии контроллера, чтобы убедиться, что на серверной стороне также выполняется точная точная проверка без кода дублирования. Потребовалась некоторая работа, связанная с jquery.maskedinput и т.д., Чтобы маскировать/размаскировать данные, здесь статья о том, как получить все это для работы.

4) Что касается отображения стороны клиента с ошибкой, это проблема дизайна, которая должна быть сформулирована заинтересованными сторонами. Лично мне не нравилась проверка рядом с текстовыми полями или сводка проверки в верхней части страницы. Я предпочитаю, чтобы ошибки выскочили на ваше лицо, поэтому я изменил Microsoft jquery.validate.unobtrusive.js, чтобы показать ошибку в всплывающем модальном диалоговом окне. Вы можете увидеть код в приведенном выше решении в файле jquery.validate.unobtrusive.MOD.js(обратите внимание, что моя версия суффикшена ".mod.js" ), и вы можете увидеть диалоговое окно с ошибкой в ​​Site.Master.

Пример действия контроллера:

[HttpPost]
    public ActionResult Index(PersonalInformation model)
    {
        if (ModelState.IsValid)
        {
            // TODO: sell personal information to sleazeballs

            TempData["PersonalInformation"] = model;

            return RedirectToAction("Success");
        }

        // If we got this far, something failed, redisplay form
        Index_Load();
        return View(model);
    }

Надеюсь, что это поможет,

Роберт