122

How can I allow a user to input HTML into a particular field using ASP.net MVC.

I have a long form with many fields that get mapped to this complex object in the controller.

I would like to make one field (the description) allow HTML which I will preform my own sanitation on at a later point.

Mikhail
  • 9,186
  • 4
  • 33
  • 49
Rabbi
  • 4,622
  • 9
  • 35
  • 45
  • 3
    For future visitors: IMHO, Chris J or Eugene Bosikov's answers are better than the accepted one for later versions of ASP.NET MVC, especially if you only want to allow HTML in one field. – lc. Aug 28 '13 at 01:55

11 Answers11

165

Add the following attribute the action (post) in the controller that you want to allow HTML for:

[ValidateInput(false)] 

Edit: As per Charlino comments:

In your web.config set the validation mode used. See MSDN:

<httpRuntime requestValidationMode="2.0" />

Edit Sept 2014: As per sprinter252 comments:

You should now use the [AllowHtml] attribute. See below from MSDN:

For ASP.NET MVC 3 applications, when you need to post HTML back to your model, don’t use ValidateInput(false) to turn off Request Validation. Simply add [AllowHtml] to your model property, like so:

public class BlogEntry {
    public int UserId {get;set;}
    [AllowHtml] 
    public string BlogText {get;set;}
 }
Community
  • 1
  • 1
Kelsey
  • 47,246
  • 16
  • 124
  • 162
  • 1
    If you are using .NET 4 you'll also have to set `` in your web.config file. – Charlino Sep 01 '10 at 19:43
  • @Charlino good point... I will amend my answer to include that and some more information. – Kelsey Sep 01 '10 at 19:44
  • but wont that preclude me from being able to use validation on the rest of my Model? I have a large model for this particular page not to mention all of the other models edited by this controller I was hoping to rely heavily on the ModelState and declarative Validation through attributes – Rabbi Sep 02 '10 at 01:47
  • @Rabbi it will remove all request validation for this action. It will not affect your model validation but all other fields will need to be checked and sanatized as well. You can't do it on a field by field level because the validation is happening at the point when the request is received which is way before the model is validated. – Kelsey Sep 02 '10 at 03:41
  • 3
    Is there really no solution for .NET 4 that doesn't include downgrading the request validation mode? – bzlm Sep 02 '10 at 06:46
  • @bzlm check out the MSDN link I posted... it doesn't need to be there but it is an option depending on the behaviour that they are after. – Kelsey Sep 02 '10 at 07:06
  • 20
    MSDN (http://msdn.microsoft.com/de-de/magazine/hh708755.aspx) says, that you shouldn't use ValidateInpute and take AllowHtmlAttribute instead. (Did'nt found the English version) – Alexander Schmidt Feb 02 '12 at 11:26
  • @sprinter252 Thanks +1 and english version can be reach by choosing language from top of the page or this link: http://msdn.microsoft.com/en-us/magazine/hh708755.aspx – QMaster Aug 10 '14 at 20:54
  • 8
    Made edit to hopefully address the 3 down votes that were recently made... it was a 4 year old answer :) – Kelsey Sep 17 '14 at 14:17
  • `[AllowHtml]` attribute only gives potentially dangerous request error. – SMUsamaShah May 31 '15 at 14:37
  • Added another upvote to offset blind downvoting Kelsey. Sad that Stack users don't look at the date of the answer and take that into consideration when deciding if the answer was correct at the time of posting. – Mike Devenney Mar 25 '16 at 15:02
  • @Kelsey: Thanks for your complete answer :) – Mazdak Shojaie May 07 '16 at 18:25
  • Muchas gracias, me sirvio mucho tu respuesta. La que se acomodo fue el atributo AllowHtml – bitcubico Jul 13 '17 at 00:22
  • Is there any way to do this in web.config or elsewhere, everytime I update my ef6 model it wipes them all out – djack109 Oct 11 '17 at 08:44
  • 3
    @djack109 Typically, you do not use your EF model as your view model. You would write a separate class that represents the actual data for your CRUD operations. This way when your EF6 model is regenerated, nothing is lost. You should also slim the models down to have only the properties you need to perform the task at hand. – Allen Clark Copeland Jr Feb 14 '19 at 05:08
132

What about [AllowHtml] attribute above property?

cryss
  • 4,130
  • 1
  • 29
  • 34
  • 5
    This seems like a much better way to me, avoiding changing any global behaviour. I've just solved my problem by adding this attribute to a property on my model. – Jonathan Sayce Sep 05 '12 at 09:22
  • 2
    Totally agree with Chris solution here, there is no reason to disable the html validation for the whole application if you just need one property in a model to be able to accept html input. Removing the validation in the web.config will open a big security hole in your app. – Miguel Apr 29 '13 at 13:19
  • 1
    Unfortunately this does not work if you are using [MetadataTypeAttribute](http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.metadatatypeattribute.aspx) – dav_i May 01 '13 at 08:13
  • @dav_i: This solution works fine with `MetadataTypeAttribute` and is preferable as it only allows HTML on the individual fields rather than the entire object. – iCollect.it Ltd Aug 05 '13 at 09:33
  • @TrueBlueAussie, I have been trying for hours in my mvc 4.0 environment and although AllowHtml should work it doesnt. I have had to admit defeat and go with a less secure option which is pants. The AllowHtml just doesnt seem to work with the use of MetadataTypeAttribute – julian guppy Dec 08 '13 at 11:52
  • It also won't work if you access the request field containing the html before the DefaultModelBinder does, as in a custom IModelBinder for example. – Oliver Nov 18 '14 at 13:06
  • @Oliver Yes, that attribute is supposed to work only with the DefaultModelBinder and I assumed that it is obvious :) – cryss Nov 19 '14 at 10:15
  • `[AllowHtml]` attribute only gives potentially dangerous request error. – SMUsamaShah May 31 '15 at 14:37
  • Works on my machine. Thanks cryss! – Mike Devenney Mar 25 '16 at 14:59
