MVC#

ASP.NET MVC 2 RC 2 & VS 2010 RC

Posted in ASP.NET MVC, Controllers, jQuery, Views by BlueCoder on 17/02/2010

Abstract: Visual Studio 2010 RC comes with MVC 2 RC 1 but if you had VS 2008 with MVC.NET 2 RC 2 installed ,as Phil Haack mentioned in his blog post, when you install VS 2010 RC you have using RC 2 version of MVC.NET automatically but without new item and project templates. In this post I’m going to show how you can manually use the latest version of templates which comes with RC 2 release of MVC.NET. I assumed you had installed VS 2008 with MVC.NET 2 RC 2 and then installed VS 2010 RC now want to update to latest version of templates. You can use this idea to install any other version of MVC.NET which comes in future.

Step 1: We are going to change the files in these locations:

Microsoft Visual Studio 10.0\Common7\IDE\ItemTemplates\CSharp\Web\MVC 2\
Microsoft Visual Studio 10.0\Common7\IDE\ItemTemplatesCache\CSharp\Web\MVC 2
Microsoft Visual Studio 10.0\Common7\IDE\ProjectTemplates\CSharp\Web\1033\
Microsoft Visual Studio 10.0\Common7\IDE\ProjectTemplatesCache\CSharp\Web\1033

So before we have chance to ruin all of our VS 2010 templates we are going to back up these files. Although we are not going to change all of files in these locations but I suggest you back up all of them so if something goes wrong you don’t miss anything.

Step 2: As I said I assume you already have VS 2008 and MVC 2 RC 2 installed on your machine. First go to “Microsoft Visual Studio 9.0\Common7\IDE\ItemTemplates\CSharp\Web\MVC 2\” and copy all the files in MVC 2 folder to the corresponding folder in VS 2010 folder (the first location in the list of step one) you should replace the current files with these new ones and you are not worry because you have already  a fresh back up of these files somewhere in your machine!

Step 3: Do the same work with files in
Microsoft Visual Studio 9.0\Common7\IDE\ItemTemplatesCache\CSharp\Web\MVC 2
Then go to “Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates\CSharp\Web\1033\” and just copy these two files to the corresponding folder in VS 2010:
EmptyMvcWebApplicationProjectTemplatev2.0.cs.zip and MvcWebApplicationProjectTemplatev2.0.cs.zip and as the previous steps you are going to replace the current ones with these new files.

Step 4: Do the same job with the same two files in
Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplatesCache\CSharp\Web\1033
So we now done with replacing files but if you now try to add a new project in your VS 2010 RC IDE you get an error says the project template tries to load from wrong assembly. But don’t worry we are one step to develop with the latest version of MVC.NET in VS 2010 RC.

Step 5: If you want to fix this issue you should dirty your hands with some manual fix of corresponding xml files in templates.
Go to “Microsoft Visual Studio 10.0\Common7\IDE\ItemTemplates\CSharp\Web\MVC 2\” and extract all zip files in the same location and delete zip files then open the unzipped files and find this section in each .vstemplate files in each folder:

“<Assembly>Microsoft.VisualStudio.Web.Mvc.2.0, Version=9.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35</Assembly>”

Then change the “Version=9.0.0.0” to “Version=10.0.0.0” then save each file in the same location. The last job is to zip back all the files. At this point you have the same zip files you had at first but with the changed version from 9 to 10. Do the same job with files at
Microsoft Visual Studio 10.0\Common7\IDE\ItemTemplatesCache\CSharp\Web\MVC 2” but this time you don’t need to do zip and unzip part.

