0

使用Ben Foster 自动验证模型状态我有这个代码:

[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}
}

在网址上:

/Edit/5?otherProperty=4

如果填写某个表单,该表单发布到具有无效模型状态的 Edit [HttpPost] 操作,则 ValidateModelState 会执行此操作并将请求返回给

/Edit/5 

问题是生成该视图所需的 ?otherProperty=4 在重定向中丢失了。

任何人都知道修改自动模型状态验证属性以使其包含查询参数的方法吗?

为了完成这个问题,我添加了 ValidateModelStateAttribute 类:

[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 };
    }
}
4

2 回答 2

0

将此添加到 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));
}

看起来它可以解决问题。我不确定这是否可以或可能是一个问题。

于 2013-06-13T19:37:11.313 回答
0

You could also use RouteValues instead of query parameters, and change your routes accordingly. For example:

routes.MapRoute(
            name: "",
            url: "{controller}/{action}/{id}/{p1}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional,p1 = UrlParameter.Optional }
        );

That way you can recieve id and p1 parameters. Using your tweak to [ValidateModelState] it's important to remember that you need to pass query parameters with routeArgument. If you use @Html.HiddenFor, they won't be in query string.

于 2014-09-26T12:48:55.860 回答