RSS

Tag Archives: Code Nuggets

ASP.NET MVC – RadioButtonList and a Code Nugget issue with Generics

I’ve been reading about a RadioButtonList that used to exist in MVC Futures but was removed from the release. There are different solutions in the forums for this, suggesting various implementations. I decided to combine some of the ideas into an extension method, which creates a radio button list with LABEL FORs. It also checks the selected OPTION, and provides a wrapping div with css class that can be easily used. This looks like this:

  • Lines 24-27 & 38-41 contain a wrapping div, in case a css class for a container was specified.
  • Lines 30-35 is where the important stuff resides: iterate over the items of the dictionary (line 18), and create radio buttons with corresponding LABEL FORs.

Although this was sufficient, I decided to take this one step further and create another extension method especially for enum types. This method creates the dictionary out of an enum, and the label’s text out of a local resource file (using LocalResX which was demonstrated some time ago here). This is how it looks:


Now all I had to do was call the new extension method from the View, or so I thought. This was my code (note that Visual Studio failed to color the generic part and the rest of the arguments):

Much to my surprise, I received the following compilation error:

CS1502: The best overloaded method match for ‘System.Web.WebPages.WebPageExecutingBase.Write(System.Web.WebPages.HelperResult)’ has some invalid arguments“.

Say what??

After some experimenting, I replaced the generic <T> with an argument of Type in the extension method, removed the <DayOfWeek> from my View and replaced it with a “typeof(DayOfWeek)” – it solved the problem. But hey, what if I did prefer to use generics? Why did the View fail to compile when I placed the generic on my extension method?

What I had done was to compare the resulting compilation of a successful non-generic implementation (using Reflector), and the failed compilation source code (from the Compilation Error page, simply click on the “Show Complete Compilation Source” to view the source code), and I noticed what had happened here:

What happened was that the View failed to recognize the generic call to the extension method, and assumed that RadioButtonList was a property, or a “HelperResult”, as the compiler error states. Check it out in the screenshot above – Html.RadioButtonList should have been called like a method with parentheses! After that I understood that the fact that Visual Studio did not cope and color the generic call in the View wasn’t a designer coloring bug as I initially thought, but rather what seems to be like a Razor bug.

I still wanted to solve this and use generics instead of passing a “typeof” argument. So what I had to do was recall the Razor Code nuggets vs. Code blocks post from a while back on how to replace the call to Write( ), performed by using a Code nugget (@), with a Code block. I made the changes:

Now I received another compilation error, but it was a whole lot better and simply stated that the result of the RadioButtonList<T> extension method is an MvcHtmlString, whereas Html.Raw expects a string. Well, I’m not sure if MS should have provided an implicit conversion method from string to MvcHtmlString and vice versa, and I wasn’t sure I wanted to do it myself, so I had to choose between calling MvcHtmlString’s ToHtmlString( ) method from the View, or from the extension method and return a string instead. I chose the latter, because I wanted to View’s code to remain cleaner, especially if this method will be reused. So, one more time:

Now the View compiled successfully. Checking the assembly with Reflector showed what I expected:

As you can see, now the code calls the RadioButtonList<T> extension method as expected. The resulting string is sent to Html.Raw and from there to the Write(…) method (which was auto-generated by Razor as a result of using ‘@’).

Although this was worked around, I still expect that Razor will support calling generic methods using a Code nugget and not only via a Code block. It’s certainly possible that I’m missing something here, and sure, the workaround isn’t too bad, but it’s just one of those things which make you feel like it’s a “breach” that wasn’t taken care of, and it also was time consuming. I also wonder why MS dropped the RadioButtonList method that was said to exist back in the previews. I guess that it’s written somewhere on the web…

Advertisements
 
2 Comments

Posted by on 12/06/2011 in Software Development

 

Tags: , , , , , ,

ASP.NET MVC Razor Code nuggets vs. Code blocks

There’s a difference between Code Nuggets and Code blocks in Razor. A “Code Nugget” is simply the usage of the @ sign which indicates a server-side “self contained” code block. For example:

1:  @Model.Name

This will basically print out a string. Resembles ASP.NET’s somewhat cumbersome <%= %>, but a lot more tidy and clean. No doubt this is very convenient.

However, if you require a “server side” code block, Razor allows opening a server side code block using @{ }. For example, say you want to print out a Model’s property, only it contains data:

1:  @{
2:     if (!string.IsNullOrWhiteSpace(Model.Name))
3:     {
4:         Html.Raw(Model.Name);
5:     }
6:  }

Note line 4: Html.Raw( ) is a helper method which simply outputs a text. Interesting enough, as opposed to the previous sample code, this code renders nothing to the browser, despite the fact that Mode.Name is not empty.

I went on and tried the following:

1:  @Html.Raw(Model.NickName)
2:  @{ Html.Raw(Model.NickName); }

As you might have guessed, line 1 provided the desired output while line 2 rendered nothing. Puzzled, I went to the Reflector and found out the following:

Code Nugget vs Code Block

Line 1 compiled into a this.Write(…) method, and line 2 resulted in a simple base.Html.Raw(…) call. This explained several things which in retrospect became obvious:

  1. A Razor code block is, basically, well, just a code block. This means that it will not output the text just because Html.Raw(…) is being called.
  2. Moreover, Html.Raw(…) does not render anything to the output stream by itself.
  3. A Code Nugget is compiled as a this.Write(…) method call.
  4. If we want to render something to the output stream from a code block, we should explicitly mention it, either by calling Write(…)/WriteLiteral(…), or simply by specifying a Code Nugget from within the code block itself. In other words, the following examples work well (note the @ signs emphasized in red):
1:  @{ @Html.Raw(Model.Name); }

And so does this:

1:  @{
2:     if  (!string.IsNullOrWhiteSpace(Model.Name))
3:     {
4:         @Html.Raw(Model.Name);
5:     }
6:  }

One final word about this topic. Re-examining Scott Gu’s blog, specifically the examples in the “Identifying Nested Content”, demonstrates the above “conclusion” explicitly. Nevertheless, apparently it was easy to miss, forget, or maybe it was just confusing till I experienced this myself. At least it resulted in a better understanding of the compiled Razor output.

 
4 Comments

Posted by on 14/02/2011 in Software Development

 

Tags: , , , , ,