<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://weblogs.asp.net/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Kazi Manzur Rashid's Blog : MvcExtensions</title><link>http://weblogs.asp.net/rashid/archive/tags/MvcExtensions/default.aspx</link><description>Tags: MvcExtensions</description><dc:language>en</dc:language><generator>CommunityServer 2007 SP1 (Build: 20510.895)</generator><item><title>Localization with ASP.NET MVC ModelMetadata</title><link>http://weblogs.asp.net/rashid/archive/2010/06/14/localization-with-asp-net-mvc-modelmetadata.aspx</link><pubDate>Mon, 14 Jun 2010 02:12:02 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7529055</guid><dc:creator>kazimanzurrashid</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/rashid/rsscomments.aspx?PostID=7529055</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/rashid/commentapi.aspx?PostID=7529055</wfw:comment><comments>http://weblogs.asp.net/rashid/archive/2010/06/14/localization-with-asp-net-mvc-modelmetadata.aspx#comments</comments><description>&lt;p&gt;When using the &lt;code&gt;DisplayFor/EditorFor&lt;/code&gt; there has been built-in support in ASP.NET MVC to show &lt;a href="http://haacked.com/archive/2009/12/07/localizing-aspnetmvc-validation.aspx"&gt;localized validation messages&lt;/a&gt;, but no support to show the associate label in localized text, unless you are using the .NET 4.0 with Mvc Future. Lets a say you are creating a create form for Product where you have support both English and German like the following. &lt;/p&gt;  &lt;h3&gt;English&lt;/h3&gt;  &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/rashid/createen_6C6E606A.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="create-en" border="0" alt="create-en" src="http://weblogs.asp.net/blogs/rashid/createen_thumb_6D36A087.png" width="1016" height="384" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;h3&gt;German&lt;/h3&gt;  &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/rashid/createde_41C259C0.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="create-de" border="0" alt="create-de" src="http://weblogs.asp.net/blogs/rashid/createde_thumb_292296A3.png" width="1018" height="384" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;I have recently added few helpers for localization in the &lt;a href="http://mvcextensions.codeplex.com"&gt;MvcExtensions&lt;/a&gt;, lets see how we can use it to localize the form. As mentioned in the past that I am not a big fan when it comes to decorate class with attributes which is the recommended way in ASP.NET MVC. Instead, we will use the fluent configuration (Similar to FluentNHibernate or EF CodeFirst) of MvcExtensions to configure our View Models. For example for the above we will using:&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:84869b71-b8f0-4652-8c3d-544264074895" class="wlWriterSmartContent"&gt;&lt;pre name="code" class="c#"&gt;public class ProductEditModelConfiguration : ModelMetadataConfiguration&amp;lt;ProductEditModel&amp;gt;
{
    public ProductEditModelConfiguration()
    {
        Configure(model =&amp;gt; model.Id).Hide();

        Configure(model =&amp;gt; model.Name).DisplayName(() =&amp;gt; LocalizedTexts.Name)
                                      .Required(() =&amp;gt; LocalizedTexts.NameCannotBeBlank)
                                      .MaximumLength(64, () =&amp;gt; LocalizedTexts.NameCannotBeMoreThanSixtyFourCharacters);

        Configure(model =&amp;gt; model.Category).DisplayName(() =&amp;gt; LocalizedTexts.Category)
                                          .Required(() =&amp;gt; LocalizedTexts.CategoryMustBeSelected)
                                          .AsDropDownList("categories", () =&amp;gt; LocalizedTexts.SelectCategory);

        Configure(model =&amp;gt; model.Supplier).DisplayName(() =&amp;gt; LocalizedTexts.Supplier)
                                          .Required(() =&amp;gt; LocalizedTexts.SupplierMustBeSelected)
                                          .AsListBox("suppliers");

        Configure(model =&amp;gt; model.Price).DisplayName(() =&amp;gt; LocalizedTexts.Price)
                                       .FormatAsCurrency()
                                       .Required(() =&amp;gt; LocalizedTexts.PriceCannotBeBlank)
                                       .Range(10.00m, 1000.00m, () =&amp;gt; LocalizedTexts.PriceMustBeBetweenTenToThousand);
    }
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can we are using &lt;code&gt;Func&amp;lt;string&amp;gt;&lt;/code&gt; to set the localized text, this is just an &lt;code&gt;overload&lt;/code&gt; with the regular string method. There are few more methods in the &lt;code&gt;ModelMetadata&lt;/code&gt; which accepts this &lt;code&gt;Func&amp;lt;string&amp;gt;&lt;/code&gt; where localization can applied like &lt;code&gt;Description&lt;/code&gt;, &lt;code&gt;Watermark&lt;/code&gt;, &lt;code&gt;ShortDisplayName&lt;/code&gt; etc. The &lt;code&gt;LocalizedTexts&lt;/code&gt; is just a regular resource, we have both English and German:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/rashid/mvclocalizationse_06DA6550.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="mvc-localization-se" border="0" alt="mvc-localization-se" src="http://weblogs.asp.net/blogs/rashid/mvclocalizationse_thumb_3B4B11CB.png" width="305" height="76" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Now lets see the view markup:&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:ae3dcf0f-65ec-4aa8-8d97-6b55165299f0" class="wlWriterSmartContent"&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage&amp;lt;Demo.Web.ProductEditModel&amp;gt;" %&amp;gt;
&amp;lt;asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"&amp;gt;
    &amp;lt;%= LocalizedTexts.Create %&amp;gt;
&amp;lt;/asp:Content&amp;gt;
&amp;lt;asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"&amp;gt;
    &amp;lt;h2&amp;gt;&amp;lt;%= LocalizedTexts.Create %&amp;gt;&amp;lt;/h2&amp;gt;
    &amp;lt;%= Html.ValidationSummary(false, LocalizedTexts.CreateValidationSummary)%&amp;gt;
    &amp;lt;% Html.EnableClientValidation(); %&amp;gt;
    &amp;lt;% using (Html.BeginForm()) {%&amp;gt;
        &amp;lt;fieldset&amp;gt;
            &amp;lt;%= Html.EditorForModel() %&amp;gt;
            &amp;lt;p&amp;gt;
                &amp;lt;input type="submit" value="&amp;lt;%= LocalizedTexts.Create %&amp;gt;" /&amp;gt;
            &amp;lt;/p&amp;gt;
        &amp;lt;/fieldset&amp;gt;
    &amp;lt;% } %&amp;gt;
    &amp;lt;div&amp;gt;
        &amp;lt;%= Html.ActionLink(LocalizedTexts.BackToList, "Index")%&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/asp:Content&amp;gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As we can see that we are using the same &lt;code&gt;LocalizedTexts&lt;/code&gt; for the other parts of the view which is not included in the &lt;code&gt;ModelMetadata&lt;/code&gt; like the Page title, button text etc. We are also using &lt;code&gt;EditorForModel&lt;/code&gt; instead of &lt;code&gt;EditorFor&lt;/code&gt; for individual field and both are supported.&lt;/p&gt;

&lt;p&gt;One of the added benefit of the fluent syntax based configuration is that we will get full compile type checking for our resource as we are not depending upon the string based resource name like the ASP.NET MVC.&lt;/p&gt;

&lt;p&gt;You will find the complete localized CRUD example in the MvcExtensions sample folder [Available in the &lt;a href="http://mvcextensions.codeplex.com/SourceControl/changeset/view/3147dc9d989c"&gt;Trunk&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;That’s it for today.&lt;/p&gt;&lt;div class="wlWriterHeaderFooter" style="margin:0px; padding:0px 0px 0px 0px;"&gt;&lt;div class="shoutIt"&gt;&lt;a rev="vote-for" href="http://dotnetshoutout.com/Submit?url=http%3a%2f%2fweblogs.asp.net%2frashid%2farchive%2f2010%2f06%2f14%2flocalization-with-asp-net-mvc-modelmetadata.aspx&amp;amp;title=Localization+with+ASP.NET+MVC+ModelMetadata"&gt;&lt;img alt="Shout it" src="http://dotnetshoutout.com/image.axd?url=http://weblogs.asp.net/rashid/archive/2010/06/14/localization-with-asp-net-mvc-modelmetadata.aspx" style="border:0px" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7529055" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/rashid/archive/tags/Asp.net/default.aspx">Asp.net</category><category domain="http://weblogs.asp.net/rashid/archive/tags/MVC/default.aspx">MVC</category><category domain="http://weblogs.asp.net/rashid/archive/tags/ASPNETMVC/default.aspx">ASPNETMVC</category><category domain="http://weblogs.asp.net/rashid/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><category domain="http://weblogs.asp.net/rashid/archive/tags/Open+Source/default.aspx">Open Source</category><category domain="http://weblogs.asp.net/rashid/archive/tags/MvcExtensions/default.aspx">MvcExtensions</category></item><item><title>MvcExtensions - ActionFilter</title><link>http://weblogs.asp.net/rashid/archive/2010/05/27/mvcextensions-actionfilter.aspx</link><pubDate>Thu, 27 May 2010 12:26:31 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7507791</guid><dc:creator>kazimanzurrashid</dc:creator><slash:comments>8</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/rashid/rsscomments.aspx?PostID=7507791</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/rashid/commentapi.aspx?PostID=7507791</wfw:comment><comments>http://weblogs.asp.net/rashid/archive/2010/05/27/mvcextensions-actionfilter.aspx#comments</comments><description>&lt;p&gt;One of the thing that people often complains is dependency injection in Action Filters. Since the standard way of applying action filters is to either decorate the Controller or the Action methods, there is no way you can inject dependencies in the action filter constructors. There are quite a few posts on this subject, which shows the property injection with a custom action invoker, but all of them suffers from the same small bug (you will find the &lt;code&gt;BuildUp&lt;/code&gt; is called more than once if the filter implements multiple interface e.g. both &lt;code&gt;IActionFilter&lt;/code&gt; and &lt;code&gt;IResultFilter&lt;/code&gt;). The &lt;a href="http://mvcextensions.codeplex.com"&gt;MvcExtensions&lt;/a&gt; supports both property injection as well as fluent filter configuration api. There are a number of benefits of this fluent filter configuration api over the regular attribute based filter decoration.&lt;/p&gt;  &lt;p&gt;You can pass your dependencies in the constructor rather than property. Lets say, you want to create an action filter which will update the User Last Activity Date, you can create a filter like the following:&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:3c3838c0-dc13-48e2-9a78-3037aa9c9f94" class="wlWriterSmartContent"&gt;&lt;pre name="code" class="c#"&gt;public class UpdateUserLastActivityAttribute : FilterAttribute, IResultFilter
{
    public UpdateUserLastActivityAttribute(IUserService userService)
    {
        Check.Argument.IsNotNull(userService, "userService");

        UserService = userService;
    }

    public IUserService UserService
    {
        get;
        private set;
    }

    public void OnResultExecuting(ResultExecutingContext filterContext)
    {
        // Do nothing, just sleep.
    }

    public void OnResultExecuted(ResultExecutedContext filterContext)
    {
        Check.Argument.IsNotNull(filterContext, "filterContext");

        string userName = filterContext.HttpContext.User.Identity.IsAuthenticated ?
                          filterContext.HttpContext.User.Identity.Name :
                          null;

        if (!string.IsNullOrEmpty(userName))
        {
            UserService.UpdateLastActivity(userName);
        }
    }
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;As you can see, it is nothing different than a regular filter except that we are passing the dependency in the constructor. Next, we have to configure this filter for which Controller/Action methods will execute:&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:9811e5e1-9a3d-4c8d-b1f7-3204ab8b4538" class="wlWriterSmartContent"&gt;&lt;pre name="code" class="c#"&gt;public class ConfigureFilters : ConfigureFiltersBase
{
    protected override void Configure(IFilterRegistry registry)
    {
        registry.Register&amp;lt;HomeController, UpdateUserLastActivityAttribute&amp;gt;();
    }
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can register more than one filter for the same Controller/Action Methods:&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:657b52ab-3c37-4f37-8039-f48cb6befc87" class="wlWriterSmartContent"&gt;&lt;pre name="code" class="c#"&gt;registry.Register&amp;lt;HomeController, UpdateUserLastActivityAttribute, CompressAttribute&amp;gt;();&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can register the filters for a specific Action method instead of the whole controller:&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:f86c6034-4dac-4bd0-8787-a5f842f60a11" class="wlWriterSmartContent"&gt;&lt;pre name="code" class="c#"&gt;registry.Register&amp;lt;HomeController, UpdateUserLastActivityAttribute, CompressAttribute&amp;gt;(c =&amp;gt; c.Index());&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can even set various properties of the filter:&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:73432b7f-4015-4a36-b166-3e91da62e97a" class="wlWriterSmartContent"&gt;&lt;pre name="code" class="c#"&gt;registry.Register&amp;lt;ControlPanelController, CustomAuthorizeAttribute&amp;gt;( attribute =&amp;gt; { attribute.AllowedRole = Role.Administrator; });&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The Fluent Filter registration also reduces the number of base controllers in your application. It is very common that we create a base controller and decorate it with action filters and then we create concrete controller(s) so that the base controllers action filters are also executed in the concrete controller. You can do the&amp;#160; same with a single line statement with the fluent filter registration:&lt;/p&gt;

&lt;p&gt;Registering the Filters for All Controllers:&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:84866982-fc41-4356-9fcf-b8332b906f7a" class="wlWriterSmartContent"&gt;&lt;pre name="code" class="c#"&gt;registry.Register&amp;lt;ElmahHandleErrorAttribute&amp;gt;(new TypeCatalogBuilder().Add(GetType().Assembly).Include(type =&amp;gt; typeof(Controller).IsAssignableFrom(type)));&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Registering Filters for selected Controllers:&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:341591c1-f8cc-42b3-80ca-a74f19f4622f" class="wlWriterSmartContent"&gt;&lt;pre name="code" class="c#"&gt;registry.Register&amp;lt;ElmahHandleErrorAttribute&amp;gt;(new TypeCatalogBuilder().Add(GetType().Assembly).Include(type =&amp;gt; typeof(Controller).IsAssignableFrom(type) &amp;amp;&amp;amp; (type.Name.StartsWith("Home") || type.Name.StartsWith("Post"))));&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;You can also use the built-in filters in the fluent registration, for example:&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:7f7d9d33-4602-4eef-92ee-63ff95d6f61c" class="wlWriterSmartContent"&gt;&lt;pre name="code" class="c#"&gt;registry.Register&amp;lt;HomeController, OutputCacheAttribute&amp;gt;(attribute =&amp;gt; { attribute.Duration = 60; });&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With the fluent filter configuration you can even apply filters to controllers that source code is not available to you (may be the controller is a part of a third party component).&lt;/p&gt;

&lt;p&gt;That’s it for today, in the next post we will discuss about the Model binding support in MvcExtensions. So stay tuned.&lt;/p&gt;&lt;div class="wlWriterHeaderFooter" style="margin:0px; padding:0px 0px 0px 0px;"&gt;&lt;div class="shoutIt"&gt;&lt;a rev="vote-for" href="http://dotnetshoutout.com/Submit?url=http%3a%2f%2fweblogs.asp.net%2frashid%2farchive%2f2010%2f05%2f27%2fmvcextensions-actionfilter.aspx&amp;amp;title=MvcExtensions+-+ActionFilter"&gt;&lt;img alt="Shout it" src="http://dotnetshoutout.com/image.axd?url=http://weblogs.asp.net/rashid/archive/2010/05/27/mvcextensions-actionfilter.aspx" style="border:0px" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7507791" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/rashid/archive/tags/Asp.net/default.aspx">Asp.net</category><category domain="http://weblogs.asp.net/rashid/archive/tags/MVC/default.aspx">MVC</category><category domain="http://weblogs.asp.net/rashid/archive/tags/ASPNETMVC/default.aspx">ASPNETMVC</category><category domain="http://weblogs.asp.net/rashid/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><category domain="http://weblogs.asp.net/rashid/archive/tags/Open+Source/default.aspx">Open Source</category><category domain="http://weblogs.asp.net/rashid/archive/tags/Action+Filter/default.aspx">Action Filter</category><category domain="http://weblogs.asp.net/rashid/archive/tags/MvcExtensions/default.aspx">MvcExtensions</category></item><item><title>MvcExtensions - PerRequestTask</title><link>http://weblogs.asp.net/rashid/archive/2010/05/19/mvcextensions-perrequesttask.aspx</link><pubDate>Wed, 19 May 2010 13:48:37 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7489644</guid><dc:creator>kazimanzurrashid</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/rashid/rsscomments.aspx?PostID=7489644</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/rashid/commentapi.aspx?PostID=7489644</wfw:comment><comments>http://weblogs.asp.net/rashid/archive/2010/05/19/mvcextensions-perrequesttask.aspx#comments</comments><description>&lt;p&gt;In the &lt;a href="http://weblogs.asp.net/rashid/archive/2010/05/12/mvcextensions-bootstrapping.aspx"&gt;previous post&lt;/a&gt;, we have seen the &lt;code&gt;BootstrapperTask&lt;/code&gt; which executes when the application starts and ends, similarly there are times when we need to execute some custom logic when a request starts and ends. Usually, for this kind of scenario we create &lt;code&gt;HttpModule&lt;/code&gt; and hook the begin and end request events. There is nothing wrong with this approach, except HttpModules are not at all IoC containers friendly and tight coupled with &lt;code&gt;HttpContext&lt;/code&gt; and its tail, also defining the HttpModule execution order is bit cumbersome, you either have to modify the &lt;code&gt;machine.config&lt;/code&gt; or clear the HttpModules and add it again in &lt;code&gt;web.config&lt;/code&gt;. Instead, you can use the &lt;code&gt;PerRequestTask&lt;/code&gt; which is very much container friendly as well as supports execution orders. Lets few examples where it can be used.&lt;/p&gt;  &lt;h3&gt;Remove www Subdomain&lt;/h3&gt;  &lt;p&gt;Lets say we want to remove the www subdomain, so that if anybody types http://www.mydomain.com it will automatically redirects to http://mydomain.com.&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:b5dc37fa-47f8-412a-a9b8-6f1c5fcbf7c7" class="wlWriterSmartContent"&gt;&lt;pre name="code" class="c#"&gt;public class RemoveWwwSubdomain : PerRequestTask
{
    public RemoveWwwSubdomain()
    {
        Order = DefaultOrder - 1;
    }

    protected override TaskContinuation ExecuteCore(PerRequestExecutionContext executionContext)
    {
        const string Prefix = "http://www.";

        Check.Argument.IsNotNull(executionContext, "executionContext");

        HttpContextBase httpContext = executionContext.HttpContext;

        string url = httpContext.Request.Url.ToString();

        bool startsWith3W = url.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase);
        bool shouldContinue = true;

        if (startsWith3W)
        {
            string newUrl = "http://" + url.Substring(Prefix.Length);

            HttpResponseBase response = httpContext.Response;

            response.StatusCode = (int)HttpStatusCode.MovedPermanently;
            response.Status = "301 Moved Permanently";
            response.RedirectLocation = newUrl;
            response.SuppressContent = true;
            shouldContinue = false;
        }

        return shouldContinue ? TaskContinuation.Continue : TaskContinuation.Break;
    }
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, first, we are setting the order so that we do not have to execute the remaining tasks of the chain when we are redirecting, next in the &lt;code&gt;ExecuteCore,&lt;/code&gt; we checking the whether www is present, if present we are sending a permanently moved http status code and breaking the task execution chain otherwise we are continuing with the chain.&lt;/p&gt;

&lt;h3&gt;Blocking IP Address&lt;/h3&gt;

&lt;p&gt;Lets take another scenario, your application is hosted in a shared hosting environment where you do not have the permission to change the IIS setting and you want to block certain IP addresses from visiting your application. Lets say, you maintain a list of IP address in database/xml files which you want to block, you have a &lt;code&gt;IBannedIPAddressRepository&lt;/code&gt; service which is used to match banned IP Address.&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:785eebb6-688a-4719-95f4-b81807051d30" class="wlWriterSmartContent"&gt;&lt;pre name="code" class="c#"&gt;public class BlockRestrictedIPAddress : PerRequestTask
{
    protected override TaskContinuation ExecuteCore(PerRequestExecutionContext executionContext)
    {
        bool shouldContinue = true;
        HttpContextBase httpContext = executionContext.HttpContext;

        if (!httpContext.Request.IsLocal)
        {
            string ipAddress = httpContext.Request.UserHostAddress;

            HttpResponseBase httpResponse = httpContext.Response;

            if (executionContext.ServiceLocator.GetInstance&amp;lt;IBannedIPAddressRepository&amp;gt;().IsMatching(ipAddress))
            {
                httpResponse.StatusCode = (int)HttpStatusCode.Forbidden;
                httpResponse.StatusDescription = "IPAddress blocked.";

                shouldContinue = false;
            }
        }

        return shouldContinue ? TaskContinuation.Continue : TaskContinuation.Break;
    }
}&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Managing Database Session&lt;/h3&gt;

&lt;p&gt;Now, let see how it can be used to manage NHibernate session, assuming that &lt;code&gt;ISessionFactory&lt;/code&gt; of NHibernate is &lt;a href="http://weblogs.asp.net/rashid/archive/2010/05/16/mvcextensions-custom-service-registration.aspx"&gt;already registered&lt;/a&gt; in our container.&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:a7c9d716-6f61-4acf-87c1-5424ddb12e1c" class="wlWriterSmartContent"&gt;&lt;pre name="code" class="c#"&gt;public class ManageNHibernateSession : PerRequestTask
{
    private ISession session;

    protected override TaskContinuation ExecuteCore(PerRequestExecutionContext executionContext)
    {
        ISessionFactory factory = executionContext.ServiceLocator.GetInstance&amp;lt;ISessionFactory&amp;gt;();

        session = factory.OpenSession();

        return TaskContinuation.Continue;
    }

    protected override void DisposeCore()
    {
        session.Close();
        session.Dispose();
    }
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;As you can see &lt;code&gt;PerRequestTask&lt;/code&gt; can be used to execute small and precise tasks in the begin/end request, certainly if you want to execute other than begin/end request there is no other alternate of &lt;code&gt;HttpModule&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;That’s it for today, in the next post, we will discuss about the Action Filters, so stay tuned.&lt;/p&gt;&lt;div class="wlWriterHeaderFooter" style="margin:0px; padding:0px 0px 0px 0px;"&gt;&lt;div class="shoutIt"&gt;&lt;a rev="vote-for" href="http://dotnetshoutout.com/Submit?url=http%3a%2f%2fweblogs.asp.net%2frashid%2farchive%2f2010%2f05%2f19%2fmvcextensions-perrequesttask.aspx&amp;amp;title=MvcExtensions+-+PerRequestTask"&gt;&lt;img alt="Shout it" src="http://dotnetshoutout.com/image.axd?url=http://weblogs.asp.net/rashid/archive/2010/05/19/mvcextensions-perrequesttask.aspx" style="border:0px" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7489644" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/rashid/archive/tags/Asp.net/default.aspx">Asp.net</category><category domain="http://weblogs.asp.net/rashid/archive/tags/MVC/default.aspx">MVC</category><category domain="http://weblogs.asp.net/rashid/archive/tags/ASPNETMVC/default.aspx">ASPNETMVC</category><category domain="http://weblogs.asp.net/rashid/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><category domain="http://weblogs.asp.net/rashid/archive/tags/Open+Source/default.aspx">Open Source</category><category domain="http://weblogs.asp.net/rashid/archive/tags/Shrinkr/default.aspx">Shrinkr</category><category domain="http://weblogs.asp.net/rashid/archive/tags/MvcExtensions/default.aspx">MvcExtensions</category></item><item><title>MvcExtensions – Custom Service Registration</title><link>http://weblogs.asp.net/rashid/archive/2010/05/16/mvcextensions-custom-service-registration.aspx</link><pubDate>Sun, 16 May 2010 15:29:51 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7485848</guid><dc:creator>kazimanzurrashid</dc:creator><slash:comments>10</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/rashid/rsscomments.aspx?PostID=7485848</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/rashid/commentapi.aspx?PostID=7485848</wfw:comment><comments>http://weblogs.asp.net/rashid/archive/2010/05/16/mvcextensions-custom-service-registration.aspx#comments</comments><description>&lt;p&gt;&lt;strong&gt;[Special Note: I have just released &lt;a href="http://mvcextensions.codeplex.com/releases/view/45435"&gt;SP1 Preview&lt;/a&gt; which contains the newly added Autofac Adapter and minor Windsor changes]&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;In this post, I will show you how you can register your custom services in your preferred IoC container and how the &lt;a href="http://mvcextensions.codeplex.com"&gt;MvcExtensions&lt;/a&gt; will integrate it with the rest of the application. One of the goal of MvcExtensions is, unlike the other mvc add-on library which provides its own custom interface for registration/resolution, it will let you use your container syntax that you are familiar with. In case, if you have to refer your container in your application you should use the &lt;a href="http://commonservicelocator.codeplex.com/"&gt;CommonServiceLocator&lt;/a&gt;(or CSL in short) which is now a days a standard to abstract your underlying container from the rest of the application. Yes, I know some of the ASP.NET MVC expert is saying that CSL is not adequate, but let me remind them, the goal of the CSL is laid into its name, if it suppose to give service registration or nested container support, it should be named as Common Service Registrar/Container Factory or something similar. Beside that referring your Container/Locator other than the bootstrapping phase is considered to be a design smell. Although behind the scene, the MvcExtensions extends the CSL with &lt;code&gt;IServiceRegistrar&lt;/code&gt; and &lt;code&gt;IServiceInjector&lt;/code&gt; interface but you never have to refer those in your code. MvcExtensions comes with most of the popular IoC container adapters that includes Autofac(added in the SP1 Preview), Ninject, StructureMap, Unity and Windsor.&lt;/p&gt;  &lt;p&gt;Lets take a fictitious blogging application as an example to see how the registration works and assume that blogging application contains &lt;code&gt;Database&lt;/code&gt;, &lt;code&gt;DatabaseFactory&lt;/code&gt;, &lt;code&gt;UnitOfWork&lt;/code&gt;, &lt;code&gt;Repository&lt;/code&gt;, few Domain Services and Mappers(converts domain objects into data transfer objects) as custom services. &lt;/p&gt;  &lt;p&gt;Lets start with the Ninject, first you have to add reference of Ninject 2, which you can find from &lt;a href="http://ninject.org/download"&gt;Ninject official site&lt;/a&gt;, next you have to add reference of &lt;a href="http://commonservicelocator.codeplex.com/releases/view/17694"&gt;CSL&lt;/a&gt; and at last the MvcExtensions and the Ninject Adapter. Next, we will create a Ninject Module which is the standard way of registering services in Ninject. The following shows the module that registers all of the above services:&lt;/p&gt;  &lt;h3&gt;Ninject&lt;/h3&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:54a72e0c-0f02-4467-9e16-939c2d7bcd61" class="wlWriterSmartContent"&gt;&lt;pre name="code" class="c#"&gt;namespace MyBlog
{
    using Ninject;
    using Ninject.Modules;

    public class NinjectServiceRegistrationModule : NinjectModule
    {
        public override void Load()
        {
            Bind&amp;lt;IDatabaseFactory&amp;gt;().To&amp;lt;DatabaseFactory&amp;gt;().InRequestScope();
            Bind&amp;lt;IDatabase&amp;gt;().ToMethod(c =&amp;gt; c.Kernel.Get&amp;lt;IDatabaseFactory&amp;gt;().Get());
            Bind&amp;lt;IUnitOfWork&amp;gt;().To&amp;lt;UnitOfWork&amp;gt;();

            Bind(typeof(IRepository&amp;lt;&amp;gt;)).To(typeof(Repository&amp;lt;&amp;gt;));

            Bind&amp;lt;IMapper&amp;lt;Blog, BlogInfo&amp;gt;&amp;gt;().To&amp;lt;BlogMapper&amp;gt;();
            Bind&amp;lt;IMapper&amp;lt;Post, PostInfo&amp;gt;&amp;gt;().To&amp;lt;PostMapper&amp;gt;();
            Bind&amp;lt;IMapper&amp;lt;Tag, TagInfo&amp;gt;&amp;gt;().To&amp;lt;TagMapper&amp;gt;();
            Bind&amp;lt;IMapper&amp;lt;Comment, CommentInfo&amp;gt;&amp;gt;().To&amp;lt;CommentMapper&amp;gt;();

            Bind&amp;lt;IBlogService&amp;gt;().To&amp;lt;BlogService&amp;gt;();
            Bind&amp;lt;IPostService&amp;gt;().To&amp;lt;PostService&amp;gt;();
            Bind&amp;lt;ITagService&amp;gt;().To&amp;lt;TagService&amp;gt;();
            Bind&amp;lt;ICommentService&amp;gt;().To&amp;lt;CommentService&amp;gt;();
        }
    }
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see there is no nothing special from MvcExtensions, you are creating the Ninject Module in the same way as you do where MvcExtensions is not used. Behind the scene,&amp;#160; The MvcExtensions will scan all the available assemblies of your application and register those Ninject Modules in the Kernel. Also check that we are not registering anything specific to ASP.NET MVC, those are handled by the &lt;code&gt;BootstrapperTask&lt;/code&gt; which I have discussed in my &lt;a href="http://weblogs.asp.net/rashid/archive/2010/05/12/mvcextensions-bootstrapping.aspx"&gt;last post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, lets see how we can use StructureMap to register the above services. First, we will add reference of &lt;a href="http://github.com/structuremap/structuremap/downloads"&gt;StructureMap 2.6.1&lt;/a&gt;, then we will add reference of CSL, MvcExtensions, StructureMap Adapter. Next, we will create a Registry which serves same as Ninject Module. The following shows the StructureMap registration:&lt;/p&gt;

&lt;h3&gt;StructureMap&lt;/h3&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:2d9950b3-f640-4aa1-8207-fa781a056c80" class="wlWriterSmartContent"&gt;&lt;pre name="code" class="c#"&gt;namespace MyBlog
{
    using StructureMap.Configuration.DSL;

    public class StructureMapServiceRegistry : Registry
    {
        public StructureMapServiceRegistry()
        {
            For&amp;lt;IDatabaseFactory&amp;gt;().HttpContextScoped().Use&amp;lt;DatabaseFactory&amp;gt;();
            For&amp;lt;IDatabase&amp;gt;().Use(c =&amp;gt; c.GetInstance&amp;lt;IDatabaseFactory&amp;gt;().Get());
            For&amp;lt;IUnitOfWork&amp;gt;().Use&amp;lt;UnitOfWork&amp;gt;();

            For(typeof(IRepository&amp;lt;&amp;gt;)).Use(typeof(Repository&amp;lt;&amp;gt;));

            For&amp;lt;IMapper&amp;lt;Blog, BlogInfo&amp;gt;&amp;gt;().Use&amp;lt;BlogMapper&amp;gt;();
            For&amp;lt;IMapper&amp;lt;Post, PostInfo&amp;gt;&amp;gt;().Use&amp;lt;PostMapper&amp;gt;();
            For&amp;lt;IMapper&amp;lt;Tag, TagInfo&amp;gt;&amp;gt;().Use&amp;lt;TagMapper&amp;gt;();
            For&amp;lt;IMapper&amp;lt;Comment, CommentInfo&amp;gt;&amp;gt;().Use&amp;lt;CommentMapper&amp;gt;();

            For&amp;lt;IBlogService&amp;gt;().Use&amp;lt;BlogService&amp;gt;();
            For&amp;lt;IPostService&amp;gt;().Use&amp;lt;PostService&amp;gt;();
            For&amp;lt;ITagService&amp;gt;().Use&amp;lt;TagService&amp;gt;();
            For&amp;lt;ICommentService&amp;gt;().Use&amp;lt;CommentService&amp;gt;();
        }
    }
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I know, we can use the StructureMap convention based api to make the above registration much more simpler and short, but that is a different topic. Same as Ninject, the MvcExtensions will scan for the SM registry and automatically register those in the container.&lt;/p&gt;

&lt;p&gt;Next, the Autofac (it has been re-added in the SP1 Preview), Autofac also has a &lt;code&gt;Module&lt;/code&gt; which acts same as Ninject Module and StructureMap Registry. Before creating the Module, you have add reference of &lt;a href="http://code.google.com/p/autofac/downloads/list"&gt;Autofac 2.2.3 Preview&lt;/a&gt;, CSL, MvcExtensions and Autofac Adapter. The following shows the Autofac registration:&lt;/p&gt;

&lt;h3&gt;Autofac&lt;/h3&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:80109f2e-b36d-48c0-934c-0cc34c05501e" class="wlWriterSmartContent"&gt;&lt;pre name="code" class="c#"&gt;namespace MyBlog
{
    using Autofac;

    public class AutofacServiceRegistrationModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterType&amp;lt;DatabaseFactory&amp;gt;().As&amp;lt;IDatabaseFactory&amp;gt;().PerRequestScoped();
            builder.Register(c =&amp;gt; c.Resolve&amp;lt;IDatabaseFactory&amp;gt;().Get()).As&amp;lt;IDatabase&amp;gt;();
            builder.RegisterType&amp;lt;UnitOfWork&amp;gt;().As&amp;lt;IUnitOfWork&amp;gt;();

            builder.RegisterGeneric(typeof(Repository&amp;lt;&amp;gt;)).As(typeof(IRepository&amp;lt;&amp;gt;));

            builder.RegisterType&amp;lt;BlogMapper&amp;gt;().As&amp;lt;IMapper&amp;lt;Blog, BlogInfo&amp;gt;&amp;gt;();
            builder.RegisterType&amp;lt;PostMapper&amp;gt;().As&amp;lt;IMapper&amp;lt;Post, PostInfo&amp;gt;&amp;gt;();
            builder.RegisterType&amp;lt;TagMapper&amp;gt;().As&amp;lt;IMapper&amp;lt;Tag, TagInfo&amp;gt;&amp;gt;();
            builder.RegisterType&amp;lt;CommentMapper&amp;gt;().As&amp;lt;IMapper&amp;lt;Comment, CommentInfo&amp;gt;&amp;gt;();

            builder.RegisterType&amp;lt;BlogService&amp;gt;().As&amp;lt;IBlogService&amp;gt;();
            builder.RegisterType&amp;lt;PostService&amp;gt;().As&amp;lt;IPostService&amp;gt;();
            builder.RegisterType&amp;lt;TagService&amp;gt;().As&amp;lt;ITagService&amp;gt;();
            builder.RegisterType&amp;lt;CommentService&amp;gt;().As&amp;lt;ICommentService&amp;gt;();
        }
    }
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see In line-9 I am using the &lt;code&gt;PerRequestScoped&lt;/code&gt;, this is an extension method that has been added in the Autofac Adapter, behind the scene it creates a new scope when a new request begins, sets up the current service locator and all the wacky stuffs that you like to avoid.&lt;/p&gt;

&lt;p&gt;Now lets see the most widely used container the Windsor, Windsor has &lt;code&gt;IWindsorInstaller&lt;/code&gt; (which I think has not been highlighted that much) which can be used for modular registration. To create a new installer you have add reference of the &lt;a href="http://www.castleproject.org/castle/download.html"&gt;Windsor 2.1&lt;/a&gt; binaries, CSL, MvcExtensions and Windsor adapter. The following shows the installer which register the services in the container:&lt;/p&gt;

&lt;h3&gt;Windsor&lt;/h3&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:5ca316cd-9079-4a33-b8b2-f39768d0dbe4" class="wlWriterSmartContent"&gt;&lt;pre name="code" class="c#"&gt;namespace MyBlog
{
    using Castle.MicroKernel;
    using Castle.MicroKernel.Registration;
    using Castle.Windsor;

    public class WindsorServiceInstaller : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(Component.For&amp;lt;IDatabaseFactory&amp;gt;().ImplementedBy&amp;lt;DatabaseFactory&amp;gt;().LifeStyle.PerWebRequest)
                     .Register(Component.For&amp;lt;IDatabase&amp;gt;().UsingFactoryMethod(k =&amp;gt; k.Resolve&amp;lt;IDatabaseFactory&amp;gt;().Get()))
                     .Register(Component.For&amp;lt;IUnitOfWork&amp;gt;().ImplementedBy&amp;lt;UnitOfWork&amp;gt;());

            container.Register(Component.For(typeof(IRepository&amp;lt;&amp;gt;)).ImplementedBy(typeof(Repository&amp;lt;&amp;gt;)));

            container.Register(Component.For&amp;lt;IMapper&amp;lt;Blog, BlogInfo&amp;gt;&amp;gt;().ImplementedBy&amp;lt;BlogMapper&amp;gt;())
                     .Register(Component.For&amp;lt;IMapper&amp;lt;Post, PostInfo&amp;gt;&amp;gt;().ImplementedBy&amp;lt;PostMapper&amp;gt;())
                     .Register(Component.For&amp;lt;IMapper&amp;lt;Tag, TagInfo&amp;gt;&amp;gt;().ImplementedBy&amp;lt;TagMapper&amp;gt;())
                     .Register(Component.For&amp;lt;IMapper&amp;lt;Comment, CommentInfo&amp;gt;&amp;gt;().ImplementedBy&amp;lt;CommentMapper&amp;gt;());

            container.Register(Component.For&amp;lt;IBlogService&amp;gt;().ImplementedBy&amp;lt;BlogService&amp;gt;())
                     .Register(Component.For&amp;lt;IPostService&amp;gt;().ImplementedBy&amp;lt;PostService&amp;gt;())
                     .Register(Component.For&amp;lt;ITagService&amp;gt;().ImplementedBy&amp;lt;TagService&amp;gt;())
                     .Register(Component.For&amp;lt;ICommentService&amp;gt;().ImplementedBy&amp;lt;CommentService&amp;gt;());
        }
    }
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I am using the new syntax but you can also use the regular one, when the container is created the &lt;code&gt;ArrayResolver&lt;/code&gt; and &lt;code&gt;FactorySupportFacility&lt;/code&gt; are added, so you do not have to add those, if you need any other facilities you can add those creating new installer.&lt;/p&gt;

&lt;p&gt;And at last, the Unity. Unlike the other containers the Unity does not have the Modular registration support . This is the reason Unity Adapter comes with an special interface &lt;code&gt;IModule&lt;/code&gt; which you have to implement in order to support the modular registration. Let us see the example first, like above you have add to reference of &lt;a href="http://unity.codeplex.com/releases/view/31277"&gt;Unity 2&lt;/a&gt;, CSL, MvcExtensions and Unity Adapter. Next, create a class which implements the &lt;code&gt;IModule&lt;/code&gt; and override the &lt;code&gt;Load&lt;/code&gt; method like the following.&lt;/p&gt;

&lt;h3&gt;Unity&lt;/h3&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:2d3e6c6b-65e7-463a-b72f-eeee25e51a9a" class="wlWriterSmartContent"&gt;&lt;pre name="code" class="c#"&gt;namespace MyBlog
{
    using Microsoft.Practices.Unity;

    using MvcExtensions.Unity;

    public class UnityServiceRegistrationModule : IModule
    {
        public void Load(IUnityContainer container)
        {
            container.RegisterType&amp;lt;IDatabaseFactory, DatabaseFactory&amp;gt;(new PerRequestLifetimeManager())
                     .RegisterType&amp;lt;IDatabase, Database&amp;gt;(new InjectionFactory(c =&amp;gt; c.Resolve&amp;lt;IDatabaseFactory&amp;gt;().Get()))
                     .RegisterType&amp;lt;IUnitOfWork, UnitOfWork&amp;gt;();

            container.RegisterType(typeof(IRepository&amp;lt;&amp;gt;), typeof(Repository&amp;lt;&amp;gt;));

            container.RegisterType&amp;lt;IMapper&amp;lt;Blog, BlogInfo&amp;gt;, BlogMapper&amp;gt;()
                     .RegisterType&amp;lt;IMapper&amp;lt;Post, PostInfo&amp;gt;, PostMapper&amp;gt;()
                     .RegisterType&amp;lt;IMapper&amp;lt;Tag, TagInfo&amp;gt;, TagMapper&amp;gt;()
                     .RegisterType&amp;lt;IMapper&amp;lt;Comment, CommentInfo&amp;gt;, CommentMapper&amp;gt;();

            container.RegisterType&amp;lt;IBlogService, BlogService&amp;gt;()
                     .RegisterType&amp;lt;IPostService, PostService&amp;gt;()
                     .RegisterType&amp;lt;ITagService, TagService&amp;gt;()
                     .RegisterType&amp;lt;ICommentService, CommentService&amp;gt;();
        }
    }
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And like other adapters the MvcExtensions will scan all the assemblies for &lt;code&gt;IModule&lt;/code&gt; and pass the container for your registration. One special thing in line-11, for &lt;code&gt;IDatabaseFactory&lt;/code&gt; we are using &lt;code&gt;PerRequestLifetimeManager&lt;/code&gt; which does not exists in the actual Unity. The issue is like the other containers the Unity does not have any built-in lifetime management support which returns the same service in the same request no matter how many times it has been requested. But it does have the support to create custom lifetime managers, the &lt;code&gt;PerRequestLifetimeManager&lt;/code&gt; is a custom class which is included in the Unity adapter.&lt;/p&gt;

&lt;p&gt;You will find the above code in the bottom of this post. Just make sure the &lt;code&gt;HttpApplication&lt;/code&gt; inherits from you preferred container’s &lt;code&gt;HttpApplication&lt;/code&gt;, currently it is using Autofac.&lt;/p&gt;

&lt;p&gt;In conclusion, as you have seen working with MvcExtensions adapters is nothing different working with the original container. In the next post, we will see how to use the &lt;code&gt;PerRequestTask&lt;/code&gt; and in which scenario it is suitable.&lt;/p&gt;

&lt;p&gt;So, stay tuned.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Download:&lt;/strong&gt; &lt;strong&gt;&lt;a href="http://weblogs.asp.net/blogs/rashid/MyBlog.zip"&gt;MyBlog.zip&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div class="wlWriterHeaderFooter" style="margin:0px; padding:0px 0px 0px 0px;"&gt;&lt;div class="shoutIt"&gt;&lt;a rev="vote-for" href="http://dotnetshoutout.com/Submit?url=http%3a%2f%2fweblogs.asp.net%2frashid%2farchive%2f2010%2f05%2f16%2fmvcextensions-custom-service-registration.aspx&amp;amp;title=MvcExtensions+%e2%80%93+Custom+Service+Registration"&gt;&lt;img alt="Shout it" src="http://dotnetshoutout.com/image.axd?url=http://weblogs.asp.net/rashid/archive/2010/05/16/mvcextensions-custom-service-registration.aspx" style="border:0px" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7485848" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/rashid/archive/tags/Asp.net/default.aspx">Asp.net</category><category domain="http://weblogs.asp.net/rashid/archive/tags/MVC/default.aspx">MVC</category><category domain="http://weblogs.asp.net/rashid/archive/tags/ASPNETMVC/default.aspx">ASPNETMVC</category><category domain="http://weblogs.asp.net/rashid/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><category domain="http://weblogs.asp.net/rashid/archive/tags/IoC_2F00_DI/default.aspx">IoC/DI</category><category domain="http://weblogs.asp.net/rashid/archive/tags/Unity/default.aspx">Unity</category><category domain="http://weblogs.asp.net/rashid/archive/tags/Open+Source/default.aspx">Open Source</category><category domain="http://weblogs.asp.net/rashid/archive/tags/Ninject/default.aspx">Ninject</category><category domain="http://weblogs.asp.net/rashid/archive/tags/StructureMap/default.aspx">StructureMap</category><category domain="http://weblogs.asp.net/rashid/archive/tags/Autofac/default.aspx">Autofac</category><category domain="http://weblogs.asp.net/rashid/archive/tags/Windsor/default.aspx">Windsor</category><category domain="http://weblogs.asp.net/rashid/archive/tags/MvcExtensions/default.aspx">MvcExtensions</category></item><item><title>MvcExtensions – Bootstrapping</title><link>http://weblogs.asp.net/rashid/archive/2010/05/12/mvcextensions-bootstrapping.aspx</link><pubDate>Wed, 12 May 2010 12:29:38 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7480454</guid><dc:creator>kazimanzurrashid</dc:creator><slash:comments>15</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/rashid/rsscomments.aspx?PostID=7480454</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/rashid/commentapi.aspx?PostID=7480454</wfw:comment><comments>http://weblogs.asp.net/rashid/archive/2010/05/12/mvcextensions-bootstrapping.aspx#comments</comments><description>&lt;p&gt;When you create a new ASP.NET MVC application you will find that the &lt;code&gt;global.asax&lt;/code&gt; contains the following lines:&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:31fdbc0c-d349-483b-9ee5-1bdd5f4b4d38" class="wlWriterSmartContent"&gt;&lt;pre name="code" class="c#"&gt;namespace MvcApplication1
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

        }

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterRoutes(RouteTable.Routes);
        }
    }
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As the application grows, there are quite a lot of plumbing code gets into the &lt;code&gt;global.asax&lt;/code&gt; which quickly becomes a design smell. Lets take a quick look at the code of one of the open source project that I recently visited:&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:2d3eeb36-4a0f-4357-92a4-abe056beae10" class="wlWriterSmartContent"&gt;&lt;pre name="code" class="c#"&gt;        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapRoute("Default","{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "" });
        }        
        protected override void OnApplicationStarted()
        {
            Error += OnError;
            EndRequest += OnEndRequest;
            
             var settings = new SparkSettings()
                .AddNamespace("System")
                .AddNamespace("System.Collections.Generic")
                .AddNamespace("System.Web.Mvc")
                .AddNamespace("System.Web.Mvc.Html")
                .AddNamespace("MvcContrib.FluentHtml")
                .AddNamespace("********")
                .AddNamespace("********.Web")
                .SetPageBaseType("ApplicationViewPage")
                .SetAutomaticEncoding(true);
                               
#if DEBUG
            settings.SetDebug(true);
#endif
            var viewFactory = new SparkViewFactory(settings);
            ViewEngines.Engines.Add(viewFactory);
#if !DEBUG            
            PrecompileViews(viewFactory);
#endif            

            RegisterAllControllersIn("********.Web");

            log4net.Config.XmlConfigurator.Configure();            
            RegisterRoutes(RouteTable.Routes);

            Factory.Load(new Components.WebDependencies());
            ModelBinders.Binders.DefaultBinder = new Binders.GenericBinderResolver(Factory.TryGet&amp;lt;IModelBinder&amp;gt;);

            ValidatorConfiguration.Initialize("********");
            HtmlValidationExtensions.Initialize(ValidatorConfiguration.Rules);
        }

        private void OnEndRequest(object sender, System.EventArgs e)
        {
            if (((HttpApplication)sender).Context.Handler is MvcHandler)
            {
                CreateKernel().Get&amp;lt;ISessionSource&amp;gt;().Close();
            }
        }
        private void OnError(object sender, System.EventArgs e)
        {
            CreateKernel().Get&amp;lt;ISessionSource&amp;gt;().Close();
        }
        protected override IKernel CreateKernel()
        {
            return Factory.Kernel;
        }
        
        private static void PrecompileViews(SparkViewFactory viewFactory)
        {
            var batch = new SparkBatchDescriptor();
            batch.For&amp;lt;HomeController&amp;gt;().For&amp;lt;ManageController&amp;gt;();
            viewFactory.Precompile(batch);                  
        }&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see there are quite a few of things going on in the above code, Registering the ViewEngine, Compiling the Views, Registering the Routes/Controllers/Model Binders, Settings up Logger, Validations and as you can imagine the more it becomes complex the more things will get added in the application start.&lt;/p&gt;

&lt;p&gt;One of the goal of the MVCExtensions is to reduce the above design smell. Instead of writing all the plumbing code in the application start, it contains &lt;code&gt;BootstrapperTask&lt;/code&gt; to register individual services. Out of the box, it contains &lt;code&gt;BootstrapperTask&lt;/code&gt; to register Controllers, Controller Factory, Action Invoker, Action Filters, Model Binders, Model Metadata/Validation Providers, ValueProvideraFactory, ViewEngines etc and it is intelligent enough to automatically detect the above types and register into the ASP.NET MVC Framework. Other than the built-in tasks you can create your own custom task which will be automatically executed when the application starts. When the &lt;code&gt;BootstrapperTasks&lt;/code&gt; are in action you will find the &lt;code&gt;global.asax&lt;/code&gt; pretty much clean like the following:&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:27324caf-e71a-4906-b8ec-e6067997e393" class="wlWriterSmartContent"&gt;&lt;pre name="code" class="c#"&gt;public class MvcApplication : UnityMvcApplication
{
    public void ErrorLog_Filtering(object sender, ExceptionFilterEventArgs e)
    {
        Check.Argument.IsNotNull(e, "e");

        HttpException exception = e.Exception.GetBaseException() as HttpException;

        if ((exception != null) &amp;amp;&amp;amp; (exception.GetHttpCode() == (int)HttpStatusCode.NotFound))
        {
            e.Dismiss();
        }
    }
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The above code is taken from my another open source project &lt;a href="http://shrinkr.codeplex.com"&gt;Shrinkr&lt;/a&gt;, as you can see the &lt;code&gt;global.asax&lt;/code&gt; is longer cluttered with any plumbing code. One special thing you have noticed that it is inherited from the &lt;code&gt;UnityMvcApplication&lt;/code&gt; rather than regular &lt;code&gt;HttpApplication&lt;/code&gt;. There are separate version of this class for each IoC Container like &lt;code&gt;NinjectMvcApplication&lt;/code&gt;, &lt;code&gt;StructureMapMvcApplication&lt;/code&gt; etc.&lt;/p&gt;

&lt;p&gt;Other than executing the built-in tasks, the Shrinkr also has few custom tasks which gets executed when the application starts. For example, when the application starts, we want to ensure that the default users (which is specified in the &lt;code&gt;web.config&lt;/code&gt;) are created. The following is the custom task that is used to create those default users:&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:1d90067b-7cc3-48e3-b173-c6aba6d36c08" class="wlWriterSmartContent"&gt;&lt;pre name="code" class="c#"&gt;public class CreateDefaultUsers : BootstrapperTask
{
    protected override TaskContinuation ExecuteCore(IServiceLocator serviceLocator)
    {
        IUserRepository userRepository = serviceLocator.GetInstance&amp;lt;IUserRepository&amp;gt;();
        IUnitOfWork unitOfWork = serviceLocator.GetInstance&amp;lt;IUnitOfWork&amp;gt;();
        IEnumerable&amp;lt;User&amp;gt; users = serviceLocator.GetInstance&amp;lt;Settings&amp;gt;().DefaultUsers;

        bool shouldCommit = false;

        foreach (User user in users)
        {
            if (userRepository.GetByName(user.Name) == null)
            {
                user.AllowApiAccess(ApiSetting.InfiniteLimit);

                userRepository.Add(user);
                shouldCommit = true;
            }
        }

        if (shouldCommit)
        {
            unitOfWork.Commit();
        }

        return TaskContinuation.Continue;
    }
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There are several other Tasks in the Shrinkr that we are also using which you will find in that &lt;a href="http://shrinkr.codeplex.com/"&gt;project&lt;/a&gt;. To create a custom bootstrapping task you have create a new class which either implements the &lt;code&gt;IBootstrapperTask&lt;/code&gt; interface or inherits from the abstract &lt;code&gt;BootstrapperTask&lt;/code&gt; class, I would recommend to start with the &lt;code&gt;BootstrapperTask&lt;/code&gt; as it already has the required code that you have to write in case if you choose the &lt;code&gt;IBootstrapperTask&lt;/code&gt; interface. As you can see in the above code we are overriding the &lt;code&gt;ExecuteCore&lt;/code&gt; to create the default users, the MVCExtensions is responsible for populating the&amp;#160; &lt;a href="http://commonservicelocator.codeplex.com"&gt;ServiceLocator&lt;/a&gt; prior calling this method and in this method we are using the service locator to get the dependencies that are required to create the users (I will cover the custom dependencies registration in the next post). Once the users are created, we are returning a special &lt;code&gt;enum,&lt;/code&gt; &lt;code&gt;TaskContinuation&lt;/code&gt; as the return value, the &lt;code&gt;TaskContinuation&lt;/code&gt; can have three values &lt;code&gt;Continue&lt;/code&gt; (default), &lt;code&gt;Skip&lt;/code&gt; and &lt;code&gt;Break&lt;/code&gt;. The reason behind of having this enum is, in some&amp;#160; special cases you might want to skip the next task in the chain or break the complete chain depending upon the currently running task, in those cases you will use the other two values instead of the &lt;code&gt;Continue&lt;/code&gt;. The last thing I want to cover in the bootstrapping task is the Order. By default all the built-in tasks as well as newly created task order is set to the &lt;code&gt;DefaultOrder&lt;/code&gt;(a static property), in some special cases you might want to execute it before/after all the other tasks, in those cases you will assign the Order in the Task constructor. For Example, in Shrinkr, we want to run few background services when the all the tasks are executed, so we assigned the order as DefaultOrder + 1. Here is the code of that Task:&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:a106aaaa-50e0-44d0-8747-65259a4fc98d" class="wlWriterSmartContent"&gt;&lt;pre name="code" class="c#"&gt;public class ConfigureBackgroundServices : BootstrapperTask
{
    private IEnumerable&amp;lt;IBackgroundService&amp;gt; backgroundServices;

    public ConfigureBackgroundServices()
    {
        Order = DefaultOrder + 1;
    }

    protected override TaskContinuation ExecuteCore(IServiceLocator serviceLocator)
    {
        backgroundServices = serviceLocator.GetAllInstances&amp;lt;IBackgroundService&amp;gt;().ToList();

        backgroundServices.Each(service =&amp;gt; service.Start());

        return TaskContinuation.Continue;
    }

    protected override void DisposeCore()
    {
        backgroundServices.Each(service =&amp;gt; service.Stop());
    }
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;That’s it for today, in the next post I will cover the custom service registration, so stay tuned.&lt;/p&gt;&lt;div class="wlWriterHeaderFooter" style="margin:0px; padding:0px 0px 0px 0px;"&gt;&lt;div class="shoutIt"&gt;&lt;a rev="vote-for" href="http://dotnetshoutout.com/Submit?url=http%3a%2f%2fweblogs.asp.net%2frashid%2farchive%2f2010%2f05%2f12%2fmvcextensions-bootstrapping.aspx&amp;amp;title=MvcExtensions+%e2%80%93+Bootstrapping"&gt;&lt;img alt="Shout it" src="http://dotnetshoutout.com/image.axd?url=http://weblogs.asp.net/rashid/archive/2010/05/12/mvcextensions-bootstrapping.aspx" style="border:0px" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7480454" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/rashid/archive/tags/Asp.net/default.aspx">Asp.net</category><category domain="http://weblogs.asp.net/rashid/archive/tags/MVC/default.aspx">MVC</category><category domain="http://weblogs.asp.net/rashid/archive/tags/ASPNETMVC/default.aspx">ASPNETMVC</category><category domain="http://weblogs.asp.net/rashid/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><category domain="http://weblogs.asp.net/rashid/archive/tags/Open+Source/default.aspx">Open Source</category><category domain="http://weblogs.asp.net/rashid/archive/tags/Shrinkr/default.aspx">Shrinkr</category><category domain="http://weblogs.asp.net/rashid/archive/tags/MvcExtensions/default.aspx">MvcExtensions</category></item><item><title>Announcing the RTM of MvcExtensions (aka System.Web.Mvc.Extensibility)</title><link>http://weblogs.asp.net/rashid/archive/2010/05/11/announcing-the-rtm-of-mvcextensions-aka-system-web-mvc-extensibility.aspx</link><pubDate>Tue, 11 May 2010 15:02:12 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:7479408</guid><dc:creator>kazimanzurrashid</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/rashid/rsscomments.aspx?PostID=7479408</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/rashid/commentapi.aspx?PostID=7479408</wfw:comment><comments>http://weblogs.asp.net/rashid/archive/2010/05/11/announcing-the-rtm-of-mvcextensions-aka-system-web-mvc-extensibility.aspx#comments</comments><description>&lt;p&gt;I am proud to announce the v1.0 of MvcExtensions (previously known as System.Web.Extensibility). There has been quite a few changes and enhancements since the &lt;a href="http://weblogs.asp.net/rashid/archive/2010/01/25/just-released-system-web-mvc-extensibility-beta.aspx"&gt;last release&lt;/a&gt;. Some of the major changes are:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The Namespace has been changed to MvcExtensions from System.Web.Mvc.Extensibility to avoid the unnecessary confusion that it is in the .NET Framework or part of the ASP.NET MVC. &lt;/li&gt;    &lt;li&gt;The Project is now moved to &lt;a href="http://mvcextensions.codeplex.com/"&gt;CodePlex&lt;/a&gt; from the &lt;a href="http://github.com/kazimanzurrashid/AspNetMvcExtensibility"&gt;GitHub&lt;/a&gt;. The primary reason to start the project over GitHub was distributed version control which is no longer valid as CodePlex recently added the Mercurial support. There is nothing wrong with GitHub, it is an excellent place for managing your project. But CodePlex has always been the native place for .NET project. &lt;/li&gt;    &lt;li&gt;MVC 1.0 support has been dropped.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I will be covering each features in my blog, so stay tuned!!!&lt;/p&gt;&lt;div class="wlWriterHeaderFooter" style="margin:0px; padding:0px 0px 0px 0px;"&gt;&lt;div class="shoutIt"&gt;&lt;a rev="vote-for" href="http://dotnetshoutout.com/Submit?url=http%3a%2f%2fweblogs.asp.net%2frashid%2farchive%2f2010%2f05%2f11%2fannouncing-the-rtm-of-mvcextensions-aka-system-web-mvc-extensibility.aspx&amp;amp;title=Announcing+the+RTM+of+MvcExtensions+(aka+System.Web.Mvc.Extensibility)"&gt;&lt;img alt="Shout it" src="http://dotnetshoutout.com/image.axd?url=http://weblogs.asp.net/rashid/archive/2010/05/11/announcing-the-rtm-of-mvcextensions-aka-system-web-mvc-extensibility.aspx" style="border:0px" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7479408" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/rashid/archive/tags/Asp.net/default.aspx">Asp.net</category><category domain="http://weblogs.asp.net/rashid/archive/tags/MVC/default.aspx">MVC</category><category domain="http://weblogs.asp.net/rashid/archive/tags/ASPNETMVC/default.aspx">ASPNETMVC</category><category domain="http://weblogs.asp.net/rashid/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><category domain="http://weblogs.asp.net/rashid/archive/tags/IoC_2F00_DI/default.aspx">IoC/DI</category><category domain="http://weblogs.asp.net/rashid/archive/tags/Open+Source/default.aspx">Open Source</category><category domain="http://weblogs.asp.net/rashid/archive/tags/MvcExtensions/default.aspx">MvcExtensions</category></item></channel></rss>