RSS

Tag Archives: Razor

MVC 4 Code Enhancements

Here are 2 minor nice enhancements for MVC 4.

Conditional Attribute Enhancements
This enhancement is something I really like. If you are accustomed to write server-side code embedded with HTML, you probably ran into ugly spaghetti code like this:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    @{
        string css = "myDiv";
    }
    <div class='@{ if (css != null) {<text>@css</text>} }'></div>
</body>
</html>

In MVC 4, one enhancement allows you to save quite a lot of spaghetti confusing code, by interpreting the Code Nugget for you, like so:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    @{
        string css = "myDiv";
    }
    <div class='@css'></div>
</body>
</html>

Even more, you can really shorten things by inserting lengthy strings and render less HTML:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    @{
        string css = "class=myDiv";
    }
    <div @css></div>
</body>
</html>

Note that if you would have used apostrophes, they would have been HTML encoded. So this:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    @{
        string css = "class='myDiv'";
    }
    <div @css></div>
</body>
</html>

is rendered like this:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
 <div class=&#39;myDiv&#39;></div>
</body>
</html>

If you would like to avoid encoding, just use Html.Raw( ) as usual:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    @{
        var css = @Html.Raw("class='myDiv'");
    }
    <div @css></div>
</body>
</html>

Note that Html.Raw returns an IHtmlString, and this works just as well. It seems like the Code Nugget simply performs a ToString( ) with HTML encoding on the given variable. This can be tested easily. Consider this code:

using System.Web.Mvc;

namespace MVCEnhancements.Controllers
{
    public class MyModel
    {
        public override string ToString()
        {
            return "t'is my code";
        }
    }
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View(new MyModel());
        }
    }
}

and the corresponding cshtml (note the @Model in line 9):

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    @{
        var css = @Html.Raw("class='myDiv'");
    }
    <div @css>@Model</div>
</body>
</html>

This renders the following:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <div class=&#39;myDiv&#39;>t&#39;is my code</div>
</body>
</html>

As you can well see, ToString( ) was called and it was also Html Encoded.

URL Resolution Enhancements
Instead of using Url.Content with a tilde,

<!DOCTYPE html>
<html>
<head>
    <script src='@Url.Content("~/Scripts/jquery-1.6.2.js")'></script>
</head>
<body>
    <div>
    </div>
</body>
</html>

You can just use the tilde like so:

<!DOCTYPE html>
<html>
<head>
    <script src='~/Scripts/jquery-1.6.2.js'></script>
</head>
<body>
    <div>
    </div>
</body>
</html>
 
2 Comments

Posted by on 20/05/2012 in Software Development

 

Tags: , ,

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…

 
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: , , , , ,

Rendering JavaScript using Razor, including non-escaped characters

NOTE: This post uses a variant of the LocalResX extension method written and described in an earlier post, only suited for usage with HtmlHelper: http://evolpin.wordpress.com/2011/02/05/asp-net-mvc-resources/.

I wanted to render a JavaScript array, which was built of several server side resources. Similar to Classic ASP, MVC easily supports embedding client and server side code. This looks something like this:

1: var myArray = [ @for(int i = 1; i <= 10; i++)
2:                  {
3:                     @string.Format("'{0}'", Html.LocalResX("Item" + i.ToString()));
4:                  } ];

However, there were two problems:

  1. I needed a comma in between the client array items.
  2. The apostrophe (and eventually the comma too) are rendered as encoded escaped characters.

The thing is, I had no idea how to render simple text (i.e. a “comma”) to the client from a Razor block. When HTML elements are involved, you just write the HTML. When non-html is involved (such as JavaScript, as in this case), this is different. You can’t just write a comma in the middle of a Razor block and expect it to be rendered (this results in a “ CS1525: Invalid expression term ‘,’“).

One solution was specified in Scott Gu’s blog, about using <text> for rendering simple code from Razor blocks. This looks like this:

1:var myArray = [ @for (int i = 1; i <= 10; i++)
2:                 {
3:                     @string.Format("'{0}'", Html.LocalResX("Item" + i.ToString()));
4:                     if (i < 10){
5:                          <text>,</text>
6:                     }
7:                 } ];

Although an acceptable solution, the result seems to be rendered with extraneous newline characters, which was not the desired result. Besides, it did not solve the escaped characters of the string itself. I looked some more and found out that there are other alternatives to do this, such as to use HtmlHelper’s Raw method, which does not encode the characters and simply renders the text “as is”. The result is as follows:

1:var myArray = [ @for (int i = 1; i <= 10; i++)
2:                 {
3:                     @Html.Raw(string.Format("'{0}'", Html.LocalResX("Item" + i.ToString())));
4:                     if (i < 10){
5:                         @Html.Raw(", ");
6:                     }
7:                 } ];

This solved both problems.

Regardless, one thing which I find weird in Razor, is that once you open a Razor code block, you have to familiarize yourself with when you should or shouldn’t specify the @ sign. For example, if I omit the @ prior to Html.Raw (line 3), no compilation error would occur, but the server will render nothing. That is, it’ll completely ignore the entire code statement. On the other hand, if I specify @ prior to the if { … } block (line 4), a compilation error will occur upon render, claiming that: “ Unexpected “if” keyword after “@” character.  Once inside code, you do not need to prefix constructs like “if” with “@”“. Basically, this is understandable at times, but inconsistent: In Scott Gu’s “Introducing Razor” he demonstrates ‘if’ blocks using the @ sign. True, these code blocks are not nested within other Razor code blocks, but this shows the inconsistency.

 
Leave a comment

Posted by on 13/02/2011 in Software Development

 

Tags: , , , ,

ASP.NET MVC Resources

