RPM*_*984 85 error-handling asp.net-mvc redirecttoaction modelstate http-redirect
我有以下两种操作方法(简化问题):
[HttpGet]
public ActionResult Create(string uniqueUri)
{
// get some stuff based on uniqueuri, set in ViewData.
return View();
}
[HttpPost]
public ActionResult Create(Review review)
{
// validate review
if (validatedOk)
{
return RedirectToAction("Details", new { postId = review.PostId});
}
else
{
ModelState.AddModelError("ReviewErrors", "some error occured");
return RedirectToAction("Create", new { uniqueUri = Request.RequestContext.RouteData.Values["uniqueUri"]});
}
}
Run Code Online (Sandbox Code Playgroud)
因此,如果验证通过,我将重定向到另一页(确认).
如果发生错误,我需要显示包含错误的同一页面.
如果我这样做return View(),则会显示错误,但如果我这样做return RedirectToAction(如上所述),则会丢失模型错误.
我对这个问题并不感到惊讶,只是想知道你们是怎么处理这个问题的?
我当然可以返回相同的View而不是重定向,但我在"Create"方法中有逻辑,它填充了视图数据,我必须复制它.
有什么建议?
asg*_*eo1 76
我今天必须自己解决这个问题,并遇到了这个问题.
一些答案很有用(使用TempData),但并没有真正回答手头的问题.
我发现的最佳建议是在这篇博客文章中:
http://www.jefclaes.be/2012/06/persisting-model-state-when-using-prg.html
基本上,使用TempData来保存和恢复ModelState对象.但是,如果将其抽象为属性,则会更加清晰.
例如
public class SetTempDataModelStateAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
base.OnActionExecuted(filterContext);
filterContext.Controller.TempData["ModelState"] =
filterContext.Controller.ViewData.ModelState;
}
}
public class RestoreModelStateFromTempDataAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
if (filterContext.Controller.TempData.ContainsKey("ModelState"))
{
filterContext.Controller.ViewData.ModelState.Merge(
(ModelStateDictionary)filterContext.Controller.TempData["ModelState"]);
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后根据您的示例,您可以保存/恢复ModelState,如下所示:
[HttpGet]
[RestoreModelStateFromTempData]
public ActionResult Create(string uniqueUri)
{
// get some stuff based on uniqueuri, set in ViewData.
return View();
}
[HttpPost]
[SetTempDataModelState]
public ActionResult Create(Review review)
{
// validate review
if (validatedOk)
{
return RedirectToAction("Details", new { postId = review.PostId});
}
else
{
ModelState.AddModelError("ReviewErrors", "some error occured");
return RedirectToAction("Create", new { uniqueUri = Request.RequestContext.RouteData.Values["uniqueUri"]});
}
}
Run Code Online (Sandbox Code Playgroud)
如果您还想在TempData中传递模型(建议使用bigb),那么您仍然可以这样做.
Kun*_*vič 49
你需要有相同的实例Review上的HttpGet动作.为此,您应该Review review在HttpPost操作中将对象保存在temp变量中,然后在HttpGet操作时将其恢复.
[HttpGet]
public ActionResult Create(string uniqueUri)
{
//Restore
Review review = TempData["Review"] as Review;
// get some stuff based on uniqueuri, set in ViewData.
return View(review);
}
[HttpPost]
public ActionResult Create(Review review)
{
//Save your object
TempData["Review"] = review;
// validate review
if (validatedOk)
{
return RedirectToAction("Details", new { postId = review.PostId});
}
else
{
ModelState.AddModelError("ReviewErrors", "some error occured");
return RedirectToAction("Create", new { uniqueUri = Request.RequestContext.RouteData.Values["uniqueUri"]});
}
}
Run Code Online (Sandbox Code Playgroud)
另外我建议,如果你想让它在HttpGet第一次执行动作后按下浏览器刷新按钮也能正常工作,你可能会这样做
Review review = TempData["Review"] as Review;
TempData["Review"] = review;
Run Code Online (Sandbox Code Playgroud)
否则刷新按钮对象review将为空,因为没有任何数据TempData["Review"].
Microsoft 删除了在 TempData 中存储复杂数据类型的功能,因此之前的答案不再有效;您只能存储简单类型,例如字符串。我已更改@asgeo1 的答案以按预期工作。
public class SetTempDataModelStateAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
base.OnActionExecuted(filterContext);
var controller = filterContext.Controller as Controller;
var modelState = controller?.ViewData.ModelState;
if (modelState != null)
{
var listError = modelState.Where(x => x.Value.Errors.Any())
.ToDictionary(m => m.Key, m => m.Value.Errors
.Select(s => s.ErrorMessage)
.FirstOrDefault(s => s != null));
controller.TempData["KEY HERE"] = JsonConvert.SerializeObject(listError);
}
}
}
public class RestoreModelStateFromTempDataAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
var controller = filterContext.Controller as Controller;
var tempData = controller?.TempData?.Keys;
if (controller != null && tempData != null)
{
if (tempData.Contains("KEY HERE"))
{
var modelStateString = controller.TempData["KEY HERE"].ToString();
var listError = JsonConvert.DeserializeObject<Dictionary<string, string>>(modelStateString);
var modelState = new ModelStateDictionary();
foreach (var item in listError)
{
modelState.AddModelError(item.Key, item.Value ?? "");
}
controller.ViewData.ModelState.Merge(modelState);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
从这里,您可以根据需要在控制器方法上添加所需的数据注释。
[RestoreModelStateFromTempDataAttribute]
[HttpGet]
public async Task<IActionResult> MethodName()
{
}
[SetTempDataModelStateAttribute]
[HttpPost]
public async Task<IActionResult> MethodName()
{
ModelState.AddModelError("KEY HERE", "ERROR HERE");
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
50199 次 |
| 最近记录: |