Archive for the ‘aspnetmvc’ Category

MVC 3 – Supporting Custom View Engines

 
MVC 3 Preview 1 was released earlier this week. It’s packed with new features such as dependency injection, global filters and new tooling to support multiple view engines, including the new Razor view engine for C# (see the end of this post f…

Migrating ASP.NET MVC 2 applications to ASP.NET MVC 3 Preview 1

ASP.NET MVC 3 Preview 1 has just been released! More info on ScottGu’s blog.

Download ASP.NET MVC 3 Preview 1!

I just finished up a preview of my ASP.NET MVC application conversion tool to support conversions from ASP.NET MVC 2 to ASP.NET MVC 3.

The previous version of the app that converted from ASP.NET MVC 1.0 to ASP.NET MVC 2 is available here.

image

Download

The app is a single executable: Download MvcAppConverter-MVC3Preview1.zip (256 KB).

Usage

The only requirement for this tool is that you have .NET Framework 4 on the machine. You do not need to have Visual Studio or ASP.NET MVC installed (unless you want to open your project!). Even though the tool performs an automatic backup of your solution it is recommended that you perform a manual backup of your solution as well.

  • To convert an ASP.NET MVC 2 project built with Visual Studio 2010 to an ASP.NET MVC 3 project in Visual Studio 2010 perform these steps:
    • Launch the converter
    • Select the solution
    • Click the “Convert” button
  • To convert an ASP.NET MVC 2 project built with Visual Studio 2008 to an ASP.NET MVC 2 project in Visual Studio 2010:
    • Open the project in Visual Studio 2010 to convert the solution and project file formats from VS2008 to VS2010
    • Upgrade the .NET Framework target version of each project to .NET Framework 4 because ASP.NET MVC 3 is compatible with only .NET Framework 4
    • Launch the converter
    • Select the solution
    • Click the “Convert” button

What it can do

  • Open up ASP.NET MVC 2 projects from Visual Studio 2010 (no other versions of ASP.NET MVC or Visual Studio are supported)
  • Create a full backup of your solution’s folder
  • For every VB or C# project that has a reference to System.Web.Mvc.dll it will (this includes ASP.NET MVC web application projects as well as ASP.NET MVC test projects):
    • Update references to ASP.NET MVC 2
  • For every VB or C# ASP.NET MVC Web Application it will:
    • Change the project type to an ASP.NET MVC 3 project
    • Update the root ~/web.config references to ASP.NET MVC 3
    • Update the root ~/web.config to have a binding redirect from ASP.NET MVC 2 to ASP.NET MVC 3
    • Update the ~/Views/web.config references to ASP.NET MVC 3
  • Add or update the JavaScript files (add jQuery, add jQuery.Validate, add Microsoft AJAX, add/update Microsoft MVC AJAX, add Microsoft MVC Validation adapter)
  • Unknown project types or project types that have nothing to do with ASP.NET MVC will not be updated

What it can’t do

  • It cannot convert projects build with Visual Studio 2008 or with .NET Framework 3.5.
  • It can have issues if your solution contains projects that are not located under the solution directory.
  • If you are using a source control system it might have problems overwriting files. It is recommended that before converting you check out all files from the source control system.
  • It cannot change code in the application that might need to be changed due to breaking changes between ASP.NET MVC 2 and ASP.NET MVC 3.
  • The release notes include manual steps to upgrade your application.

Feedback, Please!

If you need to convert a project to ASP.NET MVC 3 please try out this application and hopefully you’re good to go. If you spot any bugs or features that don’t work leave a comment here and I will try to address these issues in an updated release.

Other Resources

There are already a bunch of blog posts, walkthroughs, and even videos on the new preview, so check them out:

Brad Wilson has a four-part post on ASP.NET MVC 3’s new dependency injection support:

Creating Visual Studio projects that only contain static files

Have you ever wanted to create a Visual Studio project that only contained static files and didn’t contain any code?