Step 6: Repeat the exact job with that two file you copied to
Microsoft Visual Studio 10.0\Common7\IDE\ProjectTemplates\CSharp\Web\1033” you need to do the zip and unzip steps and the last step is to changing the assembly section in that two files at “Microsoft Visual Studio 10.0\Common7\IDE\ProjectTemplatesCache\CSharp\Web\1033” and this time without zip and unzip part. OK now we done! Open your VS 2010 RC IDE and create the new project you see the newly added project used the MVC 2 RC2 project template the more obvious changes are that the new template has jQuery 1.4.1 in its scripts folder and has the new “Optional Url parameter” in its global.asax.cs file at default route section.For more info about this new feature check out Phil Haack’s blog post.

Summary: We just updated our VS 2010 RC to use MVC.NET 2 RC 2 templates and for that we just had done some copying and pasting job and changed the assembly section in the .vstemplate files that had that section. As I said I assumed you have already VS 2008 with MVC.NET 2 RC2 installed on your machine.

Update: So after all this steps you may need do some other versional ! changes in Project Template so I uploaded the new project template (normal and  cache) so you can just download and compare it the original one to see the changes I zipped the file belong to cache folder so after copy you need to unzip and rename it as the original file. You can download the new template files here :

For copy to Microsoft Visual Studio 10.0\Common7\IDE\ProjectTemplates\CSharp\Web\1033 : here

For copy to Microsoft Visual Studio 10.0\Common7\IDE\ProjectTemplatesCache\CSharp\Web\1033: here (don’t forget to unzip and rename it as original file)


Shout it

kick it on DotNetKicks.com

Building a Data Grid in ASP.NET MVC

Posted in ASP.NET MVC, HTML Helpers by BlueCoder on 11/02/2010

Abstract: . In this post I’m going to show how you can build a Data Grid in ASP.NET MVC which has the sorting and paging features while you have enough control over the generated HTML  and more important you do this in a testable manner. And also you have bookmarking feature which is useful when user likes to share a specific page of the sorted data just by copying and pasting the URL from browser’s address bar. We avoid using JavaScript for this so the users which often disable JavaScript  in their browser don’t miss anything.

One of the first requirements of any web application is to show the data in a gird like manner. In web form world this is a simple task you put the Grid View Control directly into the .aspx page  and configure  its data source and you’ve done. But this way you lose some important things. You don’t have enough control over  the generated HTML and also you lose the bookmarking feature because paging and sorting information will be  saved in viewstate which is another issue in when you develop in  web form. In this post I’m going to show how you can build a Data Grid Helper method which has all the power of GridView (like sorting and paging) while you also have enough control over  the generated HTML  and you do all  these in a testable manner and also you have bookmarking feature which is useful when user likes to share a specific page of data which is sorted in a desired way.

To build any HTML helper in MVC.NET you should write an extension method that extends HtmlHelper class. Because I want to avoid importing namespaces and configure Web.Config file I put the static class needed to create this extension method  in System.Web.Mvc.Html namespace.

First I’m going to show a Grid Data Helper which has the sorting capability and then I’m going to create a Pager helper to add paging capability to this Grid. I use the Grid Data helper codes which “Stephen Walther” mentioned in his “ASP.NET MVC framework Unleashed” book and  for the paging part I going to use Paging helper codes which “Steven Sanderson” has mentioned in his “Pro ASP.NET MVC framework” book which generates the HTML markup for page links and I also extend it to create a dynamic pager and also I use the Dynamic Linq sample code to write simple sorting logic and avoid using many switch case block of codes.

Lets jump into code and then dig into how it works:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.IO;

namespace System.Web.Mvc.Html
{
    public static class DataGridHelper
    {
        public static string DataGrid<T>(this HtmlHelper helper)
        {
            return DataGrid<T>(helper, null, null);
        }

        public static string DataGrid<T>(this HtmlHelper helper, object data)
        {
            return DataGrid<T>(helper, data, null);
        }

