开发者

A potentially dangerous Request.Form value was detected

I have a form with the wmd editor on it. The input text area is 开发者_如何学编程rendered using:

<%: Html.TextAreaFor(t => t.NewsBody, new{@class="wmd-panel", id="wmd-input"}) %>

Every time I submit the form I get A potentially dangerous Request.Form value was detected from the client

I tried setting [ValidateInput(false)] on the action method, I tried adding <httpRuntime requestValidationMode="2.0" /> to the web.config and I've tried validateRequest="false" in the pages directive in web.config but it's still happening.

Any ideas?

Edit

Action method:

 [ILFFAuthorize(Roles = "Admin")] // this is a custom auth attrobite
        [HttpPost]
        [ValidateInput(false)]
        public ActionResult AddNews(FormCollection col){

        //public ActionResult AddNews(News news)
        //{
            if (ModelState.IsValid)
            {
                News news = new News();
                news.NewsDate = DateTime.Now;
                news.NewsPosterId = 0;

                news.NewsTitle = col["NewsTitle"];
                news.NewsBody = col["NewsBody"];
                newsRepository.Add(news);
                newsRepository.Save();

                return RedirectToAction("Index", "Home");
            }
            else
            {
                return View();
            }
        }


You need to place this on top of your [HttpPost] action method

    [HttpPost]
    [ValidateInput(false)]
    public ActionResult Edit(FormCollection collection) {
       .....
    }

If you are using MVC3 then you should't use [ValidateInput(false)] but use [AllowHtml] which is explained here: http://dailydotnettips.com/2011/08/24/how-to-allow-user-to-input-html-in-asp-net-mvc/

also: try putting [ValidateInput(false)] above your [HttpPost] not under, As I remember, these get executed top to bottom.


In MVC 3, Add [AllowHtml] to the property in the view model that you want to not be validated.


In the web.config file, within the tags, insert the httpRuntime element with the attribute requestValidationMode="2.0". Also add the validateRequest="false" attribute in the pages element.

Example:

<configuration>
  <system.web>
   <httpRuntime requestValidationMode="2.0" />
  </system.web>
  <pages validateRequest="false">
  </pages>
</configuration>


The general rule of thumb is that you will get that error when posting to an action method that does not allow potentially dangerous form values. If you take that into consideration along with the fact that you have obviously chosen to allow such values on a given action method, you must conclude that you are somehow posting to a different action method.

Can you try posting a standard string (i.e. "hello") without WMD and checking to see if your breakpoints in the selected action method are reached?


use [ValidateInput(false)] to resolve these type of error

This happens because user input contains various html tags.So MVC3 architecture doesn't have permission for this kind of input.

We can remove this error writing [ValidateInput(false)] above a action result or where we are submitting our form. This command will disable the form validation for html tags.


I tried to find a solution to this problem whole day.
Disabling validation was not an option.
Adding allowHtml was not an option either, because by msdn specification:
AllowHtmlAttribute allows a request to include HTML markup during model binding by skipping request validation for the property. source

Also, there are a lot of properties with string attributes within a project that should be validated if the default validation is set to false.

Solution:

I have created a CustomRequestValidation class:

public class CustomRequestValidation : System.Web.Util.RequestValidator
{
    protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
    {
        validationFailureIndex = -1;
        if (requestValidationSource == RequestValidationSource.RawUrl)
            return true;

        if (requestValidationSource == RequestValidationSource.Form)
        {
            var isValid = base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);
            if (!isValid)
            {
                validationFailureIndex = -1;
                return true;
            }
        }

        return base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);
    }
}

what it does is that it simply skips RequestValidation for the purpose of reaching model state.

Next I have overriden the default model binder:

public class CustomModelBinder : DefaultModelBinder
{

    protected override bool OnPropertyValidating(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor, object value)
    {
        if (value != null)
        {
            if (propertyDescriptor.PropertyType == typeof(string))
            {
                string val = value.ToString();
                int validationIndex;
                var isValid = new System.Web.Util.RequestValidator().InvokeIsValidRequestString(controllerContext.HttpContext.ApplicationInstance.Context, val, RequestValidationSource.Form, null, out validationIndex);
                if (!isValid && !propertyDescriptor.Attributes.OfType<AllowHtmlAttribute>().IsAny())
                {
                    var key = CreateSubPropertyName(bindingContext.ModelName, propertyDescriptor.Name);
                    bindingContext.ModelState.AddModelError(key, ErrorConstants.SpecialCharacters);
                }
            }
        }

        return base.OnPropertyValidating(controllerContext, bindingContext, propertyDescriptor, value);
    }
}

Now here we do all the validation. In model binder I call the default .Net IsValidRequestString method along with a check if AllowHtml was set and I set the model state accordingly. It gives me control over the data and I can go back to the page and fill back the form with previously entered data without firing off inserted scripts. I am using strongly-typed models.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