43

Add to model:

using System.Web.Mvc;

And to your property

        [AllowHtml]
        [Display(Name = "Body")]
        public String Body { get; set; }

This code from my point the best way avoid this error. If you are using HTML editor you will not have security issues because it already restricted.

Eugene Bosikov
  • 840
  • 10
  • 12
9

Adding [AllowHtml] on the specific property is the recommended solution as there are plenty of blogs and comments suggesting to decrease the security level, which should be unacceptable.

By adding that, the MVC framework will allow the Controller to be hit and the code in that controller to be executed.

However, it depends on your code, filters, etc. how the response is generated and whether there is any further validation that might trigger another similar error.

In any case, adding [AllowHtml] attribute is the right answer, as it allows html to be deserialized in the controller. Example in your viewmodel:

[AllowHtml]
public string MessageWithHtml {get; set;}
diegosasw
  • 13,734
  • 16
  • 95
  • 159
9

I faced the same issue although i added [System.Web.Mvc.AllowHtml] to the concerning property as described in some answers.

In my case, i have an UnhandledExceptionFilter class that accesses the Request object before MVC validation takes place (and therefore AllowHtml has not effect) and this access raises a [HttpRequestValidationException] A potentially dangerous Request.Form value was detected from the client.

This means, accessing certain properties of a Request object implicitly fires validation (in my case its the Params property).

A solution to prevent validation is documented on MSDN

To disable request validation for a specific field in a request (for example, for an input element or query string value), call the Request.Unvalidated method when you get the item, as shown in the following example

Therefore, if you have code like this

var lParams = aRequestContext.HttpContext.Request.Params;
if (lParams.Count > 0)
{
  ...

change it to

var lUnvalidatedRequest = aRequestContext.HttpContext.Request.Unvalidated;

var lForm = lUnvalidatedRequest.Form;
if (lForm.Count > 0)
{
  ...

or just use the Form property which does not seem to fire validation

var lForm = aRequestContext.HttpContext.Request.Form;
if (lForm.Count > 0)
{
  ...
ViRuSTriNiTy
  • 5,017
  • 2
  • 32
  • 58
4

If you need to allow html input for action-method parameter (opposed to "model property") there's no built-in way to do that but you can easily achieve this using a custom model binder:

public ActionResult AddBlogPost(int userId,
    [ModelBinder(typeof(AllowHtmlBinder))] string htmlBody)
{
    //...
}

The AllowHtmlBinder code:

public class AllowHtmlBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var request = controllerContext.HttpContext.Request;
        var name = bindingContext.ModelName;
        return request.Unvalidated[name]; //magic happens here
    }
}

Find the complete source code and the explanation in my blog post: https://www.jitbit.com/alexblog/273-aspnet-mvc-allowing-html-for-particular-action-parameters/

Alex from Jitbit
  • 53,710
  • 19
  • 160
  • 149
  • 1
    Unvalidated seems to be only available in framework 4.5 and above. – Ben Oct 09 '19 at 18:36
  • @Ben correct! Please check this modified solution. https://stackoverflow.com/questions/59483284/passing-raw-html-from-view-to-controller-xss-safe-no-information-loss – om-ha Dec 26 '19 at 02:34
3

URL Encoding the data works as well for me

For example

var data = '<b>Hello</b>'

In Browser call encodeURIComponent(data) before posting

On Server call HttpUtility.UrlDecode(received_data) to decode

That way you can control exactly which fields area allowed to have html

smjhunt
  • 311
  • 4
  • 8
2

You Can Use [AllowHtml] To Your Project For Example

 [AllowHtml]
 public string Description { get; set; }

For Use This Code To Class Library You Instal This Package

Install-Package Microsoft.AspNet.Mvc

After Use This using

using System.Web.Mvc;
Diako Hasani
  • 1,384
  • 13
  • 14
1

I have faced this problem during development of a E-Commerce site using NopCommerce, I got this solution by 3 different ways as like the previous answers. But according to the NopCommerce structure I didn't found those three at a time. I have just seen that there they are using just [AllowHtml] and it's working fine except any problem. As previously asked question

Personally I don't prefer [ValidateInput(false)] because i's skipping total model entity checking, which is insecure. But if anyone just write have a look here

[AllowHtml] 
public string BlogText {get;set;}

then it just skip only single property, and just allow only particular property and check hardly all other entities. Therefore it seems preferable towards mine.

Community
  • 1
  • 1
Ananda G
  • 2,389
  • 23
  • 39
1

In my case, the AllowHtml attribute was not working when combined with the OutputCache action filter. This answer solved the problem for me. Hope this helps someone.

Community
  • 1
  • 1
jd4w9
  • 41
  • 2
0

None of the answers here worked for me unfortunately.

I ended up using Custom Model Binding and used a third-party Sanitizer.

See my self-answered question here.

om-ha
  • 3,102
  • 24
  • 37