6

I'm building a Content Management System to allow people other than me to update stuff on the site.

I have a front-facing HTML form that sends data, via AJAX, to a controller:

// CONTROLLER
[ValidateInput(false)]
public void CarAJAX()
{
    CarAdmin CA = new CarAdmin();
    CA.UpdateCar(System.Web.HttpContext.Current.Request);
}

This data will have HTML, so I keep getting an error in my Model:

// MODEL
using System;
using System.Web;
using System.Web.Mvc;

namespace Site.Models
{
    public class CarAdmin
    {
        public String id { get; set; }
        [AllowHtml]
        public String HTML_Stuff { get; set; }

        public CarAdmin(){}

        public void UpdateCar(HttpRequest Request)
        {
            HTML_Stuff = Request.Form["HTML_Stuff"]; // <-- ERROR HAPPENS HERE!!!!!!

            // sanitation and validation

            String Select = String.Format("UPDATE Car Set HTML_Stuff = {0} WHERE id = {1}", HTML_Stuff, id);

            // Execute DB Command
        }
    }
}

As shown in the code, I'm getting an error when I try to set a member equal to a request variable that has HTML.

Edit: The error is 'A potentially dangerous Request.Form value was detected'

Here's what I've tried:

  • Change the validation mode in web.config, but I don't want to change the validation for my entire site, when only one variable will have HTML.

  • [AllowHtml] in the Model, however I'm still getting the same error - as if [AllowHtml] did nothing at all.

  • [ValidateInput(false)] in the Controller, similar to AllowHtml, it seems to have no affect whatsoever.

Am I missing something here?

Community
  • 1
  • 1
Travis Heeter
  • 13,002
  • 13
  • 87
  • 129

4 Answers4

15

I had the same problem. "requestValidationMode="2.0"" was set in web.config, [AllowHtml] was also set on proper property and I still got the error "A potentially dangerous Request.Form value detected...".

But I observed that the controller method actually was called (I was able to debug the method) so this had to meant that validation is in fact turned off. In Call Stack I noticed repeatedly occurring of classes around cache like "System.Web.Caching.OutputCacheModule" and this led me to an idea that this has something to do with cache I had turned off on the whole controller like this "[OutputCache(NoStore = true, Duration = 0)]".

Based on this I tried to also set Location of the cache to OutputCacheLocation.None and this did the trick. So I ended up with [OutputCache(NoStore = true, Duration = 0, Location = OutputCacheLocation.None)] working and finally not validating and not failing my requests.

trucko
  • 166
  • 1
  • 3
  • Adding the OutputCache attribute to the controller also worked for me, rather bizarrely – KevD May 18 '16 at 16:19
  • Not sure why that should work, but it did the trick for me - thanks! – ChrisFox Jul 17 '16 at 17:25
  • Great Scott! How bizarre. Plus 1 beer from me. (Let's start a new stackexchange fork called BeerExchange. Credit beers for solutions. Could be a huge winner.) – Sentinel Feb 08 '17 at 11:44
  • This worked without "requestValidationMode="2.0"" ...well done figuring THAT on out :) – davaus Jan 24 '19 at 02:31
0

Try with this:

// CONTROLLER
[HttpPost]
public ActionResult CarAJAX(CarAdmin model)
{
    model.UpdateCar();
}

// MODEL
using System;
using System.Web;
using System.Web.Mvc;

namespace Site.Models
{
    public class CarAdmin
    {
        private string html;

        public String id { get; set; }
        [AllowHtml]
        public String HTML_Stuff { 
            get
            { 
                return html; 
            }
            set
            { 
                // sanitation and validation on "value"
                html = value;
            }
        }

        public CarAdmin(){}

        public void UpdateCar()
        {
            String Select = String.Format("UPDATE Car Set HTML_Stuff = {0} WHERE id = {1}", HTML_Stuff, id);

            // Execute DB Command
        }
    }
}

I also noticed that you are validating inside a method. It would probably be better, if you do that when setting the property.

EDIT:
I researched quite a bit on the topic. You actually need to bind model to the controller using AJAX. Please look at this example. I'm not sure of extents of your code, but I think you also need ActionResult to return within controller. There are nice examples of what to return from ActionResult.

Community
  • 1
  • 1
fsacer
  • 1,382
  • 1
  • 15
  • 23
0

just put [ValidateInput(false)] on controller

-1

You should do it as-

Create a separate class with entities those are required-

public class EntityDto {
        public String id { get; set; }
        [AllowHtml]
        public String HTML_Stuff { get; set; }
}

And then use it in your controller method-

[ValidateInput(false)]
public void UpdateCar(EntityDto model)
{
    var html_stuff = model.HTML_Stuff; 

    // sanitation and validation

    String Select = String.Format("UPDATE Car Set HTML_Stuff = {0} WHERE id = {1}", html_stuff , id);

    // Execute DB Command
}

Let me know if it helps.

fsacer
  • 1,382
  • 1
  • 15
  • 23
Manoz
  • 6,507
  • 13
  • 68
  • 114