using Ben Foster Automatic Validate Model State I have this code :
[ImportModelStateFromTempData]
public ActionResult Edit(int id, int otherProperty) {
// ...
return View()
}
[HttpPost,ValidateModelState]
public ActionResult Edit(int id, PaymentOrderCreateUpdateCommand order) {
// ...
return RedirectToAction("Index", new {otherProperty = order.otherProperty}
}
Being on the url :
/Edit/5?otherProperty=4
If a fill a some form that post to Edit [HttpPost] action with an invalid model state, the ValidateModelState do it's thing and returns the request to
/Edit/5
problem is the ?otherProperty=4 needed for that view to be generated is lost in the Redirect.
Anyone knows of a way to modify the automatic model state validation attribute so it includes the query parameters on it ?
for completion on the question I add the ValidateModelStateAttribute class :
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class ValidateModelStateAttribute : ModelStateTempDataTransfer {
public override void OnActionExecuting(ActionExecutingContext filterContext) {
if (!filterContext.Controller.ViewData.ModelState.IsValid) {
if (filterContext.HttpContext.Request.IsAjaxRequest()) {
ProcessAjax(filterContext);
} else {
ProcessNormal(filterContext);
}
}
base.OnActionExecuting(filterContext);
}
protected virtual void ProcessNormal(ActionExecutingContext filterContext) {
// Export ModelState to TempData so it's available on next request
ExportModelStateToTempData(filterContext);
// redirect back to GET action
filterContext.Result = new RedirectToRouteResult(filterContext.RouteData.Values);
}
protected virtual void ProcessAjax(ActionExecutingContext filterContext) {
var errors = filterContext.Controller.ViewData.ModelState.ToSerializableDictionary();
var json = new JavaScriptSerializer().Serialize(errors);
// send 400 status code (Bad Request)
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
filterContext.HttpContext.Response.StatusDescription = "Invalid Model State";
filterContext.Result = new ContentResult() { Content = json };
}
}
adding this to the ProcessNormal :
// add query string values.
var qs = filterContext.HttpContext.Request.QueryString;
foreach (string key in qs.Keys) {
filterContext.RouteData.Values.Add(key, qs.Get(key));
}
looks like it does the trick. I'm not sure if this is ok or can be a problem tho.