Лучшие практики для MVC, jQuery и Ошибок из-за неправильного обращения

Действительно просто ответ для добавления ссылки, которая я удивлен, еще не был упомянут: запись в блоге Lippert Eric на "Массивы, которые рассматривают несколько вредными".

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

18
задан Damien 6 August 2009 в 11:01
поделиться

6 ответов

Вызов AJAX не является обновлением страницы, поэтому я определенно не буду перенаправлять на 403, 404 и т. Д. Я бы отобразил диалоговое окно на стороне клиента, соответствующим образом объясняя неожиданный результат запроса. Ваш контроллер может возвращать результаты неудачной проверки вызову AJAX аналогично тому, как он возвращает данные об успешном завершении, поэтому в вашем диалоговом окне также может отображаться все, что требуется в этом сценарии.

3
ответ дан 30 November 2019 в 09:38
поделиться

Сохраняйте два представления ошибок, одно для нормального (полного) отображения страницы, а другое, которое просто отображает ошибки в XML или JSON.

Никогда не проверяйте на стороне клиента, поскольку пользователь может легко его обойти. Для проверки в реальном времени просто запустите AJAX-запрос к серверу для проверки, таким образом вы напишете код проверки один раз.

0
ответ дан 30 November 2019 в 09:38
поделиться

Мы никогда не перенаправляем (зачем заставлять пользователя многократно нажимать кнопку «назад», если он не понимает, что нужно ввести в определенное поле?), Мы отображаем ошибки на месте , будь то AJAX или нет (расположение `` пятна '' на странице полностью зависит от вас, для всех запросов AJAX мы просто показываем цветную полосу вверху страницы, точно так же, как stackoverflow для новичков, только наш не выталкивайте остальное содержимое вниз).

Что касается проверки формы, вы можете выполнять ее как на стороне сервера, так и на стороне клиента. Мы всегда стараемся отображать ошибки на стороне сервера в верхней части формы в отдельном контейнере, на стороне клиента - прямо рядом с соответствующим полем при отправке. После того, как страница возвращается с сервера с ошибками проверки на стороне сервера, пользователь сначала будет видеть только те, которые находятся на стороне сервера, поэтому дублирования не будет.

0
ответ дан 30 November 2019 в 09:38
поделиться

У вас есть советы о том, как сделать действия контроллера, которые хорошо работают при обычном вызове через Ajax? Это неприятная проблема при написании методов действий.

Да, да. Мы также работали над аналогичной проблемой - мы хотели, чтобы приложение имело набор форм, которые обычно вызывались бы через ajax, но могли обрабатываться нормально. Более того, мы не Я не хочу, чтобы в javascript висела куча повторяющейся логики. Во всяком случае, метод, который мы придумали, заключался в использовании пары ActionFilterAttributes для перехвата форм, а затем небольшого JavaScript для подключения формы для обработки ajax.

Во-первых, для запроса ajax мы просто хотели поменять местами главные страницы:

    private readonly string masterToReplace;

    /// <summary>
    /// Initializes an Ajax Master Page Switcharoo
    /// </summary>
    /// <param name="ajaxMaster">Master page for ajax requests</param>
    public AjaxMasterPageInjectorAttribute(string ajaxMaster)
    {
        this.masterToReplace = ajaxMaster;
    }

    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        if (!filterContext.HttpContext.Request.IsAjaxRequest() || !(filterContext.Result is ViewResult)) return;
        ViewResult vr = (ViewResult) filterContext.Result;
        vr.MasterName = masterToReplace;
    }
}

На стороне возврата мы используем xVal для проверки на стороне клиента, поэтому не следует особо мешать неверным данным, но еще можно получить. Для этого мы просто используем обычную проверку и заставляем метод aciton возвращать форму с сообщениями проверки. Успешные публикации обычно награждаются редиректами. В любом случае, мы делаем небольшую инъекцию json для случая успеха:

/// <summary>
/// Intercepts the response and stuffs in Json commands if the request is ajax and the request returns a RedirectToRoute result.
/// </summary>
public class JsonUpdateInterceptorAttribute : ActionFilterAttribute 
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAjaxRequest())
        {
            JsonResult jr = new JsonResult();
            if (filterContext.Result is RedirectResult)
            {
                RedirectResult rr = (RedirectResult) filterContext.Result;
                jr.Data = new {command = "redirect", content = rr.Url};
            }
            if (filterContext.Result is RedirectToRouteResult)
            {
                RedirectToRouteResult rrr = (RedirectToRouteResult) filterContext.Result;
                VirtualPathData vpd = RouteTable.Routes.GetVirtualPath(filterContext.RequestContext, rrr.RouteValues);
                jr.Data = new {command = "redirect", content = vpd.VirtualPath};
            }
            if (jr.Data != null)
            {
                filterContext.Result = jr;
            }
        }
    }
}

Последний трюк заключается в использовании небольшого объекта javascript, чтобы связать все вместе:

function AjaxFormSwitcher(form, outputTarget, doValidation) {
    this.doValidation = doValidation;
    this.outputTarget = outputTarget;
    this.targetForm = form;
}