While working on ASP.NET MVC we had a need for exactly this type of project. Most of the projects in the ASP.NET MVC solution contain code, such as managed code (C#), unit test libraries (C#), and Script# code for generating our JavaScript code.

MVC 2 Solution

However, one of the projects, MvcFuturesFiles, contains no code at all. It only contains static files that get copied to the build output folder:

MVC Futures Files project contents

As you may well know, adding static files to an existing Visual Studio project is easy. Just add the file to the project and in the property grid set its Build Action to “Content” and the Copy to Output Directory to “Copy if newer.” This works great if you have just a few static files that go along with other code that gets compiled into an executable (EXE, DLL, etc.).

But this solution does not work well if the projects only contains static files and has no compiled code. If you create a new project in Visual Studio and add static files to it you’ll still get an EXE or DLL copied to the output folder, despite not having any actual code. We wanted to avoid having a teeny little DLL generated in the output folder.

In ASP.NET MVC 2 we came up with a simple solution to this problem. We started out with a regular C# Class Library project but then edited the project file to alter how it gets built. The critical part to get this to work is to define the MSBuild targets for Build, Clean, and Rebuild to perform custom tasks instead of running the compiler. The Build, Clean, and Rebuild targets are the three main targets that Visual Studio requires in every project so that the normal UI functions properly. If they are not defined then running certain commands in Visual Studio’s Build menu will cause errors.

Once you create the class library projects there are a few easy steps to change it into a static file project:

The first step in editing the csproj file is to remove the reference to the Microsoft.CSharp.targets file because the project doesn’t contain any C# code:

    <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

The second step is to define the new Build, Clean, and Rebuild targets to delete and then copy the content files:

    <Target Name="Build">
        <Copy
            SourceFiles="@(Content)"
            DestinationFiles="@(Content->'$(OutputPath)%(RelativeDir)%(Filename)%(Extension)')" />
    </Target>
    <Target Name="Clean">
        <Exec Command="rd /s /q $(OutputPath)" Condition="Exists($(OutputPath))" />
    </Target>
    <Target Name="Rebuild" DependsOnTargets="Clean;Build">
    </Target>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

The third and last step is to add all the files to the project as normal Content files (as you would do in any project type).

To see how we did this in the ASP.NET MVC 2 project you can download the source code and inspect the MvcFutureFules.csproj project file.

If you’re working on a project that contains many static files I hope this solution helps you out!

MVC 2 Source Code Released to Microsoft Reference Server

Even though we announced the release of MVC 2 (for Visual Studio 2008) on March 12, we are still working on getting a few more goodies out. And although not as awesome as canned unicorn meat (I don’t think anything can beat that), it is still very ex…

Migrating ASP.NET MVC 1.0 applications to ASP.NET MVC 2 RTM

ASP.NET MVC 2 RTM has just been released! More info on ScottGu’s blog.


I have updated the MVC App Converter to convert projects from ASP.NET MVC 1.0 to ASP.NET MVC 2 RTM.


This should be last the last major change to the MVC App Converter that I released previews of in the past several months.


MVC App Converter screen shot


Download


The app is a single executable: Download MvcAppConverter-MVC2RTM.zip (255 KB).


Usage


The only requirement for this tool is that you have .NET Framework 3.5 SP1 on the machine. You do not need to have Visual Studio or ASP.NET MVC installed (unless you want to open your project!). Even though the tool performs an automatic backup of your solution it is recommended that you perform a manual backup of your solution as well.



  • To convert an ASP.NET MVC 1.0 project built with Visual Studio 2008 to an ASP.NET MVC 2 project in Visual Studio 2008 perform these steps:

    • Launch the converter

    • Select the solution

    • Click the “Convert” button

  • To convert an ASP.NET MVC 1.0 project built with Visual Studio 2008 to an ASP.NET MVC 2 project in Visual Studio 2010:

    • Wait until Visual Studio 2010 is released (next month!) and it will have a built-in version of this tool that will run automatically when you open an ASP.NET MVC 1.0 project

    • Perform the above steps, then open the project in Visual Studio 2010 and it will perform the remaining conversion steps

What it can do



  • Open up ASP.NET MVC 1.0 projects from Visual Studio 2008 (no other versions of ASP.NET MVC or Visual Studio are supported)

  • Create a full backup of your solution’s folder

  • For every VB or C# project that has a reference to System.Web.Mvc.dll it will (this includes ASP.NET MVC web application projects as well as ASP.NET MVC test projects):

    • Update references to ASP.NET MVC 2

    • Add a reference to System.ComponentModel.DataAnnotations 3.5 (if not already present)

  • For every VB or C# ASP.NET MVC Web Application it will:

    • Change the project type to an ASP.NET MVC 2 project

    • Update the root ~/web.config references to ASP.NET MVC 2

    • Update the root ~/web.config to have a binding redirect from ASP.NET MVC 1.0 to ASP.NET MVC 2

    • Update the ~/Views/web.config references to ASP.NET MVC 2

    • Add or update the JavaScript files (add jQuery, add jQuery.Validate, add Microsoft AJAX, add/update Microsoft MVC AJAX, add Microsoft MVC Validation adapter)

  • Unknown project types or project types that have nothing to do with ASP.NET MVC will not be updated

What it can’t do



  • It cannot convert projects directly to Visual Studio 2010 or to .NET Framework 4.

  • It can have issues if your solution contains projects that are not located under the solution directory.

  • If you are using a source control system it might have problems overwriting files. It is recommended that before converting you check out all files from the source control system.

  • It cannot change code in the application that might need to be changed due to breaking changes between ASP.NET MVC 1.0 and ASP.NET MVC 2.

Feedback, Please!


If you need to convert a project to ASP.NET MVC 2 please try out this application and hopefully you’re good to go. If you spot any bugs or features that don’t work leave a comment here and I will try to address these issues in an updated release.

ASP.NET MVC 2 RC – Validating Credit Card Numbers

Today we announced the release candidate of ASP.NET MVC 2. Apart from some bug fixes, client validation has undergone some significant changes, amongst others, making it easier to work with custom validators. You can find more details about all the cha…

Migrating ASP.NET MVC 1.0 applications to ASP.NET MVC 2 Beta (updated!)

Thanks to the great feedback I’ve received on my ASP.NET MVC conversion tool for ASP.NET MVC 2 Preview 2 I’ve updated it to support conversions to ASP.NET MVC 2 Beta. I’ve included a number of bugs fixes and improvements based on the feedback:

  1. The JavaScript files have been updated to be compatible with ASP.NET MVC 2 Beta
  2. A “Scripts” folder will be automatically created if one does not already exist
  3. References to the System.Web.Mvc.dll assembly will be updated to use the fully-qualified name (public key token, etc.)
  4. UI improvements

ASP.NET MVC Solution Converter

Download

The app is a single executable: Download MvcAppConverter.zip (226 KB).

Usage

The only requirement for this tool is that you have .NET Framework 3.5 SP1 on the machine. You do not need to have Visual Studio or ASP.NET MVC installed (unless you want to open your project!). Even though the tool performs an automatic backup of your solution it is recommended that you perform a manual backup of the solution as well.

  • To convert an ASP.NET MVC 1.0 project built with Visual Studio 2008 to an ASP.NET MVC 2 project in Visual Studio 2008 perform these steps:
    • Launch the converter
    • Select the solution
    • Click the “Convert” button
  • To convert an ASP.NET MVC 1.0 project built with Visual Studio 2008 to an ASP.NET MVC 2 project in Visual Studio 2010:
    • Perform the above steps, then open the project in Visual Studio 2010 and it will perform the remaining conversion steps

What it can do

  • Open up ASP.NET MVC 1.0 projects from Visual Studio 2008 (no other versions of ASP.NET MVC or Visual Studio are supported)
  • Create a full backup of your solution’s folder
  • For every VB or C# project that has a reference to System.Web.Mvc.dll it will (this includes ASP.NET MVC web application projects as well as ASP.NET MVC test projects):
    • Update references to ASP.NET MVC 2
    • Add a reference to System.ComponentModel.DataAnnotations 3.5 (if not already present)
  • For every VB or C# ASP.NET MVC Web Application it will:
    • Change the project type to an ASP.NET MVC 2 project
    • Update the root ~/web.config references to ASP.NET MVC 2
    • Update the root ~/web.config to have a binding redirect from ASP.NET MVC 1.0 to ASP.NET MVC 2
    • Update the ~/Views/web.config references to ASP.NET MVC 2
    • Add or update the JavaScript files (add jQuery, add jQuery.Validate, add Microsoft AJAX, add/update Microsoft MVC AJAX, add Microsoft MVC Validation adapter)
  • Unknown project types or project types that have nothing to do with ASP.NET MVC will not be updated

What it can’t do

  • It cannot convert projects directly to Visual Studio 2010 or to .NET Framework 4.
  • It can have issues if your solution contains projects that are not located under the solution directory.
  • If you are using a source control system it might have problems overwriting files. It is recommended that before converting you check out all files from the source control system.
  • It cannot change code in the application that might need to be changed due to breaking changes between ASP.NET MVC 1.0 and ASP.NET MVC 2. Consult the readme for information on breaking changes.

Feedback, Please!

If you need to convert a project to ASP.NET MVC 2 please try out this application and hopefully you’re good to go. If you spot any bugs or features that don’t work leave a comment here and I will try to address these issues in an updated release.

TempData Improvements

Today, the release of ASP.NET MVC 2 Beta was announced. It’s packed with new features including client validation, an empty MVC project, and the asynchronous controller to name a few. You can visit the links below to learn more about the new features.

The Beta is only available for Visual Studio 2008. If you are using Visual Studio 2010 Beta 2 then you will need to be a bit more patient to explore these features. The Visual Studio 2010 release cycle is different from MVC and we only update the MVC bits when a new version of 2010 is released.

Apart from adding new features, we also try to improve existing ones when making a new prerelease version available. One such improvement we made in the Beta was around the behavior of TempData. TempData is used to store information that can be consumed in subsequent requests. Conceptually, TempData is MVC’s equivalent of the Flash in Ruby on Rails (RoR); barring a few behavioral differences that will be pointed out. Basic scenarios using the Post Redirect Get (PRG) pattern are well supported in MVC today, but a number of shortcomings were identified and addressed in the latest release. The code snippet below is an example of a scenario that’s supported in both MVC 1 and 2.

   1:  [AcceptVerbs(HttpVerbs.Post)]
   2:  public ActionResult Update(Person person) {
   3:      try {
   4:          /* Do some work */
   5:          TempData["Message"] = "Success";
   6:          return RedirectToAction("Result");
   7:      }
   8:      catch {
   9:          TempData["Message"] = "Update Failed";
  10:          return RedirectToAction("Result");
  11:      }
  12:  }
  13:   
  14:  public ActionResult Result() {
  15:      return View();
  16:  }

Assuming that the Result view simply renders <%= TempData["Message"] %>. the message will disappear when the user hits F5 to refresh the view, irrespective of whether or not the Update action succeeded. No problem here; that’s the expected behavior.

 

Old Behavior

Before examining the problematic scenarios, let’s look at how TempDataDictionary behaved prior to MCV 2 Beta.

  1. When an action method is invoked, the controller calls TempData.Load() to retrieve the TempDataDictionary using the current provider (SessionStateTempDataProvider by default). All the initial keys that are present in the dictionary are stored in a HashSet, X.
  2. A separate HashSet, Y, is used by TempDataDictionary to track the keys of new items that are inserted into TempData. It also tracks existing items (items that were created in the previous request) when they are updated.
  3. The controller calls TempData.Save() at the end of the request once the action method has completed. Keys in X that are not in Y are removed and the dictionary is persisted to storage using the provider.

There are two problems with the aforementioned behavior. First, items can be removed from TempData before they are consumed. Second, it is possible that items are retained too long in the dictionary. The three scenario’s described below should help to clarify how these issues are manifested.

Scenario 1: PRG

This is similar to the PRG scenario described earlier, except that when an error occurs, the action method directly renders a view instead of using RedirectToAction.

   1:  [AcceptVerbs(HttpVerbs.Post)]
   2:  public ActionResult Update(Person person) {
   3:      try {
   4:          /* Do some work */
   5:          TempData["Message"] = "Success";
   6:          return RedirectToAction("Update");
   7:      }
   8:      catch {
   9:          TempData["Message"] = "Update Failed";
  10:          return View();
  11:      }
  12:  }

The Update view correctly displays the contents of TempData when an error occurs. However, refreshing the page results in the value being rendered for a second time.

Scenario 2: Multiple Redirects

This scenario relates to actions that perform multiple redirects. TempData[“Foo”] is set by Action1, but will be removed at the end of Action2. Consequently, the view rendered in Action3 will not be able to display the contents of TempData[“Foo”].

   1:  public ActionResult Action1() {
   2:      TempData["Foo"] = "Bar";
   3:      return RedirectToAction("Action2");
   4:  }
   5:   
   6:  public ActionResult Action2() {
   7:      /* Do some more work */
   8:      return RedirectToAction("Action3");
   9:  }
  10:   
  11:  public ActionResult Action3() {
  12:      return View();
  13:  }

Scenario 3: Interleaved Requests

This is a variation on the basic PRG scenario where another request is processed before an action redirects.

   1:  public ActionResult Action1() {
   2:      TempData["Foo"] = "Bar";
   3:      return RedirectToAction("Action2");
   4:  }
   5:   
   6:  public ActionResult Action2() {
   7:      return View();
   8:  }

The expectation for the code above is that it should always work, but actually it can fail when another request is processed before the redirect in Action1 occurs. The rogue request could be the result of an AJAX call or something simple such as the user opening a new tab inside the browser (in which case SessionState is shared). The net result is that values in TempData can become lost.

 

TempData Changes

RoR provides a wrapper for the flash called now that addresses some of the problem scenarios highlighted earlier. Values written to flash.now can be read in the current action, but will not survive until the next request as illustrated by the snippet below:

   1:  1: flash.now[:floyd] = “Goodbye cruel world” # Only available in the current action   
   2:  2: flash[:arnie] = “I’ll be back”            # Next action can still access this value

Early during the design we considered adding a similar mechanism to TempDataDictionary. In the end we opted for something simpler that addressed the scenarios we wanted to solve while limiting the number of changes to the existing API. The outcome of the changes we made resulted in the following rules that govern how TempData operates:

  1. Items are only removed from TempData at the end of a request if they have been tagged for removal.
  2. Items are only tagged for removal when they are read.
  3. Items may be untagged by calling TempData.Keep(key).
  4. RedirectResult and RedirectToRouteResult always calls TempData.Keep().

API Changes

The only API change for TempDataDictionary was the introduction of the Keep() method and one overload.

public void Keep();
public void Keep(string key);

Calling Keep() from within an action method ensures that none of the items in TempData are removed at the end of the current request, even if they were read. The second overload can be used to retain specific items in TempData.

Side Effects

Beware when debugging an application and adding a watch that references an item in TempData. Reading a value from the dictionary will result in it being deleted at the end of the request, so it can potentially interfere with your debugging effort.

RenderAction

One of the many new features in the Beta release is the set of helper methods used to render actions. Actions that are executed using these helpers are considered to be child actions, so loading and saving TempData is deferred to the parent action. The child actions merely operate on the same instance of TempData that their parents have.

Providers

The default provider for TempData, SessionsStateTempDataProvider, can be replaced with a custom provider. Although doing this was supported since the introduction of the ITempDataProvider interface in MVC 1.0, we decided to make it a bit easier in MVC 2. We’ve introduced a new method in the Controller class that’s responsible for instantiating a provider; aptly named CreateTempDataProvider. For example, if you want to use the CookieTempDataProvider (part of MvcFutures), you only need to do the following in your controller:

   1:      public class CookieController : Controller
   2:      {
   3:          protected override ITempDataProvider CreateTempDataProvider() {
   4:              return new CookieTempDataProvider(HttpContext);
   5:          }
   6:      }

 

Enjoy

Have fun with the latest release of MVC. As always, comments and feedback are appreciated, so please visit the MVC forum if you have any questions or run into problems with the latest release.

Migrating ASP.NET MVC 1.0 applications to ASP.NET MVC 2

To help our customers adopt ASP.NET MVC 2 I built an application that helps upgrade Visual Studio 2008 solutions that use ASP.NET MVC 1.0 to use ASP.NET MVC 2 Preview 2. This application is inspired by Scott Hanselman’s blog post on updating ASP.NET MVC projects to work in Visual Studio 2010 Beta 1.

image

Download

The app is a single executable: Download MvcAppConverter.zip (220 KB).

Usage

The only requirement for this tool is that you have .NET Framework 3.5 SP1 on the machine. You do not need to have Visual Studio or ASP.NET MVC installed (unless you want to open your project!). Even though the tool performs an automatic backup of your solution it is recommended that you perform a manual backup of the solution as well.

  • To convert an ASP.NET MVC 1.0 project built with Visual Studio 2008 to an ASP.NET MVC 2 project in Visual Studio 2008 perform these steps:
    • Launch the converter
    • Select the solution
    • Click the “Convert” button
  • To convert an ASP.NET MVC 1.0 project built with Visual Studio 2008 to an ASP.NET MVC 2 project in Visual Studio 2010:
    • Perform the above steps, then open the project in Visual Studio 2010 and it will perform the remaining conversion steps

What it can do

  • Open up ASP.NET MVC 1.0 projects from Visual Studio 2008 (no other versions of ASP.NET MVC or Visual Studio are supported)
  • Create a full backup of your solution’s folder
  • For every VB or C# project that has a reference to System.Web.Mvc.dll it will (this includes ASP.NET MVC web application projects as well as ASP.NET MVC test projects):
    • Update references to ASP.NET MVC 2
    • Add a reference to System.ComponentModel.DataAnnotations 3.5 (if not already present)
  • For every VB or C# ASP.NET MVC Web Application it will:
    • Change the project type to an ASP.NET MVC 2 project
    • Update the root ~/web.config references to ASP.NET MVC 2
    • Update the root ~/web.config to have a binding redirect from ASP.NET MVC 1.0 to ASP.NET MVC 2
    • Update the ~/Views/web.config references to ASP.NET MVC 2
    • Add or update the JavaScript files (add jQuery, add jQuery.Validate, add Microsoft AJAX, add/update Microsoft MVC AJAX, add Microsoft MVC Validation adapter)
  • Unknown project types or project types that have nothing to do with ASP.NET MVC will not be updated

What it can’t do

  • It cannot convert projects directly to Visual Studio 2010 or to .NET Framework 4.
  • It can have issues if your solution contains projects that are not located under the solution directory.
  • If you are using a source control system it might have problems overwriting files. It is recommended that before converting you check out all files from the source control system.
  • It cannot change code in the application that might need to be changed due to breaking changes between ASP.NET MVC 1.0 and ASP.NET MVC 2. Consult the readme for information on breaking changes.

Feedback, Please!

If you need to convert a project to ASP.NET MVC 2 please try out this application and hopefully you’re good to go. If you spot any bugs or features that don’t work leave a comment here and I will try to address these issues in an updated release.

ASP.NET MVC Release Candidate 2: I declare myself to be declarative!

Today is a happy day: we released ASP.NET MVC Release Candidate 2. We’re getting ever-so-close to the final (RTM/RTW) release of ASP.NET MVC – it won’t be long! We think we fixed all the highest priority issues so that everyone out there can build ASP.NET MVC applications without worrying that we’re going to make some sudden changes that will break you. Please see Phil’s blog post announcing the release.


In this blog post I’ll introduce you to a feature that’s not even part of the main ASP.NET MVC download. It’s part of the separate MVC Futures download, which includes prototypes of features that we’re thinking of including in a future version of ASP.NET MVC.


Introduction to the MVC Controls


Before we dig into the details, let’s create a simple ASP.NET MVC application that uses the MVC Controls.


1. Download the MVC Futures binary from CodePlex.


2. Create a new MVC Web Application Project (if asked, feel free to not create a unit test project). Please note that you must have Release Candidate 2 installed. Each release of ASP.NET MVC has a matching release of MVC Futures. Mixing releases is not supported and usually doesn’t work.


01-NewProject


3. Add a reference to the MVC Futures binary. Right-click on the References node in Solution Explorer and choose “Add Reference”. Select the “Browse” tab and navigate to the location to which you saved Microsoft.Web.Mvc.dll, select the file, and select OK.


02-AddReference


03-References


4. Edit the web.config in the root of the application to include tag mappings to the MVC Futures namespace. This tells the ASP.NET parser where to locate the controls when you type in an <mvc:SomeControl> tag. There should already be some tag mappings listed – the only new tag mapping is the third one with “mvc” as the tag prefix.

<pages>
<
controls>
<
add tagPrefix=aspnamespace=System.Web.UIassembly=System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35/>
<
add tagPrefix=aspnamespace=System.Web.UI.WebControlsassembly=System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35/>
<
add tagPrefix=mvcnamespace=Microsoft.Web.Mvc.Controlsassembly=Microsoft.Web.Mvc/>
</
controls>

5. Start using the controls!


Let’s start out with a simple scenario of updating some of the Account and Membership features of the default template to use the MVC Controls.


1. Open up the ~/Views/Account/LogOn.aspx view page. The markup there should include this text box:

<%= Html.TextBox(“username”) %>

2. Change the text box markup to use the MVC TextBox control:

<mvc:TextBox runat=”server” Name=”username” />

(Please note that it sometimes takes Visual Studio a few moments to recognize new tag mappings. If Intellisense doesn’t show up, please just give it a minute.)


3. Run the application and click “Log On” at the top-right of the page.


04-Login


4. If all is well, the page should continue to have the exact same behavior as before. For example, if you immediately click “Log On” without typing in a username or password you should see the red highlight on the text box indicating an error.


05-errors


The idea of the MVC Controls is that they are largely modeled after the HtmlHelpers, and thus try to preserve all their behavior. This includes naming conventions, the markup they render, and usage of model state.


Advanced MVC Controls


For a more advanced scenario involving the MVC Controls I’d like to introduce the MVC Repeater control. In many ways it is very similar to the ASP.NET Repeater control, but the main difference is of course that the MVC Repeater has specific knowledge of ViewData.


1. In the application you already created, open ~/Controllers/HomeController.cs (Sorry, I don’t have a VB sample!) and add this new action method and two classes:

public ActionResult ProductList() {
List<Distributor> distributors = new List<Distributor> {
new Distributor { DistributorID = 501, Name = “Joe’s Shop”, Location = “Redmond, WA” },
new Distributor { DistributorID = 502, Name = “Jill’s Shop”, Location = “Los Angeles, CA” },
new Distributor { DistributorID = 503, Name = “Jeremy’s Shop”, Location = “Boston, MA” },
};

List<Product> products = new List<Product> {
new Product {
ProductID = 1001,
Name = “LEGO Technic Off Roader”,
UnitPrice = 119.99m,
Distributors = new List<Distributor> { distributors[0], distributors[1] } },
new Product {
ProductID = 1002,
Name = “Ferrari F430″,
UnitPrice = 189000m,
Distributors = new List<Distributor> { distributors[0], distributors[1], distributors[2] } },
new Product {
ProductID = 1003,
Name = “Five bedroom house in Bellevue, WA”,
UnitPrice = 540000m,
Distributors = new List<Distributor> { } },
new Product {
ProductID = 1004,
Name = “Dell 2007FP LCD monitor”,
UnitPrice = 439m,
Distributors = new List<Distributor> { distributors[2] } },
};

ViewData["products"] = products;

return View();
}

public class Product {
public int ProductID { get; set; }
public string Name { get; set; }
public decimal UnitPrice { get; set; }
public IEnumerable<Distributor> Distributors { get; set; }
}

public class Distributor {
public int DistributorID { get; set; }
public string Name { get; set; }
public string Location { get; set; }
}


2. Right-click anywhere in the action method and choose Add View with the default options and select “Add”:


06-addview


3. In the newly created view add this ASPX markup to the second content placeholder (right below the <h2> tag):

<mvc:Repeater runat=”server” Name=”products”>
<
ItemTemplate>
<
b><mvc:Label runat=”server” Name=”Name” /></b>
(PID#<mvc:Label runat=”server” Name=”ProductID” />)
$<mvc:Label runat=”server” Name=”UnitPrice” /><br />
Distributors:<br />
<
mvc:Repeater runat=”server” Name=”distributors”>
<
ItemTemplate>
- <b><mvc:Label runat=”server” Name=”Name” /></b>
(DID#<mvc:Label runat=”server” Name=”DistributorID” />),
located in <mvc:Label runat=”server” Name=”Location” /><br />
</
ItemTemplate>
<
EmptyDataTemplate>
- Sorry, there are no distributors for this item<br />
</
EmptyDataTemplate>
</
mvc:Repeater>
<
br />
</
ItemTemplate>
</
mvc:Repeater>
Please note that when you paste in the code Visual Studio might add an “ID” attribute to every control tag. You can delete all those attributes if you don’t want them – but it’s fine to leave them.

4. Run the page and you will get this nested databound rendering:


07-rendering


Advantages of MVC Controls Over Code Nuggets


If you’ve used the default WebFormViewEngine in ASP.NET MVC, you’ve certainly used this syntax somewhere in your views:



<%= Html.TextBox(“FirstName”) %>


What you might not know is that this syntax is called a “code nugget.” While there is nothing inherently wrong with using code nuggets, one advantage of using MVC Controls is that they can provide a rich design-time experience. Many developers, even those who are familiar with the intricacies of HTML and CSS, like to get an accurate preview of what their page will look like without running the application.


If you’ve used ASP.NET Web Forms and controls such as the SqlDataSource and the GridView, you’ve seen how rich a design-time experience can be. Those controls include design time rendering previews, advanced template editing, and even wizards that walk you through the steps of configuring the controls.


The MVC Controls in the MVC Futures download are just a start: they certainly don’t have the fit and finish that is seen in the SqlDataSource design-time experience. Like many rumors about ASP.NET MVC itself have stated, the beginnings of the MVC Controls were in fact written on an airplane!


Compare the areas in the following screen shot of the text box we created earlier to see the difference. The MVC Control has a proper preview, whereas the HTML Helper doesn’t render at all.


08-DesignView


Disadvantages of MVC Controls


One of the biggest disadvantages of the MVC Controls is that there is a rather immediate limit to how you can use them. For example, take this relatively simple scenario with the regular TextBox HtmlHelper:

<%= Html.TextBox(“FirstName”, Model.FirstName.ToUpper()) %>

There is no simple way to do this with the MVC Controls because there is no place to add your own code to pre-process the values.


Another disadvantage is that the MVC Controls work only with the WebFormViewEngine. There are several other view engines out there that people have been using with ASP.NET MVC. Some of the popular third party view engines out there are Spark view engine, NHaml, and the view engines included in the MVC Contrib project, which are Brail, NVelocity, and XSLT.


For ASP.NET MVC 1.0 we decided on the MVC team to focus our efforts on features that have the widest possible benefit. In this case it meant writing helpers that worked with as many different view engines as possible.


As a slight bit of humor (though it’s in fact serious), please refer to Eric Lippert’s blog post How many Microsoft employees does it take to change a lightbulb?


The Future of the MVC Controls


As I mentioned in the top of the post, the MVC Controls are just a prototype. They are not complete; they are not set in stone; and there is no guarantee that they will ever be part of the main ASP.NET MVC download.


I already have a long list of improvements to make to the MVC Controls. I plan to add many more controls as well as more advanced features to existing controls.


If you have any feedback, comments, or suggestions on the MVC Controls feel free to post them here. We take all feedback seriously!


Some questions to think about:



  1. Do you see yourself using the MVC Controls?

    • If so, why?

    • If not, why not?

  2. What MVC Controls would you see yourself using the most? (Even ones that don’t exist yet.)