Implementing a multilingual web application is something I see as crucial, in order to address a larger crowd of people. In ASP.NET Web Forms, this was very easy to accomplish using the ‘$’ or meta:resourceKey, and the code behind relevant methods. In ASP.NET MVC I’m uncertain if this is inherently supported so I was searching for a way how to accomplish this. Global resources behave the same: ASP.NET infrastructure auto-generates a Resource class which can be used in exactly the same manner as in Web Forms. For example, if I have a GlobalResources.resx file, a GlobalResources class will be auto-generated containing static properties, which can be used as follows:

1: <li>@Html.ActionLink(Resources.GlobalResources.Home, "Index", "Home")</li>

Local resources, however, are not auto-generated classes. Looking around the web I came across an interesting post on how to use Local Resources using an extension method. This was great, but I was looking for some implementation that will: 1) Use a single “resource key” as an argument, and 2) Will be “context aware”, so that if the context is a layout (“Master page”), it’ll use local layout resources, and if the context is a page, it’ll use local page resources. After performing some experiments and debugging, I learned two interesting things using the excellent .NET Reflector (see pic below):

  1. Layouts and Pages are both considered as “pages” as they inherit from “WebViewPage”, making them both “pages” (Web Form’s MasterPage does not inherit from Page class, but from UserControl).
  2. Despite that, layouts seem to be compiled to a different assembly than pages.

MVC page inheritance
Knowing that this is the same class hierarchy, I used a single method to accomplish the local resource handling. This resulted in the following extension method:

1: public static string LocalResX(this WebViewPage page, string key)
2: {
3:     var  value = page.ViewContext.HttpContext.GetLocalResourceObject(page.VirtualPath, key) as string;
4: #if  DEBUG
5:     if  (string.IsNullOrWhiteSpace(value))
6:         value = string.Format("*{0}*" , key.ToLowerInvariant());
7: #endif 
8:     return value;
9: }

Line 3 performs the two relevant things:

  1. Using the WebViewPage base class we have access to the ViewContext->HttpContext->GetLocalResourceObject, which is what retrieves the resource.
  2. the page.VirtualPath is what “differentiates” the Layout from the Page “resource context wise” . So when we’re in layout context, this will return the layout’s path. When in page context, this will return the page’s path. This is what ASP.NET needs in order to return the correct resource file.

Lines 4-7 are not really essential. They simply help in pointing out resource keys which do not exist in the resource file yet. This can also be logged to a log file.

The resulting code:

1:<li>@Html.ActionLink(Resources.GlobalResources.Home, "Index", "Home")</li> 
2:<li>@Html.ActionLink(this.LocalResX("Blog"), "Blog", "Home")</li>

Line 1 demonstrates a GlobalResource usage.

Line 2 shows the Local Resources implementation.

 
3 Comments

Posted by on 05/02/2011 in Software Development

 

Tags: , , , ,

Getting acquainted with ASP.NET MVC

After several years of professional development mainly in ASP.NET Web Forms (1.x, 2, 3.5 and 4), I have decided to start learning ASP.NET MVC. The general idea was to learn a different web development technique in .NET, in order to be able to decide in the future which technology is more suitable per project requirements. I remember reading post(s) several years ago which stated that basically web forms is a “sort of MVC”, long before ASP.NET MVC was developed (or so I think). The markup being the View, the code behind was the Controller, and the data objects were the Model. Apparently this isn’t the case.

It is my impression that there’s a really large buzz around ASP.NET MVC and I’m curious whether this is “justifiable”. In my MVC-newbie eyes, ASP.NET MVC code resembles classic ASP: Server side code is embedded within Client side code (or is it the other way around??). I did enjoy classic ASP at the time, before ASP.NET, but I really wouldn’t want to return to those days. In short, MVC “better be worth the buzz”.

In order to learn ASP.NET MVC, I have decided to take on a “pet” project. I believe that developing a “real world” project is the better way of learning programming. You can watch sample code or video lectures, but I believe that hands-on development is when you really get to know things. Just like in driving: you can learn theory as much as you want, but it doesn’t mean that you can drive. You know how to drive only after you have practiced driving. And the more you drive and gain experience, the better driver you become. So, every now and then I (re)write projects in new technologies. This “pet” project is not only designated to learn MVC, but other stuff too, such as the Entity Framework 4, JQuery UI and others. I also intend on using professional but free templates I found in http://www.freewebtemplates.com.

So, in order to learn ASP.NET MVC I have taken several steps. I believe that the first steps were to view some of Scott Hanselman video intros. Those videos led me to other interesting posts. So far I can recommend those:

  1. MVC basics: although this relates to MVC2 (MVC3 just been released), its a great “hello world” video.
  2. While we’re at it, I thought it’s a good idea to start MVC with the new Razor View engine. So Scott Gu has a good intro post on razor.
  3. Scott Hanselman has several Ninja tips videos which are quite useful: http://channel9.msdn.com/Blogs/matthijs/ASPNET-MVC-2-Ninja-Black-Belt-Tips-by-Scott-Hanselman and http://www.hanselman.com/blog/PDC09ASPNETMVC2NinjasStillOnFireBlackBeltTips.aspx. Note: I don’t quite remember if they have overlapping tips or not.
  4. In one of the lectures, Scott recommended the Route Debugger. This is really a great utility.
  5. For using Ajax in MVC, I read this great post: http://dotnetslackers.com/articles/aspnet/ASP-NET-MVC-2-0-and-AJAX-Part-1.aspx.

After being through these, I experimented some of the stuff on one or two sample MVC projects. Once I felt confident enough with the basics, I started my pet project, today.

 
3 Comments

Posted by on 30/01/2011 in Software Development

 

Tags: , , ,

 
Follow

Get every new post delivered to your Inbox.

Join 67 other followers