Sunday, July 31, 2011

Asp.Net MVC3 and Asp.Net Web Forms Side-By-Side in One Project.

You must have known from my previous post that, we have moved to MVC3 instead of the Web Forms approach.

While I was suggesting the clients to adopt the new MVC3 framework, the obvious question from their side was, Can the Web Forms and MVC3 co-exist?  Can the new MVC code reside in the Web Forms project?

I Googled a little, found that it was very much possible, however we needed to spike it out to be completely sure.  After some trial and errors, we were able to make the Web Forms and MVC3 code co-exist in one project.  The entire process was not very straight forward hence, I decided to write a post on how to do it.

Let's first create a bare bone ASP.NET Web Forms application.  This can be done by using the Create New Project Wizard of the Visual Studio 2010

Create new Asp.Net Web Forms Project

The Wizard generates the web.config file, master page and two pages About.aspx and Default.aspx.  Running the app at this stage should open up a page like this

Asp.Net Web Forms Default Page

Now we have an asp.net web forms application up and running.  Lets try and add the MVC3 code in the existing project and lets get it running.  This would effectively prove that Web Forms and MVC3 can co-exist.

Integrating MVC3 into the Web Forms application - How Do They Do It!

MVC3 is build on Convention Over Configuration.  Controllers in MVC3 are put in a special directory called Controllers, the views go into the Views directory.  Lets create these two directories at the root level.

Adding Directories Controllers and View

Let's add a very simple controller class called HomeController to the project.  All MVC3 Controllers need to extend the System.Web.Mvc.Controller class.  To do this, you will need to add the reference of the System.Web.Mvc.dll into the project.

Lets look at the code that goes into the HomeController

The HomeController has a very simple Index Action method.  This Index action is simply going to render the Index view.  The Action method also adds a property to the ViewBag called UserName.  We will use the UserName Property in the view.

The Index view needs to be created.  Let's create a file called Index.aspx in the Views/Home/ directory.  The Index.aspx file looks like

Notice that, the aspx page inherits the class System.Web.Mvc.ViewPage and not System.Web.Page. All MVC3 views must extend the ViewPage class.

Also Notice, how we are showing the UserName from the ViewBag using the <%= %> Syntax.  Unlike traditional ASPX pages there is no code behind for this ASPX file.  

Curious thing about Index.aspx file is that, it does not inherit from the HomeController class.  Then how can the view access the ViewBag property UserName which was set in the Controller? 

Well, the MVC3 framework implements Separation of Concerns between the View and the Controller.  But it surely needs to pass information between the Controller and View, ViewBag is just one way of doing this.  Whatever we set in the ViewBag from the Controller is available in the Views!  This is just one of the way in which you can pass information between Controller and View.

The project structure at this stage looks like

Project Structure after adding the HomeController and Index.aspx page

At this stage, if we could open up the URL http://<host name>:<port>/<your application name>/home/index then we can be sure that we have successfully integrated MVC3 in a Web Forms Project.  Lets try and browse the URL and see what we get.

404 Error When we try to browse /home/index URL

We get a The resource cannot be found (404) error.  

Why?  

This is because, we have not yet informed the framework that, when someone hits the URL /home/index then how should it be served.  This can be done by registering a new route in the Global.ascx.cs file.

This file has an Application_Start method.  This method is called when the application is started.  In this method we have to inform the framework that, when someone sends a request for the URL /home/index then, route that URL to the HomeController.  This is done using the following code

The complete code of Global.ascx.cs file looks like

Lets run the application and browse the URL /home/index lets see what happens now?

Parser Error - Could not load type 'System.Web.ViewPage'
Nope, not there yet.

Turns out that for the page to get compiled and render correctly we need to add the System.Web.Mvc in the system.web/compilation/assemblies section in the web.config. The updated web.config looks like 

The only change here was to add the assembly System.Web.Mvc to the list of assemblies under the compilation section. This will make sure that this assembly is available to the aspx view when its compiled.

After making this change lets run the app and browse the URL /home/index and lets see what happens.

Index.aspx is rendered Successfully using MVC3

Success!  We are able to render the page using MVC3 in a Web Forms application!

Notice that, currently we are using the aspx rendering engine for rending MVC3 views, in the next post I will explain how we could take advantage of the new Razor Rendering Engine in a Web Forms application.
Have some Fun!