asp.net-mvcexceptionhttp-postdangerous-request

mvc - First "get" result for request.params get exception, second "get" is ok


mvc - First "get" result for request.params get exception, second "get" is ok. i have a page that has a field with xml text in it. i am using validation=false. but, on post method in the controller i am trying to get the requset.params and i get an error of "A potentially dangerous Request.Form value was detected from the client". after some digging and debugging i see that first time i am trying to get the request.params i get an exception, BUT when i try to get it for the second time everything is ok.

this is the filter i am using to avoid problems with the xml (i am converting it to binary data and empty the xml string field):

   public class RestAPIAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
                 ((SimulationModel)filterContext.ActionParameters["model"]).Data = CommonConverters.StringToByteArray(((SimulationModel)filterContext.ActionParameters["model"]).StringData);
            ((SimulationModel)filterContext.ActionParameters["model"]).StringData = string.Empty;


            base.OnActionExecuting(filterContext);
        }
    }

and this is the post method:

   [HttpPost]
    [ValidateInput(false)]
    [RestAPIAttribute]
    public ActionResult EditSimulation(Guid id, SimulationModel model)
    {
        try
        {
            model.RelationModel = new RelationModel(false, this.Resource("Simulations.AddToObjects"), "SimulationToObjects", id, sessionId, Request.Params, new List<ObjectTypes>() { ObjectTypes.Entity, ObjectTypes.EntityType, ObjectTypes.Universe });
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
        }

        /* more code here*/

        return View(newModel);
    }

now, as you can see one of the RelationModel's constuctor has a parameter of request.param which is giving me the problem.

my currenty workaround for this issue is just calling it twice (but i am looking for better solution or at least an explanation):

   [HttpPost]
    [ValidateInput(false)]
    [RestAPIAttribute]
    public ActionResult EditSimulation(Guid id, SimulationModel model)
    {
        try
        {
             try
            {
                model.RelationModel = new RelationModel(false, this.Resource("Simulations.AddToObjects"), "SimulationToObjects", id, sessionId, Request.Params, new List<ObjectTypes>() { ObjectTypes.Entity, ObjectTypes.EntityType, ObjectTypes.Universe });
            }
            catch
            {
                model.RelationModel = new RelationModel(false, this.Resource("Simulations.AddToObjects"), "SimulationToObjects", id, sessionId, Request.Params, new List<ObjectTypes>() { ObjectTypes.Entity, ObjectTypes.EntityType, ObjectTypes.Universe });
            }
        }
        catch (Exception ex)
        {
            Logger.LogException(ex);
        }

        /* more code here*/

        return View(newModel);
    }

Solution

  • If this is ASP.NET MVC 3+ you could use the [AllowHtml] attribute on your model property that contains the XML. This will disable request validation only for this property and not the entire request:

    public class SimulationModel 
    { 
        [AllowHtml]
        public string StringData { get; set; } 
    }
    

    and then:

    [HttpPost]
    public ActionResult EditSimulation(Guid id, SimulationModel model)
    {
        // you could directly use model.StringData here without any 
        // encoding needed
    
        return View(newModel);
    }
    

    And if this is an ASP.NET MVC 2 application running in ASP.NET 4.0 in addition to decorating your controller action with the [ValidateInput(false)] attribute you might need to put the following in your web.config:

    <httpRuntime requestValidationMode="2.0"/>
    

    If it is an ASP.NET MVC 3 application you don't need to put this line in your web.config in order to use the [ValidateInput(false)] attribute.