Update on ASP.NET MVC 3 RC2 (and a workaround for a bug in it)

Last week we published the RC2 build of ASP.NET MVC 3.  I blogged a bunch of details about it here.

One of the reasons we publish release candidates is to help find those last “hard to find” bugs. So far we haven’t seen many issues reported with the RC2 release (which is good) - although we have seen a few reports of a metadata caching bug that manifests itself in at least two scenarios:

  • Nullable parameters in action methods have problems: When you have a controller action method with a nullable parameter (like int? – or a complex type that has a nullable sub-property), the nullable parameter might always end up being null - even when the request contains a valid value for the parameter.
  • [AllowHtml] doesn’t allow HTML in model binding: When you decorate a model property with an [AllowHtml] attribute (to turn off HTML injection protection), the model binding still fails when HTML content is posted to it.

Both of these issues are caused by an over-eager caching optimization we introduced very late in the RC2 milestone.  This issue will be fixed for the final ASP.NET MVC 3 release.  Below is a workaround step you can implement to fix it today.

Workaround You Can Use Today

You can fix the above issues with the current ASP.NT MVC 3 RC2 release by adding one line of code to the Application_Start() event handler within the Global.asax class of your application:

image

The above code sets the ModelMetaDataProviders.Current property to use the DataAnnotationsModelMetadataProvider.  This causes ASP.NET MVC 3 to use a meta-data provider implementation that doesn’t have the more aggressive caching logic we introduced late in the RC2 release, and prevents the caching issues that cause the above issues to occur. 

You don’t need to change any other code within your application.  Once you make this change the above issues are fixed.  You won’t need to have this line of code within your applications once the final ASP.NET MVC 3 release ships (although keeping it in also won’t cause any problems).

Hope this helps – and please keep any reports of issues coming our way,

Scott

P.S. In addition to blogging, I am also now using Twitter for quick updates and to share links. Follow me at: twitter.com/scottgu

