Как сохранить ошибки ModelState при использовании RedirectToAction? - PullRequest
25 голосов
/ 18 марта 2009

У меня есть код, который сохраняет тикет в нашей системе. Если есть ошибка, он выполняет RedirectToAction. Проблема в том, что у меня, похоже, нет ошибок в новом действии. Как я могу это исправить?

 ModelState.AddModelError("_FORM", "Unable to save ticket");
 ModelState.AddModelError("_FORM", "Phone number was invalid.");
 ModelState.AddModelError("_FORM", "Lane number is required.");
 return RedirectToAction("CreateStep", "Ticket");

Я знаю, что некоторые предлагали использовать TempData, но как мне получить каждую ошибку из ModelState?

Спасибо.

Ответы [ 5 ]

41 голосов
/ 12 апреля 2009

Шаблон PRG в порядке, но я сделал это:

Базовый контроллер:

protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
    if (TempData["ModelState"] != null && !ModelState.Equals(TempData["ModelState"]))
        ModelState.Merge((ModelStateDictionary)TempData["ModelState"]);

    base.OnActionExecuted(filterContext);
}

Действие (я использую xVal ):

try
{
    user.Login();
    AuthenticationManager.SignIn(user);
}
catch (RulesException rex)
{
    // on bad login
    rex.AddModelStateErrors(ModelState, "user");
    TempData["ModelState"] = ModelState;
    return Redirect(Request.UrlReferrer.ToString());
}

Действие выдает исключение, добавляет ModelState к TempData и перенаправляет обратно к рефереру. Поскольку действие перехватывается, OnActionExecuted все еще выполняется, но первый раз вокруг ModelState - это то же самое, что TempData ["ModelState"], поэтому вы не хотите сливаться с самим собой. Когда действие перенаправления выполняется, OnActionExecuted запускается снова. На этот раз, если что-то есть в TempData ["ModelState"], оно сливается с ModelState этого действия.

Вы можете расширить его до нескольких моделей, используя TempData ["ModelState.user"] = ModelState и затем объединяя каждый объект TempData, который начинается с ModelState.

29 голосов
/ 19 ноября 2011

Я знаю, что эта ветка старая, но в этом блоге о ASP.NET Best Practices есть несколько отличных предложений.
№ 13 на странице посвящен использованию 2 фильтров действий для сохранения и восстановления ModelState между перенаправлениями.

Это шаблон, который использует моя работа, и мне это нравится.

Вот упрощенный пример:

[ImportModelStateFromTempData]
public ActionResult Dashboard()
{
    return View();
}

[AcceptVerbs(HttpVerbs.Post), ExportModelStateToTempData]
public ActionResult Dashboard(string data)
{
    if (ValidateData(data))
    {
        try
        {
            _service.Submit(data);
        }
        catch (Exception e)
        {
            ModelState.AddModelError(ModelStateException, e);
        }
    }

    return RedirectToAction("Dashboard");
}
4 голосов
/ 24 марта 2009

этот пост описывает, как вы можете реализовать PRG-Pattern в MVC http://blog.simonlovely.com/archive/2008/11/26/post-redirect-get-pattern-in-mvc.aspx

НТН

3 голосов
/ 18 марта 2009

Использование коллекции TempData []

Tempdata сохраняется от одного запроса к другому, а затем исчезает.

0 голосов
/ 16 ноября 2016

То, что я сделал для поддержания моего ModelState вне зависимости от того, куда я отправляюсь с перенаправлениями, следующее:

  1. В вашей модели добавьте:

    public ModelStateDictionary modelstate { get; set; }
    
  2. В конструкторе вашей модели добавьте:

    this.modelstate = new System.Web.Mvc.ModelStateDictionary();
    
  3. Пример сообщения с моей моделью под названием Models.ContactInformation:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult contact(Models.ContactInformation con)
    {
      if (string.IsNullOrEmpty(con.SelectedAgencySelectorType))
      {
        ModelState.AddModelError("", "You did not select an agency type.");
      }
    
      con.modelstate = ModelState;
      TempData["contact"] = con;
      if (!ModelState.IsValid) return RedirectToAction("contactinformation", "reports");
    
        //do stuff
    
        return RedirectToAction("contactinformation", "reports");
    }
    
  4. Так что теперь у ваших tempdata есть ваша модель и состояние модели как есть.

  5. Следующее - мой взгляд, который не зависит от состояния чего-либо, если оно не имеет чего-либо. Вот код:

    [HttpGet]
    public ActionResult contactinformation()
    {
        //try cast to model
        var m = new Models.ContactInformation();
        if (TempData["contact"] is Models.ContactInformation) m = (Models.ContactInformation)TempData["contact"];
    
        //restore modelstate if needed
        if (!m.modelstate.IsValid)
        {
            foreach (ModelState item in m.modelstate.Values)
            {
                foreach (ModelError err in item.Errors)
                {
                    ModelState.AddModelError("", err.ErrorMessage.ToString());
                }
            }
        }
    
        return View(m);
    }
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...