默认
方法1
[ValidateInput(false)]
这个方法会完全开放,对于有些字段允许,有些字段不允许的情况,是不会检测的
方法2
[AllowHtml]
此方法只有再使用DefaultModelBinder的时候才有效
public ActionResult Index(FormCollection form)
如使用FormCollection是不起作用的。因为FormCollection与具体的Model并无关联
检测不通过,就报错的方式似乎也并不是很友好,如果输入的文本确实需要包含<script标签,那就没法添加成功了
假设允许输入,但是自动传唤成HtmlEncode形式,是否会更好。
可采用自定义ModelBinder的方式
public class MvcHtmlModelBinder : DefaultModelBinder
{
protected override void SetProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor, object value)
{
var propertyMetadata = bindingContext.PropertyMetadata[propertyDescriptor.Name];
if (propertyMetadata.RequestValidationEnabled && propertyDescriptor.PropertyType == typeof(string) && value != null && !string.IsNullOrEmpty(value.ToString()))
{
value = value.ToString()
.Replace("<script", "<script")
.Replace("</script>", "</script>");
}
base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value);
}
}
在global里
ModelBinders.Binders.Add(typeof(TestModel), new MvcHtmlModelBinder());
这样,当更新Model以后,允许html的,还是html,而不允许html的,进行了Encode。
当我们把这样的数据记录到数据库,再读出来时(比如编辑页面)
允许html的,和我们输入的一致,而不允许html的,读出来的encode后的,和我们输入的是不一致的。
我们希望在Html.TextBoxFor时,可以再转回来
public class MvcHtmlModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
protected override ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, System.ComponentModel.PropertyDescriptor propertyDescriptor)
{
var meta = base.GetMetadataForProperty(modelAccessor, containerType, propertyDescriptor);
if (meta.RequestValidationEnabled && meta.ModelType == typeof(string))
{
if (meta.Model != null && !string.IsNullOrEmpty(meta.Model.ToString()))
{
meta.Model = meta.Model.ToString().Replace("<", "<").Replace(">", ">");
}
}
return meta;
}
}
global里
ModelMetadataProviders.Current = new MvcHtmlModelMetadataProvider();
之后,我们使用类似这样的代码
public ActionResult Index()
{
var obj = new TestModel
{
Html = "<script>alert(1)</script>",
Text = "<script>alert(1)</script>"
};
return View(obj);
}
他显示的结果是转回来的
但是,如果你是直接输出
@Model.Text
还是转意过的代码
以上代码只为说明,请勿直接用于生产