ASP.NET MVC 3 RC Bug and Quick Solution

Update:  This issue has been fixed.

 

     Introduction:

          ASP.NET MVC 3 RC includes a cool feature called Granular Request Validation which allows you to make request validation granular by introducing a new attribute SkipRequestValidationAttribute. All your model properties with this attribute are not validated during request validation. For further details of this new feature please see Granular Request Validation in ASP.NET MVC 3. However there is a bug in this new feature that when you bind FormCollection or use Request.Form, Request.QueryString (and so on) which contains HTML input then it throws a dangerous input exception even you use ValidateInput(false). So in this quick article, I will show you the work around of this bug. But I am sure that in RTM release this bug will be fixed.

 

    Description:

          The quick work around of this bug(provided by Levi genius) is to remove FormCollection parameter from the action method and instead use Request.Unvalidated().Form inside your action method body. Unvalidated is an extension method present in System.Web.Helpers namespace. See this thread for details. This may be easy for you to change up to 5 methods manually but if you have hundred of action methods then it may be difficult to change all action methods manually. That's why I created a regular expression which automatically do this.

 

          First of all you need to add a reference of System.Web.Helpers namespace which contains the Unvalidated extension method. So open Find and Replace window. Select Look In: "Entire Solution" or "Current Project" and checked the Use: "Regular expressions". Then type using System.Web.Mvc;[ ]*{\n} in the Find what box and type using System.Web.Mvc;\1using System.Web.Helpers;\1 in the Replace with box.

 

 

         

 

 

          Now you need to remove the FormCollection parameter and add this line inside your method body,

 

          FormCollection form = new FormCollection(Request.Unvalidated().Form);

 

          Again open Find and Replace window. Select Look In: "Entire Solution" or "Current Project" and checked the Use: "Regular expressions". Then type ({[(]}:Wh*FormCollection:Wh*{[^,)]*}:Wh*[,]*)|([,]:Wh*FormCollection:Wh*{[^,)]*}){}{([^{]|\n)*[{]}[ ]*{\n} in the Find what box and type \1\5\6\t\t\tFormCollection \2\3 = new FormCollection(Request.Unvalidated().Form);\6 in Replace with box.

 

 

 

          

 

 

          If you have the following actions in your project,

 

        public ActionResult ActionA(FormCollection form1)
        {
            return View();
        }
        public ActionResult ActionB(int i,FormCollection form)
        {
            return View();
        }
        public ActionResult ActionC(int i, FormCollection formABC, string j, [Bind(Include = "Name,Address")] Student s)
        {
            return View();
        }
        public ActionResult ActionD(int i, string j,FormCollection f , string k, string t)
        {
            return View();
        }
        public ActionResult ActionE(FormCollection form123, string t, string t2)
        {
            return View(new Student { Age = 30, Name = "Akbar" });
        }

 

 

          Then using the above method, it will be converted to the following actions,

 

        public ActionResult ActionA()
        {
            FormCollection form1 = new FormCollection(Request.Unvalidated().Form);
            return View();
        }
        public ActionResult ActionB(int i)
        {
            FormCollection form = new FormCollection(Request.Unvalidated().Form);
            return View();
        }
        public ActionResult ActionC(int i, string j, [Bind(Include = "Name,Address")] Student s)
        {
            FormCollection formABC = new FormCollection(Request.Unvalidated().Form);
            return View();
        }
        public ActionResult ActionD(int i, string j, string k, string t)
        {
            FormCollection f  = new FormCollection(Request.Unvalidated().Form);
            return View();
        }
        public ActionResult ActionE( string t, string t2)
        {
            FormCollection form123 = new FormCollection(Request.Unvalidated().Form);
            return View(new Student { Age = 30, Name = "Akbar" });
        }

 

          Finally if you are using Request.Form, Request.QueryString, Request.Cookies or Request.Headers then just replace them with Request.Unvalidated().Form, Request.Unvalidated().QueryString, Request.Unvalidated().Cookies, and Request.Unvalidated().Headers.

 

          Update: If you have any problem using method overloading after using the above regex then instead Replace,

          ({[(]}:Wh*FormCollection:Wh*{[^,)]*}:Wh*[,]*)|({[,]}:Wh*FormCollection:Wh*{[^,)]*}):Wh*{[,)]}{([^{]|\n)*[{]}[ ]*{\n}

           With

           \1\3string unused\5\6\7\t\t\tFormCollection \2\4 = new FormCollection(Request.Unvalidated().Form);\7

    Summary:

           In this article I showed you a bug in MVC 3 RC and showed you how you can work around this bug quickly in your application using Regular Expression feature of Visual Studio. Hopefully you will enjoy this article too.

 

Published Sunday, November 14, 2010 1:25 PM by imran_ku07

Comments

# Twitter Trackbacks for ASP.NET MVC 3 RC Bug and Quick Solution - Imran Baloch's Blog [asp.net] on Topsy.com

Pingback from  Twitter Trackbacks for                 ASP.NET MVC 3 RC Bug and Quick Solution - Imran Baloch's Blog         [asp.net]        on Topsy.com

# re: ASP.NET MVC 3 RC Bug and Quick Solution

Monday, November 15, 2010 9:17 PM by Brett Live

thanks for sharing. Appreciate it!

# re: ASP.NET MVC 3 RC Bug and Quick Solution

Tuesday, November 23, 2010 9:50 AM by Simon Bartlett

This isn't a bug. The SkipRequestValidationAttribute is only for use on view models and when used with a model-binder, and the MSDN blog you link to clearly states this.

Using the FormCollection or use Request.Form, Request.QueryString bypasses this mechanism.

The blog post you linked to suggests setting ValidateInputAttribute to false on your action method instead; [ValidateInput(false)]

# re: ASP.NET MVC 3 RC Bug and Quick Solution

Tuesday, November 23, 2010 11:21 AM by imran_ku07

@Simon just see this thread,

forums.asp.net/.../1621677.aspx

# re: ASP.NET MVC 3 RC Bug and Quick Solution

Tuesday, November 23, 2010 1:39 PM by Simon Bartlett

Ok, the SkipVerification model attribute doesn't have a bug - as your Introduction implies. But in fact the ValidateInput action attribute potentially has a bug. An intro that was perhaps clear and concise would have prevented me from getting the wrong message :)

# re: ASP.NET MVC 3 RC Bug and Quick Solution

Tuesday, November 23, 2010 9:53 PM by imran_ku07

@Simon,

Just see the Microsoft.Web.Infrastructure.dll for granular validation. It will make you clear that what is happening.

# re: ASP.NET MVC 3 RC Bug and Quick Solution

Saturday, December 18, 2010 11:10 AM by Johnnyo

Is this still a problem with mvc 3 rc2?

# re: ASP.NET MVC 3 RC Bug and Quick Solution

Sunday, December 19, 2010 6:20 AM by imran_ku07

@Johnnyo,

The error is has been fixed.

So if have a ?UserName=<script> querysting and you have not used it anywhere.

public ActionResult Action()

then no exception will raised.

But if you use this in model binding,

public ActionResult Action(string UserName)

then an exception is raised,

If you use this

[ValidateInput(false)]

public ActionResult Action(string UserName)

then no exception will raised.

But if use Request.QueryString["UserName"]

[ValidateInput(false)]

public ActionResult Action(string UserName)

{

var s=Request.QueryString["UserName"];

then even with ValidateInput(false), an exception is raised,

# re: ASP.NET MVC 3 RC Bug and Quick Solution

Monday, December 20, 2010 12:44 AM by Johnnyo

Thanks imran.  I'll download MVC 3 RC2 and try it out.

# re: ASP.NET MVC 3 RC Bug and Quick Solution

Monday, December 20, 2010 1:25 AM by Johnnyo

Tried MVC 3 RC2 and ValidateInput(false) now works properly.  Thanks.

Leave a Comment

(required) 
(required) 
(optional)
(required)