        public static string DataGrid<T>(this HtmlHelper helper, object data, string[] columns)
        {
            //Get items
            var items = (IEnumerable<T>)data;
            if (items == null)
                items = (IEnumerable<T>)helper.ViewData.Model;

            //Get column names
            if (columns == null)
                columns = typeof(T).GetProperties().Select(p => p.Name).ToArray();

            //Create HtmlTextWriter
            var writer = new HtmlTextWriter(new StringWriter());

            //Open table tag
            writer.RenderBeginTag(HtmlTextWriterTag.Table);

            //Render Table Header
            writer.RenderBeginTag(HtmlTextWriterTag.Thead);
            RenderHeader(helper, writer, columns);
            writer.RenderEndTag();

            // Render table body
            writer.RenderBeginTag(HtmlTextWriterTag.Tbody);
            foreach (var item in items)
                RenderRow<T>(helper, writer, columns, item);
            writer.RenderEndTag();

            //Close  table tag
            writer.RenderEndTag();

            //return the string
            return writer.InnerWriter.ToString();
        }

        private static void RenderHeader(HtmlHelper helper, HtmlTextWriter writer, string[] columns)
        {
            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            foreach (var columnName in columns)
            {
                writer.RenderBeginTag(HtmlTextWriterTag.Th);
                var currentAction = (string)helper.ViewContext.RouteData.Values["action"];
                var link = helper.ActionLink(columnName, currentAction, new { sort = columnName });
                writer.Write(link);
                writer.RenderEndTag();
            }
            writer.RenderEndTag();
        }

        public static void RenderRow<T>(HtmlHelper helper, HtmlTextWriter write, string[] columns, T item)
        {
            write.RenderBeginTag(HtmlTextWriterTag.Tr);
            foreach (var columnName in columns)
            {
                write.RenderBeginTag(HtmlTextWriterTag.Td);
                var value = typeof(T).GetProperty(columnName).GetValue(item, null) ?? String.Empty;
                write.Write(helper.Encode(value.ToString()));
                write.RenderEndTag();
            }
            write.RenderEndTag();
        }

    }
}

The core part of this helpers  simply makes a table. As you see this helper is a generic method so you can use it for all of your domain model classes. You can send model data and columns names through the parameters or you can simply pass it through the ViewModel and let the helper do the work for you. The first interesting part of code is where we use a bit of reflection to find the columns name of the our model:


columns = typeof(T).GetProperties().Select(p => p.Name).ToArray();

In this line of code we get the name of all properties of the model we passed to helper and put them on the columns array, then we use this array to generate the HTML markup of our gird’s header and also we are going use it for generating the links needed for calling the action method and passing the column name as sort expression to it.
Then we begin to create the markup and as you see we use HtmlTextWriter class to do this task more clean, more readable, more error proof, and also more testable but you can use StringBuilder class or just use any method you feel comfortable.
As you see the more interesting part of code are RenderHeader and RenderRow methods lets dig into:
RenderHeader : In this method we going to make the header columns as a link to call the sorting for the grid. To create the links we need to get the current action through this line of code :

var currentAction = (string)helper.ViewContext.RouteData.Values[“action”];

Then we use Html.ActionLink helper method to generate the actual link markups:

var link = helper.ActionLink(columnName, currentAction, new { sort = columnName });

RenderRow : In this method we use a bit of reflection to get the value of the properties of model to fill each cell and also we use column array we to specify the name of the property:

var value = typeof(T).GetProperty(columnName).GetValue(item, null) ?? String.Empty;

Also note that we use Html.Encode method to pass only valid Html markup to the view and prevent XSS or other JS attacks:

write.Write(helper.Encode(value.ToString()));

And that’s it our Grid Data Helper completed and has the sorting feature but what about paging?
I’m going to create the paging helper a bit more reusable so I’ll be able to use it outside of Grid Data and also I’m interested in separate the paging logic from sorting for the sake of SoC. Lets first check the source code and then see how it works :

