We have separated our business logic layer and business objects into a completely separate project/assembly. Some properties of the models can contain HTML content. In front of the business logic, we have an ASP.NET MVC web application, where users can manage the business objects.
So, how can we indicate to the MVC model binder that we want to allow HTML content on (and only on) some specific properties, without referencing ASP.NET MVC in our business logic layer? Or, how can metadata be injected from another assembly without strong references?
Thank you.
I had to change BindModel to the following (this builds on Russ Cam's answer) in order to check the attribute on the actual property. I also looked at this answer for help:
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);
}
Implement your own IModelBinder
and AllowHtmlAttribute
- put the attribute in your core project and the IModelBinder
in your MVC application.
public class MyAllowHtmlAttribute : Attribute
{
}
To implement the IModelBinder
, simply inherit from DefaultModelBinder
and add logic to turn off request validation based on the presence of your own 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);
}
}
Then hook up your own ModelBinder in Application_Start
(or other startup code)
ModelBinders.Binders.DefaultBinder = new MyBetterDefaultModelBinder();
This logic in the custom model binder is what the AllowHtmlAttribute
in MVC does but you wouldn't be able to use that one easily as it is intrinsically tied to ModelMetadata in MVC.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With