Estoy intentando vincular una cadena HTML ingresada por el usuario desde un POST en una variable de cadena simple en un objeto modelo. Esto funciona bien si uso el atributo [AllowHtml]
. Sin embargo, me gustaría para desinfectar el código HTML antes de que se abre paso en el modelo, así que he creado un ModelBinder:Uso de un archivador de modelo personalizado para cadenas HTML
public class SafeHtmlModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerCtx, ModelBindingContext bindingCtx)
{
var bound = base.BindModel(controllerCtx, bindingCtx);
// TODO - return a safe HTML fragment string
return bound;
}
}
Y también un CustomModelBinderAttribute
:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class SafeHtmlModelBinderAttribute : CustomModelBinderAttribute
{
public SafeHtmlModelBinderAttribute()
{
binder = new SafeHtmlModelBinder();
}
private IModelBinder binder;
public override IModelBinder GetBinder()
{
return binder;
}
}
continuación, anoto las del modelo que quiero ser desinfectados con el nuevo atributo:
[Required(AllowEmptyStrings = false, ErrorMessage = "You must fill in your profile summary")]
[AllowHtml, SafeHtmlModelBinder, WordCount(Min = 1, Max = 300)]
public string Summary { get; set; }
Esto está siguiendo el ejemplo de la http://msdn.microsoft.com/en-us/magazine/hh781022.aspx. Desafortunadamente, ¡parece que no funciona! Si coloco un punto de interrupción en mi método BindModel
, nunca se golpea. ¿Algunas ideas?
ACTUALIZACIÓN
Sobre la base de la información de Joel he cambiado de IModelBinder para interceptar el valor cuando en el método SetProperty
y en lugar de aplicar el SafeHtmlModelBinderAttribute
a las propiedades de cadena que contiene la clase que pueden contener HTML. El código comprueba que la propiedad es una cadena y también se permite para contener HTML antes de intentar desinfectar:
public class SafeHtmlModelBinder : DefaultModelBinder
{
protected override void SetProperty(
ControllerContext controllerCtx,
ModelBindingContext bindingCtx,
PropertyDescriptor property,
object value)
{
var propertyIsString = property.PropertyType == typeof(string);
var propertyAllowsHtml = property.Attributes.OfType<AllowHtmlAttribute>().Count() >= 1;
var input = value as string;
if (propertyIsString && propertyAllowsHtml && input != null)
{
// TODO - sanitize HTML
value = input;
}
base.SetProperty(controllerCtx, bindingCtx, property, value);
}
}
¿CustomModelBinderAttribute funciona en las propiedades?Mirando el código fuente de MVC ese atributo solo se usa en 'const interno AttributeTargets ValidTargets = AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Parameter | AttributeTargets.Struct; '... lo que me sugiere que el framework puede no esperar ver esto en las propiedades. – Schneider