namespace System.Web.Mvc.Html
{
    public static class PageLinkHelper
    {
        public static string PageLink(this HtmlHelper html, int currentPage, int totalPages, Func<int, string> pageUrl)
        {

            var diff = 1;
            StringBuilder result = new StringBuilder();
            var TotalPages = totalPages;

            if (currentPage < 1)
                currentPage = 1;

            if ((currentPage + diff) < totalPages)
                totalPages = currentPage + diff;
            var startPage = 1;
            if ((currentPage - diff) > startPage)
                startPage = currentPage - diff;

            if ((currentPage - diff) > 1)
            {
                TagBuilder tag3 = new TagBuilder("a");
                tag3.Attributes.Add("href", pageUrl(1));
                tag3.InnerHtml = "1";
                result.AppendLine(tag3.ToString());
            }

            if ((currentPage - (diff + 1)) > 1)
            {
                TagBuilder tag2 = new TagBuilder("a");
                tag2.Attributes.Add("href", pageUrl(currentPage - (diff + 1)));
                tag2.InnerHtml = "...";
                result.AppendLine(tag2.ToString());
            }

            for (int i = startPage; i <= totalPages; i++)
            {
                TagBuilder tag = new TagBuilder("a");
                tag.Attributes.Add("href", pageUrl(i));
                tag.InnerHtml = i.ToString();
                if (i == currentPage)
                    tag.AddCssClass("pageSelected");
                result.AppendLine(tag.ToString());
            }

            if ((currentPage + (diff + 1)) < TotalPages)
            {
                TagBuilder tag2 = new TagBuilder("a");
                tag2.Attributes.Add("href", pageUrl(currentPage + (diff + 1)));
                tag2.InnerHtml = "...";
                result.AppendLine(tag2.ToString());
            }

            if ((currentPage + diff) < TotalPages)
            {
                TagBuilder tag3 = new TagBuilder("a");
                tag3.Attributes.Add("href", pageUrl(TotalPages));
                tag3.InnerHtml = TotalPages.ToString();
                result.AppendLine(tag3.ToString());
            }
            return result.ToString();
        }
    }
}

This helper gets the current page and total page and also a method to generate the links.
We will pass all this data directly in the view as you see soon. I just wanted to show the core part of this pager helper is :

 for (int i = startPage; i <= totalPages; i++)
            {
                TagBuilder tag = new TagBuilder("a");
                tag.Attributes.Add("href", pageUrl(i));
                tag.InnerHtml = i.ToString();
                if (i == currentPage)
                    tag.AddCssClass("pageSelected");
                result.AppendLine(tag.ToString());
            }

Which we create the markup for each page and add a CSS class to the current page, the remaining codes just is to generate “… “ links and check the difference between current page and first or last page. I create a logic which just show the first, last and current pages and also the previous and next pages link and shows “…” to get access to farther page links. Obviously you can change it to satisfies your needs and also I’ll waiting to hear about more efficient and better ways to implement these kind of logic in the comments.
All the work we done until here is just generates the dumb HTML markups to use in the view! We should create the core logic in Controller. But first I want to note some important topics. First of all I’m using the default route configuration for this demo and also take advantage of Repository and View Model patterns. The database I use is Northwind sample DB and I use EF as ORM and also I use a simple DI pattern to decouple the Controller from the repository and the only dependency is at the constructor of the controller.
OK let’s just check the source code of Controller then dig into how it works :

namespace Mvc2Application1.Controllers
{
    public class ProductController : Controller
    {
        private IProductsRepository _repository;
        private int _pageSize;
        public ProductController():this(new ProductsRepositoryEF())
        {

        }

        public ProductController(IProductsRepository repository)
        {
            _repository = repository;
            _pageSize = 10;
        }

