AllowHtml所依赖的请求验证概念,并且绑定检查特定于Web请求。这里没有分离的关注点,它们是紧密相连的。因此,不,您不能在没有System.Web等参考的情况下使用它。
我们已经将业务逻辑层和业务对象分离为一个完全独立的项目/程序集。模型的某些属性可以包含HTML内容。在业务逻辑之前,我们有一个ASP.NET MVC Web应用程序,用户可以在其中管理业务对象。
因此,我们如何向MVC模型绑定器指示我们希望允许HTML内容位于(且仅位于)某些特定属性上,而无需在业务逻辑层中引用ASP.NET MVC?或者,如何在没有强引用的情况下从另一个程序集中注入元数据?
谢谢。
我必须将BindModel更改为以下内容(这是基于Russ Cam的答案),以便检查实际属性上的属性。我还查看了this答案以寻求帮助:
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var holderType = bindingContext.ModelMetadata.ContainerType;
if (holderType != null)
{
var propertyType = holderType.GetProperty(bindingContext.ModelMetadata.PropertyName);
var attributes = propertyType.GetCustomAttributes(true);
var hasAttribute = attributes
.Cast<Attribute>()
.Any(a => a.GetType().IsEquivalentTo(typeof(MyAllowHtmlAttribute)));
if (hasAttribute)
{
bindingContext.ModelMetadata.RequestValidationEnabled = false;
}
}
return base.BindModel(controllerContext, bindingContext);
}
实现您自己的IModelBinder
和AllowHtmlAttribute
-将属性放在您的核心项目中,并将IModelBinder
放在您的MVC应用程序中。
public class MyAllowHtmlAttribute : Attribute
{
}
要实现IModelBinder
,只需继承DefaultModelBinder
并添加逻辑以根据您自己的AllowHtmlAttribute
的存在关闭请求验证。>
public class MyBetterDefaultModelBinder : DefaultModelBinder { public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { var allowHtmlAttribute = bindingContext.ModelType.GetCustomAttribute<MyAllowHtmlAttribute>(); if (allowHtmlAttribute != null) { bindingContext.ModelMetadata.RequestValidationEnabled = false; } return base.BindModel(controllerContext, bindingContext); } }
然后将您自己的ModelBinder连接到
Application_Start
(或其他启动代码)中>ModelBinders.Binders.DefaultBinder = new MyBetterDefaultModelBinder();
自定义模型绑定器中的这种逻辑就是MVC中的
AllowHtmlAttribute
所做的,但是由于它本质上与MVC中的ModelMetadata绑定,因此您将无法轻松使用它。
AllowHtml所依赖的请求验证概念,并且绑定检查特定于Web请求。这里没有分离的关注点,它们是紧密相连的。因此,不,您不能在没有System.Web等参考的情况下使用它。
[在我看来,您排除了最正确的选项-视图模型,即使验证和绑定确实是视图模型的概念。
您不能拥有具有特定于Web的绑定和验证概念的可移植业务对象。
如果仍然对某人有用:我有类似的要求,但是我的类是首先由Entity Framework数据库生成的,因此该项目广泛使用了[MetadataType]属性。
我将这个问题的各个部分拼凑在一起,并将这些问题链接到该解决方案中,以允许该方法与指定[AllowHtml](或类似名称)的Metadata类一起使用
在您的Entity Framework项目中,定义一个属性:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)] public class SkipRequestValidationAttribute : Attribute { }
然后在您的元数据类中,将此属性分配给相关属性:
[MetadataType(typeof(ActivityLogMetadata))] public partial class ActivityLog { } public class ActivityLogMetadata { [Required] [SkipRequestValidation] [Display(Name = "Body")] public string Body { get; set; } }
现在,在您的MVC项目中,添加此自定义模型联编程序以查找这些元属性。
public class MyModelBinder : DefaultModelBinder { public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { var containerType = bindingContext.ModelMetadata.ContainerType; if (containerType != null) { /* Do we have a Metadata attribute class specified for the Type we're binding? */ var metaRedirectInfo = containerType .GetCustomAttributes(typeof(MetadataTypeAttribute), true) .OfType<MetadataTypeAttribute>().FirstOrDefault(); if (metaRedirectInfo != null) { /* If our Meta class has a definition for this property, check it */ var thisProperty = metaRedirectInfo.MetadataClassType.GetProperty(bindingContext.ModelMetadata.PropertyName); if (thisProperty != null) { var hasAttribute = thisProperty .GetCustomAttributes(false) .Cast<Attribute>() .Any(a => a.GetType().IsEquivalentTo(typeof(SkipRequestValidationAttribute))); /* If we have a SkipRequestValidation attribute, ensure this property isn't validated */ if (hasAttribute) bindingContext.ModelMetadata.RequestValidationEnabled = false; } } } return base.BindModel(controllerContext, bindingContext); } }
最后,在您的MVC项目启动方法(例如Startup.cs)中,替换默认的模型绑定程序:
ModelBinders.Binders.DefaultBinder = new MyModelBinder();
AllowHtml所依赖的请求验证概念,并且绑定检查特定于Web请求。这里没有分离的关注点,它们是紧密相连的。因此,不,您不能在没有System.Web等参考的情况下使用它。
如果仍然对某人有用:我有类似的要求,但是我的类是首先由Entity Framework数据库生成的,因此该项目广泛使用了[MetadataType]属性。