AjaxFormSwitcher.prototype.switchFormToAjax = function() {
    var afs = this;
    var opts = {
        beforeSubmit: this.doValidation ? afs.checkValidation : null,
        complete: function(xmlHttp, status){ afs.processResult(afs, xmlHttp, status); },
        clearForm: false
    };
    this.targetForm.ajaxForm(opts);
}

AjaxFormSwitcher.prototype.checkValidation = function(formData, jqForm, options) {
    jqForm.validate();
    return jqForm.valid();
}

AjaxFormSwitcher.prototype.processResult = function(afs, xmlHttp, status) {
    if (xmlHttp == null) return;
    var r = xmlHttp;
    var c = r.getResponseHeader("content-type");
    if (c.match("json") != null) {
        var json = eval("(" + r.responseText + ")");
        afs.processJsonRedirect(json);
    }
    if (c.match("html") != null) {
        afs.outputTarget.html(r.responseText);
    }
}

AjaxFormSwitcher.prototype.processJsonRedirect = function(data) {
    if (data!=null) {
        switch (data.command) {
            case 'redirect':
                window.location.href = data.content;
                break;
        }
    }
}

Этот небольшой скрипт обрабатывает такие вещи, как подключение формы для выполнения ajax и обработка результата (либо команда json, либо html, который отображается в целевом объекте). По общему признанию, я не умею писать javascript, так что, вероятно, есть гораздо более изящный способ написать это.

2
ответ дан 30 November 2019 в 09:38
поделиться

Отказ от ответственности: я мало занимался программированием ASP.NET MVC.

Тем не менее, я использовал ряд фреймворков MVC на других языках и выполнил довольно много проектов django. Со временем я разработал шаблон для решения подобных проблем в django, используя включение шаблона .

По сути, я создаю частичный шаблон, содержащий форму (и любые ошибки проверки), который включается в основной шаблон. Представление (или Контроллер, в вашем случае) затем выбирает между этими двумя шаблонами: запросы AJAX получают частичный шаблон, а обычные запросы получают полный шаблон. В основном шаблоне я использую плагин формы jQuery для отправки формы через AJAX и просто заменяю текущую форму данными с сервера: если проверка не удалась, я получаю форму с выделенными полями и список ошибок вверху; если POST завершается успешно, форма заменяется сообщением об успешном завершении или чем-то еще, более подходящим для вашей ситуации.

Я думаю, что в мире ASP.NET MVC UserControls может быть эквивалентом частичных? В этой статье показано, как достичь чего-то похожего на то, что я описал (хотя статья кажется довольно устаревшей, и все могло измениться).

Чтобы ответить на ваш второй вопрос, я не хочу: Не думаю, что вам следует выполнить перенаправление на «страница не найдена» - один возвращает 302, другой должен возвращать 404; одно не является ошибкой, а другое. Если вы потеряете код состояния, ваш javascript станет более сложным (поскольку вам придется как-то протестировать фактические возвращенные данные, чтобы выяснить, что произошло). Эти два сообщения должны дать вам некоторые идеи о том, как реализовать страницы ошибок, удобные для HTTP. Django делает нечто подобное (вызывает исключение Http404 , возвращает код состояния 404 и при необходимости отображает шаблон 404.html ).

мне нужно будет как-то протестировать фактические возвращенные данные, чтобы выяснить, что произошло). Эти два сообщения должны дать вам некоторые идеи о том, как реализовать страницы ошибок, удобные для HTTP. Django делает нечто подобное (вызывает исключение Http404 , возвращает код состояния 404 и при необходимости отображает шаблон 404.html ).

мне нужно будет как-то протестировать фактические возвращенные данные, чтобы выяснить, что произошло). Эти два сообщения должны дать вам некоторые идеи о том, как реализовать страницы ошибок, удобные для HTTP. Django делает нечто подобное (вызывает исключение Http404 , возвращает код состояния 404 и, при необходимости, отображает шаблон 404.html ).

1
ответ дан 30 November 2019 в 09:38
поделиться

Я использовал xVal в прошлом, наряду с с некоторыми самодельными генераторами правил JS на основе отражения. Идея состоит в том, что вы определяете правило один раз (в вашем случае через nHibernate), а помощник HTML отражает ваши свойства и на лету генерирует код проверки на стороне клиента (используя плагин jQuery.validation). Совершенно правильный способ иметь отзывчивый пользовательский интерфейс на стороне клиента, в то же время обеспечивая принудительную проверку на стороне сервера.

К сожалению, этот метод не работает для форм, отправленных AJAX.

Для правил AJAX это было бы так же просто как добавление массива Errors к вашим возвращенным объектам JSON. Везде, где вы используете AJAX, просто проверьте длину ошибок (это все, что делает ModelState.IsValid) и отобразите ошибку. Вы можете использовать метод IsAjaxRequest для обнаружения вызова AJAX:

public ActionResult PostForm(MyModel thing)
{
  UpdateModel(thing);

  if (this.Request.IsAjaxRequest() == false)
  {
    return View();
  }
  else
  {
    foreach(var error in ModelState.Errors)
    {
      MyJsonObject.Errors.Add(error.Message); 
    }
    return JsonResult(MyJsonObject);
  }
}
0
ответ дан 30 November 2019 в 09:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: