首页 > 解决方案 > 更改发布值的 ActionFilter 无法影响模型

问题描述

我们正在尝试以“全局”方式清理 ASP.NET MVC Web 应用程序中发布的字符串条目。在我目前的尝试中,我编写了一个自定义操作过滤器,并用我的 FormPostSanitizer 类装饰了一个发布操作。这个想法是我们将装饰所有应该清理的发布操作。

该方法成功地捕获并清理了输入。但是这些经过清理的值在保存到数据库之前并没有固定到模型中。

这是它如何装饰控制器。

[HttpPost]
[ValidateAntiForgeryToken]
[FormPostSanitizer]
public ActionResult MyAction(MyViewModel model)
{
    // If ModelState.IsValid, save the model ...
}

这是我的动作过滤器。

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    if (filterContext.HttpContext.Request.HttpMethod != "POST") return;

    FormCollection formCollection = new FormCollection(filterContext.Controller.ControllerContext.HttpContext.Request.Form);
    foreach (string key in formCollection.AllKeys)
    {
        string sanitized = formCollection[key].SanitizeString(); // Extension method to alter the string.
        formCollection.Set(key, sanitized);
    }
    filterContext.ActionParameters["form"] = formCollection;
}

我的期望是最后一行将更改的值提交给 filterContext,并且模型将具有经过清理的值。这些值被清理了,但它们没有被应用到模型中。

如果在已编译的代码中有更好的方法可以在它们绑定到模型之前拦截和更改发布的值,那么请指点我一篇显示该方法的帖子。谢谢你的帮助。

标签: c#asp.netasp.net-mvc

解决方案


您可以为此目的创建自定义模型绑定器

public class SanitizeModelBinder : DefaultModelBinder
{
    protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder)
    {
        bool sanitize = controllerContext.HttpContext.Request.HttpMethod == "POST";

        //get value from default binder
        object value = base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder);
        if (!sanitize)
        {
            return value;
        }

        //sanitize value if it is a string
        string stringValue = value as string;
        if (stringValue != null)
        {
            return stringValue.SanitizeString();
        }

        return value;
    }
}

设置默认活页夹Global.asax.cs以将其用于每个操作

System.Web.Mvc.ModelBinders.Binders.DefaultBinder = new SanitizeModelBinder();

或者如果您想将此活页夹用于某些型号

public ActionResult MyAction([ModelBinder(typeof(SanitizeModelBinder))]MyViewModel model)

推荐阅读