May 2009 - Posts

I have described before in my prior post how you can run your ASP.NET MVC application in Visual Studio 2010. There is currently no support for ASP.NET MVC project types in Visual Studio 2010 Beta 1. So what I did is I created a starter kit for ASP.NET MVC 1.0 which you can download from here. Now follow the steps:

1. Execute the AspNetMvc2010.vsi, you will see the following dialog box. Proceed.

StarterKitInstall


2. Say yes to whatever comes along.

Warning


3. Now go to File > New Project, you will find ASP.NET MVC Application in Visual C# > Web tab.

ProjectCreation

 

Hope this saves some time!

You probably already know that ASP.NET MVC is not included with Visual Studio 2010 Beta1 since MVC was released when Visual Studio release was being locked down. I hope it will be available from Beta2. It also looks like if you install ASP.NET MVC after Visual Studio 2010 it does not pick up as well. So currently the only way to create and work with a MVC project is to create a project in Visual Studio 2008 and then open it with Visual Studio 2010. If you do so, it will ask you to convert this project to 2010 version which is little strange to me since there are not many things to convert from 2008 to 2010 as of yet. Anyway, so as usual you have to go through a Conversion Wizard.

ConversionError

You will notice an error while it was performing conversion. It says that the project type is not supported by this installation. You will also find the Solution Explorer is unable to load the project.

SolutionExplorer

 

Solution

1. Now its the same procedure for Visual Studio 2008 if ASP.NET MVC is not installed. Right click on the project name from the Solution Explorer and Edit.

EditProject


2. You will see the project definition XML. Seek for the line below:

<ProjectTypeGuids>{603c0e0b-db56-11dc-be95-000d561079b0};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>

3. Remove the first GUID. Save and close the file.

4. Reload the project.

ReloadProject 


5. Conversion Wizard will pop up again, now with an additional dialog box whether we would like to upgrade to .NET Framework 4.0

WebSiteTargeting

 
6. Choose whather you want. Now that the conversion is complete, you will see the report is clean.

ConversionReport

 
You are ready to go. Note that even though you can get it working with Visual Studio 2010 in this way, but you still cannot have the functionality of adding new types from Context menu such as “Add View..” and so on.

There are two different ways to build controls for ASP.NET MVC as of now. The most common way is by HTML Helper extension methods. You will find such methods being used in numerous places inside Views. Such methods can take any complexity of parameters, yet return only standard HTML tags in string format as response. Our Menu control will render a basic structure of CSS Menu, which appearance can be controlled from the site’s CSS file. So no matter which look & feel you would like to see your menu reflects, you do not have to change your Menu control. You will only have to make changes into your CSS.

Menu       Menu1

The following TextBox method renders an input tag with name “username”:

<%= Html.TextBox("username") %>

This sort of extension methods often become handy when you need to render complex or reusable controls in different Views. Today I will talk about a simple Menu control I built which renders UL/LI tags, but can take parameters ranging from string to complex types such as MvcMenuItem. Let us see an example how we would like to see Menu control to be used:

   1:  <%
   2:      var list = new List<MvcMenuItem>();
   3:   
   4:      list.Add(new MvcMenuItem{ Text = "Home", ActionName = "Index" });
   5:      list.Add(new MvcMenuItem("About", "About", "Home"));
   6:      list.Add(new MvcMenuItem("Feedback", "alert('feedback');"));
   7:  %>
   8:   
   9:  <%= Html.Menu()
  10:      .ClientId("menu")
  11:      .AddRange(list)
  12:      .HtmlAttributes(new { style="color: Red" })
  13:      .Render()
  14:  %>


From the snippet you can see, the Menu control is taking a list of MvcMenuItem class which we will create later, is being invoked from Html class and supports method calls in chain which is known as Fluent Interface. Let us take a look at how many different ways we can add menu item to the Menu control:

MvcMenu Add(MvcMenuItem item)
MvcMenu Add(string text, string actionName, string controllerName, string clientCallbackMethod)
MvcMenu Add(string text, string actionName, string controllerName)
MvcMenu Add(string text, string clientCallbackMethod)
MvcMenu Add(string text)
MvcMenu AddRange(List<MvcMenuItem> items)


I am sure you noticed the return type in every method mentioned above. It is because we have to return the current instance of the class from within every method to support Fluent Interface. Let us also take a look at the class properties of MvcMenuItem which has several constructor overloads, helpful when initializing instances. You will notince ClientCallbackMethod property which indicates if this menu item is meant to be calling a client side method. You pass a JavaScript method/code block the menu item will execute it upon user’s click.

public class MvcMenuItem
{
    public string Text { get; set; }
    public string ActionName { get; set; }
    public string ControllerName { get; set; }
    public string ClientCallbackMethod { get; set; }
}


HtmlHelper
resides in a different assembly than we are building MVC control for. So how would we write extension for it? All we have to do is, reference the System.Web.Mvc assembly and we will write the class inside that namespace too:

namespace System.Web.Mvc
{
    public static class MvcMenuExtensions
    {
        public static MvcMenu Menu(this HtmlHelper helper)
        {
            return new MvcMenu(helper);
        }
    }
}


As we are writing extension method, you will notice we followed the convention of putting it in a static class, and the static method named Menu is taking the HtmlHelper which we will pass to the MvcMenu we will be building. Constructor of the MvcMenu class is important. It takes that HtmlHelper and store it to its private variable so that it can be reused later. We need it to be reused later since we are supporting Fluent Interface.

public MvcMenu(HtmlHelper helper)
{
    Helper = helper;
    Items = new List<MvcMenuItem>();
}


As you can understand MvcMenu is the class we are writing responsible for processing menu items, and rendering. Next part is easy and straight forward. We will implement Render method which will write Menu Items for us:

   1:  public MvcMenu HtmlAttributes(object dictionary)
   2:  {
   3:      HtmlProperties = new RouteValueDictionary(dictionary);
   4:      return this;
   5:  }
   6:   
   7:  public string Render()
   8:  {
   9:      var ulTag = new TagBuilder("ul");
  10:      ulTag.MergeAttribute("id", Id ?? string.Empty);
  11:      ulTag.MergeAttributes(HtmlProperties);
  12:   
  13:      foreach (var item in Items)
  14:      {
  15:          var liTag = new TagBuilder("li");
  16:   
  17:          if(!string.IsNullOrEmpty(item.ClientCallbackMethod))
  18:              liTag.InnerHtml = string.Format("<a href=\"javascript:;\" onclick=\"{1}\">{0}</a>", item.Text, item.ClientCallbackMethod);
  19:          else
  20:              liTag.InnerHtml = Html.LinkExtensions.ActionLink(Helper, item.Text, item.ActionName, item.ControllerName ?? string.Empty);
  21:          
  22:          ulTag.InnerHtml += liTag.ToString();
  23:      }
  24:   
  25:      return ulTag.ToString();
  26:  }


We used the ActionLink method which helps us generate valid URL from Action and Controller name. We will reach up to that point only if there is no ClientCallbackMethod is defined. You will also notice the TagBuilder class which is can render a standard HTML tag for you even with specified style. Also do not forget to add the namespace in web.config:

<namespaces>
	<add namespace="TanzimSaqib.Mvc.Menu"/>
	...
</namespaces>


Download the code. Enjoy.

More Posts