        public ActionResult List(string sort, int? page)
        {
            var currentPage = page ?? 1;
            ViewData["SortItem"] = sort;
            sort = sort ?? "Name";
            ViewData["CurrentPage"] = currentPage;
            ViewData["TotalPages"] = (int)Math.Ceiling((float)_repository.Products.Count() / _pageSize);

            var products = from p in _repository.Products
                           select new ProductViewModel()
                           {
                               Name = p.ProductName,
                               Price = p.UnitPrice ?? 0,
                               Category = p.Category.CategoryName
                           };
            var sortedProducts = products
                .OrderBy(sort)
                .Skip((currentPage - 1) * _pageSize)
                .Take(_pageSize);
            return View(sortedProducts);
        }

As you see we pass the sort and page information to action method through parameters and pass the SortItem CurrentPage and TotalPages to view through ViewData dictionary. I used the ViewModel pattern to just pass the needed columns to the view and also flatten the complex abject to a relatively simple class. The most interesting part is where instead of passing lambda expression I just passed the property name as the sort condition. If you try this you get error. To be able to do this dynamic query through LINQ you need to add the Dynamic.cs class from the sample codes included in Visual Studio into your project and also add the System.Linq.Dynamic namespace reference to your Controller class for more info about using Dynamic Linq check out the Scott Guthrie’s blog post.and that’s it as you see our controller is also simple enough to work with then let’s go to view code and complete our masterpiece!

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<Mvc2Application1.Models.ViewModels.ProductViewModel>>" %>
<%@ Import Namespace="Mvc2Application1.Models.ViewModels" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
	List
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>List of Product</h2>
    <%=Html.DataGrid<ProductViewModel>() %>
    <div>
        <%=Html.PageLink((int)ViewData["CurrentPage"],
            (int)ViewData["TotalPages"],
            p => Url.Action("List",
                new { page = p,
                    sort = (string)ViewData["SortItem"] }))%>
    </div>
</asp:Content>

First note I imported the required namespace. As you see the view code is very simple, we show the Data Grid just by calling the Html.DataGrid helper and for the paging part we just call the Html.PageLink Helper we just created. The most interesting part is the method we pass to this helper:

p => Url.Action("List",new { page = p,sort = (string)ViewData["SortItem"]})

This way every page link goes to the same action method (List) and pass the page and sort parameter to it so the user can share the specific part of data just by passing the Url to others because all the paging and sorting information can be seen in the address bar. And that’s it we just created our Data Grid and now we have the complete control over generated HTML and also we can easily test our helper codes. As Rob Connery says every time you have an if in your view create a helper! This way your view is easy to test and also more HTML friendly.
Summary : We just created two useful helper methods which we can use all over our project to show a Data Grid which have the sorting and paging features we also took advantage of Dynamic Linq to write a simple sorting logic and we also took advantage of some advanced feature of C# like generics and reflection to write our Data Grid helper and also used the TagBuilder and HtmlTextWriter classes to write a clean and testable helper. Our Paging logic is completely separate from our Data Grid so we can use it with any other list of data.

Update: You can download sample project here .And also don’t Forget to download the Northwind DB here and copy it to your App_Data folder .


Shout it

kick it on DotNetKicks.com

Setting Up IoC in ASP.NET MVC using Castle Windsor

Posted in ASP.NET MVC, Controllers, IoC by BlueCoder on 09/01/2010

Abstract: This post gathers information needed to setting up Inversion of Control (IoC) in an ASP.NET MVC application using Castle Windsor.

Introduction: In previous post I summarized how ASP.NET MVC components work together to process request from user and return result . In that post I mentioned we can customize each step to satisfy our needs so I’m going to show you how you can create a custom Controller Factory to implement IoC in your application. For more information about IoC and why we use it you can take a look at this like :http://www.mikesdotnetting.com/Article/117/Dependency-Injection-and-Inversion-of-Control-with-ASP.NET-MVC .

I learned how to use Windsor to set up IoC by reading the great book of Steven Sanderson “Pro ASP.NET MVC framework”. You can read the section I used for this post here :Pro ASP.NET MVC framework by Steven Sanderson

You can get the latest version of Castle project here : www.castleproject.org/castle/download.html

After download and install Castle Project follow these steps to set up IoC in a very simple MVC project. I use default project template & routing configuration that comes with MVC 2.

1.Right click your References folder and add reference to “Castle.Core.dll”, “Castle.MicroKernel.dll”, “Castle.Windsor.dll” files which are in  “C:\Program Files\CastleProject\Bin\net-2.0 after installing Castle.

Add Reference to Castle

2.Next we are going to create a custom Controller Factory class. Add WindsorControllerFactory.cs to the root of your application and write these lines of codes to create a controller factory which uses castle to load the required objects at run time base on configuration section which we set up later. Don’t afraid of XML & Reflection parts in the code. These snippets just say to Windsor Container that where in the Web.config file look for registering components and Reflection part just registers all controllers’ types as components. Usually when we use IoC we want to inject an object to an constructor parameter at run time, but in constructor code we just say which interface that object implements but IoC Container loads the needed object base on its configuration. The Interfaces, objects and classes which their constructor injected are components of an IoC container. In this example we register components in two places: We register controllers in the controller factory but register other types using  castle section in Web.config file. So let just right the needed Controller Factory which uses the snippets of Steven’s book that I just updated it to be compatible with MVC 2:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Castle.Windsor;
using Castle.Windsor.Configuration.Interpreters;
using Castle.Core.Resource;
using System.Reflection;
using Castle.Core;
using System.Web.Routing;

namespace Mvc2Application6
{
    public class WindsorControllerFactory : DefaultControllerFactory
    {
        WindsorContainer container;
        // The constructor:
        // 1. Sets up a new IoC container
        // 2. Registers all components specified in web.config
        // 3. Registers all controller types as components
        public WindsorControllerFactory()
        {
            // Instantiate a container, taking configuration from web.config
            container = new WindsorContainer(
            new XmlInterpreter(new ConfigResource("castle"))
            );
            // Also register all the controller types as transient
            var controllerTypes =
                from t in Assembly.GetExecutingAssembly().GetTypes()
                                  where typeof(IController).IsAssignableFrom(t)
                                  select t;
            foreach (Type t in controllerTypes)
                container.AddComponentWithLifestyle
                    (t.FullName, t,LifestyleType.Transient);
        }

        // Constructs the controller instance needed to service each request this part is Updated to be compatible with MVC 2
        protected override IController
            GetControllerInstance
            (RequestContext requestContext, Type controllerType)
        {
            return (IController)container.Resolve(controllerType);
        }
        /*
         * For MVC 1 use this
        protected override IController GetControllerInstance(Type controllerType)
        {
            return (IController)container.Resolve(controllerType);
        }*/
    }
}

Note : This post works with Castle 1 RC 3. I recently got an email from one of readers that this not works with the latest version which is 2
so for those folks who want to work which the latest version I notify that instead of AddComponentWithLifestyle method they should use the new AddComponentLifeStyle method.

3.To ASP.NET MVC use your new controller factory add this to the application start method of your global.asax.cs file :

ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory());

4. Next we need manipulate our Web.config file in the root of the application: Add a <castle> node directly in the configuration node: <castle><components></components></castle> we edit this shortly. In the configSections node add this:

<section name="castle" type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler,Castle.Windsor" />

5. To work with our new IoC structure you need to construct your application to use it so follow these steps to set up a simple application which use our IoC implementation:
Create an IEbookRepository interface in Model folder:

namespace Mvc2Application6.Models

{

public interface IEbookRepository

{

IEnumerable<Book> ListEbook();

}

}

As you see it’s a simple interface with a property that returns a list of Books. Book is a simple class with 3 properties:

namespace Mvc2Application6.Models

{

public class Book

{

public int ID { get; set; }

public string Name { get; set; }

public string Author { get; set; }

}

}

Create a concrete class which implements IEbookRepository interface (for simplicity we don’t touch DB and an in memory  list of books satisfies our example):


namespace Mvc2Application6.Models

{

public class EBookRepository : IEbookRepository

{

public IEnumerable<Book> ListEbook()

{

List<Book> books = new List<Book>();

books.Add(new Book { ID = 1, Author = "Steven Sanderson", Name = "Pro ASP.NET MVC framewok" });

books.Add(new Book { ID = 2, Author = "Stphan Waler", Name = "ASP.NET MVC framework Unleashed" });

books.Add(new Book { ID = 3, Author = "Scott Guthrie", Name = "ASP.NET MVC 1.0" });

return books;

}

}

}

Add a new Constructor to your Home Controller:

private IEbookRepository _repository ;

public HomeController(IEbookRepository repository)

{

this._repository = repository;

}

Now we need to tell WindsorContainer to inject IEbookRepository with an object of type EBookRepository so back to your Web.config file and edit castle node we created in step 4:


<castle>

<components>

<component id="EbookRepository"

service="Mvc2Application6.Models.IEbookRepository,Mvc2Application6"

type="Mvc2Application6.Models.EBookRepository,Mvc2Application6"

lifestyle="PerWebRequest">

</component>

</components>

</castle>

This says whenever a class has a dependency to a IEbookRepository (in our example through its constructor) IoC container should load an EBookRepository  object with whenever a web  request comes.

Then we need to register Windsor’s PerRequestLifestyle module in httpModules section :

<add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule,Castle.MicroKernel" />

To register Windsor’s PerRequestLifestyle for IIS 7 refer to the original book “APRESS Pro ASP.NET MVC framework” or use the Google book link above.

So that’s it we set up an IoC container for our ASP.NET MVC application.

you can download sample project here.

Summary: We used Castle Windsor to Set up IoC in a very simple MVC application and for this we created a custom controller factory and added some configuration in web.config file. We also edited Application Start Method to tell MVC use our new controller factory instead of DefaultControllerFactory.


Shout it

kick it on DotNetKicks.com

How ASP.NET MVC WORKS?

Posted in ASP.NET MVC, Controllers, Models, Routing, Views by BlueCoder on 03/01/2010

Abstract : In this very short article we travel through ASP.NET MVC Request Processing Pipeline from accepting the request by IIS to showing the result view by View Engine.

IIS takes each HTTP request and invokes ASP.NET which in turn invokes UrlRoutingModule which is a registered HTTP module. UrlRoutingModule starts Routing System which lives in System.Web.Routing namespace. Routing system parses the incoming Url and constructs a data structure named Request Context and searches RouteTable entries to find the matching entry and by default  invokes MvcRouteHandler passing the Request Context to it. Request Context includes parameters parsed from Url and provides access to Request and Response objects. MvcRouteHandler by default invokes DefaultControllerFactory which follows a naming convention to choose the correct controller class for a given request. Chosen controller invokes the correct action method which in turn returns an ActionResult object. and that’s it! The request is processed and a result returned. Hooray!

In case of ViewResult, action method constructs a ViewData structure and passes it to ViewResult. ViewResult is able to locate and render a particular view template using ViewData. It does so by invoking WebFormViewEngine which uses WebForms ASPX files as view templates.

The great news is every steps above can be customized: you can have your own Controller Factory and any View  Engine you comfortable with you even can create your own Route Handler to take control of routing .

summary : To be able to get the best of ASP.NET MVC you should know whats going on behind the scene and how you  can change that so in this very short post you get familiar with ASP.NET MVC Request Processing Pipeline and now have a good idea about it you also learned you can change the way MVC behaves by extending each part in your own way. hope this helps.

Further Readings:

In depth: ASP.NET MVC Pipeline

Request Handling Pipeline Poster

Custom Controller Factory in ASP.NET MVC

Custom Routing for ASP.NET MVC

Extending ASP.NET MVC : Replacing the View Engine

Extending ASP.NET MVC – Replacing the View Engine


Shout it

kick it on DotNetKicks.com

Follow

Get every new post delivered to your Inbox.