22 Comments

  • Thanks,i like mvc!

  • And now my website is working again.

  • Thanks for the fix!

  • Thanks for the update. I can't get approval using it around here till it has RTMed. Any idea when the final bits will be released??

  • Thanks !!! I've spent 3 days trying to understand is it EF Code First CTP 5 error or not, because if you try to request any DB context inside Action with untellable parameter, Asp.Net MVC 3 RC 2 will return very wired exception. Now - all fixed. Thanks again !

  • @Sam,

    >>>>>>>> Thanks for the update. I can't get approval using it around here till it has RTMed. Any idea when the final bits will be released??

    We'll ship the final "RTM" release of ASP.NET MVC 3 the middle of January - so not too long away now.

    Hope this helps,

    Scott

  • ViewModel in RC1 has been changed to ViewBag in RC2.
    I'm a newbie and will probably always be, but I do greatly appreciate having this framework to help me have fun developing web sites.

  • Thanks for the job you and your team have done for mvc. it is such a perfect job that the mvc framework has developed so quickly.

    The changes are perfect. Html.Raw is so smooth. My blog page was full of @MvcHtmlString.Create which was making my app look crowded.

    For the record, I am a little dissapointed that this change breaks a lot of thing in my app and I took 15 minutes to upgrade this.

    Also it would be nice to collepse razor syntax code inside the view. for instance;

    @using(Html.BeginForm()) {

    ...

    ...

    ...


    }

    that would be so useful to collapse it like we do with div, p, blackquote and so on..

  • Thanks Sir,

    It is really very helpful moreover the way you explain make it more easy :P

    Abdullah Saqib Pakistan

  • do you have a workaround for my bug yet :-)

    https://connect.microsoft.com/VisualStudio/feedback/details/630568

  • I think we should add an option to enable or disable html encoding of RazorViewengine, all my project always render html string, and I dont want add Html.Raw to all my output @..., I have some functions to clean html and prevent XSS already, I dont want html encoding by default and I decoding again.
    Html Encoding with unicode like Vietnamese language is terrible for SEO, I want it encoding utf-8 but it encoding with 1252.

    Thanks

  • Thanks,I like mvc!

  • Hi Scott

    I guess that it is correct to put a bug report here. After short google searching, this seems to be the right place.
    Below are listed 3 bugs really breaking MVC 3 functionality.
    Almost every other new "feature" (e.g. TempDataDictionary is not serializable ...) we managed to fix outside your code.
    But these are crucial.

    Tested on ASP.NET MVC 3, RC2

    1) Bug on your caching mechanism (I guess)

    public abstract class ValueController : Controller
    where TID: struct
    {
    public virtual ActionResult Detail(TID? id) {
    return View("Detail");
    }
    }
    public class LongController : ValueController{}
    public class IntController : ValueController{}


    Run "Int" first then "Long"
    Int.mvc/Detail/2
    Long.mvc/Detail/2

    The parameters dictionary contains an invalid entry for parameter 'id'
    for method 'System.Web.Mvc.ActionResult Detail(System.Nullable`1[System.Int64])'
    in 'ValueController`1[System.Int64]'.
    The dictionary contains a value of type 'System.Int32',
    but the parameter requires a value of type 'System.Nullable`1[System.Int64]'.


    Run Long first then int
    Long.mvc/Detail/2
    Int.mvc/Detail/2

    The parameters dictionary contains an invalid entry for parameter 'id'
    for method 'System.Web.Mvc.ActionResult Detail(System.Nullable`1[System.Int32])'
    in 'ValueController`1[System.Int32]'.
    The dictionary contains a value of type 'System.Int64',
    but the parameter requires a value of type 'System.Nullable`1[System.Int32]'.


    2) Fatal bug in .cshtml/razor generated compile code

    Let's have this statement
    @if(Model.Name.IsEmpty())
    {
    }

    C:\Path\Home.cshtml(7): error CS0121:
    The call is ambiguous between the following methods or properties:
    'MyOwn.Extensions.IsEmpty(string)' and
    'System.Web.WebPages.StringExtensions.IsEmpty(string)'

    It is a trap to insert using statement referencing your extensions. Remove it.
    If there will be used even only one same extension (e.g. IsEmpty()) coming from your code
    and from CORRECTLY referenced code done by user(developer)
    (@using or web.config)
    everything will fail.
    (web.config setting does not help)

    3) There is simply missing equivalent to the <%= providing not encoded string.
    Even for the simpliest stuff which cannot be encoded we (developers) will start to introduce ower own ways how to do it (extensions, methods)...

    Everything is worse, then to provide it directly by the Razor engine (@=) and make it as a standard
    (As an example (few frustrating minutes to find it):
    @culture.NumberFormat.NumberDecimalSeparator
    provides unusable "&#160;" instead of " ".
    Well but we need to pass it correctly and use int in JS,
    so I had to hack your incomplete syntax)

    Have a nice day
    Radim Köhler

  • @vietgeek: I agree with you. I would appreciate if they didn't encode by default.

  • Hi Scott

    I guess that it is correct to put a bug report here. After short google searching, this seems to be the right place.
    Below are listed 3 bugs really breaking MVC 3 functionality.
    Almost every other new "feature" (e.g. TempDataDictionary is not serializable ...) we managed to fix outside your code.
    But these are crucial.

    Tested on ASP.NET MVC 3, RC2

    1) Bug on your caching mechanism (I guess)

    public abstract class ValueController : Controller
    where TID: struct
    {
    public virtual ActionResult Detail(TID? id) {
    return View("Detail");
    }
    }
    public class LongController : ValueController{}
    public class IntController : ValueController{}


    Run "Int" first then "Long"
    Int.mvc/Detail/2
    Long.mvc/Detail/2

    The parameters dictionary contains an invalid entry for parameter 'id'
    for method 'System.Web.Mvc.ActionResult Detail(System.Nullable`1[System.Int64])'
    in 'ValueController`1[System.Int64]'.
    The dictionary contains a value of type 'System.Int32',
    but the parameter requires a value of type 'System.Nullable`1[System.Int64]'.


    Run Long first then int
    Long.mvc/Detail/2
    Int.mvc/Detail/2

    The parameters dictionary contains an invalid entry for parameter 'id'
    for method 'System.Web.Mvc.ActionResult Detail(System.Nullable`1[System.Int32])'
    in 'ValueController`1[System.Int32]'.
    The dictionary contains a value of type 'System.Int64',
    but the parameter requires a value of type 'System.Nullable`1[System.Int32]'.


    2) Fatal bug in .cshtml/razor generated compile code

    Let's have this statement
    @if(Model.Name.IsEmpty())
    {
    }

    C:\Path\Home.cshtml(7): error CS0121:
    The call is ambiguous between the following methods or properties:
    'MyOwn.Extensions.IsEmpty(string)' and
    'System.Web.WebPages.StringExtensions.IsEmpty(string)'

    It is a trap to insert using statement referencing your extensions. Remove it.
    If there will be used even only one same extension (e.g. IsEmpty()) coming from your code
    and from CORRECTLY referenced code done by user(developer)
    (@using or web.config)
    everything will fail.
    (web.config setting does not help)

    3) There is simply missing equivalent to the <%= providing not encoded string.
    Even for the simpliest stuff which cannot be encoded we (developers) will start to introduce ower own ways how to do it (extensions, methods)...

    Everything is worse, then to provide it directly by the Razor engine (@=) and make it as a standard
    (As an example (few frustrating minutes to find it):
    @culture.NumberFormat.NumberDecimalSeparator
    provides unusable "&#160;" instead of " ".
    Well but we need to pass it correctly and use int in JS,
    so I had to hack your incomplete syntax)

    Have a nice day
    Radim Köhler

  • Hi Scott,

    I have a separate issue which this workaround does not seem to solve. Reverting to RC1 seems to fix the issue which makes me think that a bug in RC2 is causing the issue. I realise the following is just an overview of what is going on, but will be happy to provide detailed information if needed.

    When issuing a POST request to "/publish/content/entityview" where the action has two parameters: a Guid, and List. JSON data is being posted, and the content type header is correctly set to "application/json".

    The issue is that, during the model binding phase, the model binder is trying to invoke the action with a Guid, and an instance of List, which of course throws an exception complaining that "The parameters dictionary contains an invalid entry for parameter 'parameters'" (referring to the parameter of type List.

    The strange this is, I have a completely unrelated controller elsewhere which contains an action which takes a parameter of List. However, when the model binder is asked to bind the incoming data to the parameters on this action, it tries to create an instance of List and of course I get the same exception (just the reversal of types). This particular action is being invoked via a normal GET request through the browser.

    The other weird thing is that these issues seem to be exclusive - when the first problem arises, the second doesn't (and vice-versa). As a test, I put a new entry into my routing table to point directly to "/publish/content/entityview" and that fixes the first issue but raises the second. Putting in a route to handle the second issue as well has no effect. Taking this custom route out again fixes the second issue but the first remains (confusing, I know!).

    The problem is it is difficult for me to see exactly what is going on, and why the model binder is getting confused between these two types in particular. The types aren't even similar in construction. They don't have the same properties, they don't inherit from one another (in fact, one is a class and the other is a struct).

    As I said, my colleague went through the pains of reverting to RC1 and re-ran the code, which all works as normal. RC2 however breaks the behaviour.

    Sorry this is a bit long - is this something your team have come across and/or can you provide any guidance?

    Many thanks

  • After installing MVC3 RC2 I am unable to open Silverlight class projects.

    It wants me to (re)install Silverlight 4.0 Tools for Visual Studio 2010, but that does not fix the problem.

  • i believe i have seen the same issue in ASP.NET MVC2. Can you confirm this?

  • I am using ViewBag for getting dynamic types to the view.The page renders without any issues. But when posting the values it throws Runtimebinderexception if the code in the view is like this.
    @if (Viewbag.something))

  • I'm using RC2 and it appeared also in RC1 ...
    whenever I make some changes to my code and Press F5 to start up the project I get this error:

    Storage scopes cannot be created when _AppStart is executing.

    Unfortuntely, I can't tell how to reproduce this, since it happens at random moments...
    I thought you might spend some time checking this bug ...
    Thanks

  • I have used this and find lot of ease in MVC 3 to use as meta-data provider
    Its well work in all environment.

  • Hi, just for your info.
    I found that by some reason line 142 in jquery.unobtrusive-ajax.js
    $("form[data-ajax=true] :submit").live("click", function (evt) {
    causes problem in IE 8 (which looks like javascript errors in jquery itself, jquery-1.4.4.js, line 3619, pos 4 and line 3635, pos 4).
    However, changing to
    $("form[data-ajax=true]").find(":submit").live("click", function (evt) {
    fixed my problem, and everything still look working for me.

Comments have been disabled for this content.