Alexander Grek
Alexander Grek

Reputation: 11

ASP.NET MVC - HtmlEncode all strings by default

For example, a user creates a new question on a forum.

I send ajax to the server, then I use HtmlEncode to exclude the HTML code before saving it in the database.

Is it possible that HtmlEncode would be used automatically when receiving a request?

Also, when using the attribute (for example [HtmlAllowed]) you can allow html code in request.

Thanks

Upvotes: 1

Views: 1168

Answers (2)

Alexander Grek
Alexander Grek

Reputation: 11

Thanks to Yegor Androsov, for pointing me to right direction.

This ModelBinder automaticaly encode all string properties, except that has [SafeHtml] attribute

public class SafeStringModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        HttpRequestBase request = controllerContext.HttpContext.Request;
        string name = bindingContext.ModelName;
        string value = request.Unvalidated[name];

        Type holderType = bindingContext.ModelMetadata.ContainerType;
        if (holderType != null)
        {
            PropertyInfo propertyType = holderType.GetProperty(bindingContext.ModelMetadata.PropertyName);
            if (propertyType == null) return value;

            object[] attributes = propertyType.GetCustomAttributes(true);
            bool hasAttribute = attributes.Cast<Attribute>().Any(a => a.GetType() == typeof (SafeHtmlAttribute));

            if (!hasAttribute && !string.IsNullOrEmpty(value))
            {
                value = HttpUtility.HtmlEncode(value);
            }
        }

        return value;
    }
}

[AttributeUsage(AttributeTargets.Property)]
public class SafeHtmlAttribute : Attribute { }

Upvotes: 0

Yehor Androsov
Yehor Androsov

Reputation: 6152

You can achieve it using custom model binder, every string property or string parameter will go through this method when ASP.NET attempts to bind request to parameters of action method

public class StringBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        ValueProviderResult value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        bindingContext.ModelState.SetModelValue(bindingContext.ModelName, value);

        var str = (string)value?.ConvertTo(typeof(string));

        str = HttpUtility.HtmlEncode(str);
        return str;
    }
}

And in Application_Start()

ModelBinders.Binders.Add(typeof(string), new StringBinder());

Upvotes: 1

Related Questions