In the previous post, we have seen the BootstrapperTask 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 HttpModule 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 HttpContext and its tail, also defining the HttpModule execution order is bit cumbersome, you either have to modify the machine.config or clear the HttpModules and add it again in web.config. Instead, you can use the PerRequestTask which is very much container friendly as well as supports execution orders. Lets few examples where it can be used.

Remove www Subdomain

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.

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;
    }
}

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 ExecuteCore, 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.

Blocking IP Address

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 IBannedIPAddressRepository service which is used to match banned IP Address.

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<IBannedIPAddressRepository>().IsMatching(ipAddress))
            {
                httpResponse.StatusCode = (int)HttpStatusCode.Forbidden;
                httpResponse.StatusDescription = "IPAddress blocked.";

                shouldContinue = false;
            }
        }

        return shouldContinue ? TaskContinuation.Continue : TaskContinuation.Break;
    }
}

Managing Database Session

Now, let see how it can be used to manage NHibernate session, assuming that ISessionFactory of NHibernate is already registered in our container.

public class ManageNHibernateSession : PerRequestTask
{
    private ISession session;

    protected override TaskContinuation ExecuteCore(PerRequestExecutionContext executionContext)
    {
        ISessionFactory factory = executionContext.ServiceLocator.GetInstance<ISessionFactory>();

        session = factory.OpenSession();

        return TaskContinuation.Continue;
    }

    protected override void DisposeCore()
    {
        session.Close();
        session.Dispose();
    }
}

As you can see PerRequestTask 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 HttpModule.

That’s it for today, in the next post, we will discuss about the Action Filters, so stay tuned.

Shout it

[Special Note: I have just released SP1 Preview which contains the newly added Autofac Adapter and minor Windsor changes]

In this post, I will show you how you can register your custom services in your preferred IoC container and how the MvcExtensions 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 CommonServiceLocator(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 IServiceRegistrar and IServiceInjector 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.

Lets take a fictitious blogging application as an example to see how the registration works and assume that blogging application contains Database, DatabaseFactory, UnitOfWork, Repository, few Domain Services and Mappers(converts domain objects into data transfer objects) as custom services.

Lets start with the Ninject, first you have to add reference of Ninject 2, which you can find from Ninject official site, next you have to add reference of CSL 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:

Ninject

namespace MyBlog
{
    using Ninject;
    using Ninject.Modules;

    public class NinjectServiceRegistrationModule : NinjectModule
    {
        public override void Load()
        {
            Bind<IDatabaseFactory>().To<DatabaseFactory>().InRequestScope();
            Bind<IDatabase>().ToMethod(c => c.Kernel.Get<IDatabaseFactory>().Get());
            Bind<IUnitOfWork>().To<UnitOfWork>();

            Bind(typeof(IRepository<>)).To(typeof(Repository<>));

            Bind<IMapper<Blog, BlogInfo>>().To<BlogMapper>();
            Bind<IMapper<Post, PostInfo>>().To<PostMapper>();
            Bind<IMapper<Tag, TagInfo>>().To<TagMapper>();
            Bind<IMapper<Comment, CommentInfo>>().To<CommentMapper>();

            Bind<IBlogService>().To<BlogService>();
            Bind<IPostService>().To<PostService>();
            Bind<ITagService>().To<TagService>();
            Bind<ICommentService>().To<CommentService>();
        }
    }
}

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,  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 BootstrapperTask which I have discussed in my last post.

Now, lets see how we can use StructureMap to register the above services. First, we will add reference of StructureMap 2.6.1, 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:

StructureMap

namespace MyBlog
{
    using StructureMap.Configuration.DSL;

    public class StructureMapServiceRegistry : Registry
    {
        public StructureMapServiceRegistry()
        {
            For<IDatabaseFactory>().HttpContextScoped().Use<DatabaseFactory>();
            For<IDatabase>().Use(c => c.GetInstance<IDatabaseFactory>().Get());
            For<IUnitOfWork>().Use<UnitOfWork>();

            For(typeof(IRepository<>)).Use(typeof(Repository<>));

            For<IMapper<Blog, BlogInfo>>().Use<BlogMapper>();
            For<IMapper<Post, PostInfo>>().Use<PostMapper>();
            For<IMapper<Tag, TagInfo>>().Use<TagMapper>();
            For<IMapper<Comment, CommentInfo>>().Use<CommentMapper>();

            For<IBlogService>().Use<BlogService>();
            For<IPostService>().Use<PostService>();
            For<ITagService>().Use<TagService>();
            For<ICommentService>().Use<CommentService>();
        }
    }
}

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.

Next, the Autofac (it has been re-added in the SP1 Preview), Autofac also has a Module which acts same as Ninject Module and StructureMap Registry. Before creating the Module, you have add reference of Autofac 2.2.3 Preview, CSL, MvcExtensions and Autofac Adapter. The following shows the Autofac registration:

Autofac

namespace MyBlog
{
    using Autofac;

    public class AutofacServiceRegistrationModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterType<DatabaseFactory>().As<IDatabaseFactory>().PerRequestScoped();
            builder.Register(c => c.Resolve<IDatabaseFactory>().Get()).As<IDatabase>();
            builder.RegisterType<UnitOfWork>().As<IUnitOfWork>();

            builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));

            builder.RegisterType<BlogMapper>().As<IMapper<Blog, BlogInfo>>();
            builder.RegisterType<PostMapper>().As<IMapper<Post, PostInfo>>();
            builder.RegisterType<TagMapper>().As<IMapper<Tag, TagInfo>>();
            builder.RegisterType<CommentMapper>().As<IMapper<Comment, CommentInfo>>();

            builder.RegisterType<BlogService>().As<IBlogService>();
            builder.RegisterType<PostService>().As<IPostService>();
            builder.RegisterType<TagService>().As<ITagService>();
            builder.RegisterType<CommentService>().As<ICommentService>();
        }
    }
}

As you can see In line-9 I am using the PerRequestScoped, 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.

Now lets see the most widely used container the Windsor, Windsor has IWindsorInstaller (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 Windsor 2.1 binaries, CSL, MvcExtensions and Windsor adapter. The following shows the installer which register the services in the container:

Windsor

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<IDatabaseFactory>().ImplementedBy<DatabaseFactory>().LifeStyle.PerWebRequest)
                     .Register(Component.For<IDatabase>().UsingFactoryMethod(k => k.Resolve<IDatabaseFactory>().Get()))
                     .Register(Component.For<IUnitOfWork>().ImplementedBy<UnitOfWork>());

            container.Register(Component.For(typeof(IRepository<>)).ImplementedBy(typeof(Repository<>)));

            container.Register(Component.For<IMapper<Blog, BlogInfo>>().ImplementedBy<BlogMapper>())
                     .Register(Component.For<IMapper<Post, PostInfo>>().ImplementedBy<PostMapper>())
                     .Register(Component.For<IMapper<Tag, TagInfo>>().ImplementedBy<TagMapper>())
                     .Register(Component.For<IMapper<Comment, CommentInfo>>().ImplementedBy<CommentMapper>());

            container.Register(Component.For<IBlogService>().ImplementedBy<BlogService>())
                     .Register(Component.For<IPostService>().ImplementedBy<PostService>())
                     .Register(Component.For<ITagService>().ImplementedBy<TagService>())
                     .Register(Component.For<ICommentService>().ImplementedBy<CommentService>());
        }
    }
}

I am using the new syntax but you can also use the regular one, when the container is created the ArrayResolver and FactorySupportFacility are added, so you do not have to add those, if you need any other facilities you can add those creating new installer.

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 IModule 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 Unity 2, CSL, MvcExtensions and Unity Adapter. Next, create a class which implements the IModule and override the Load method like the following.

Unity

namespace MyBlog
{
    using Microsoft.Practices.Unity;

    using MvcExtensions.Unity;

    public class UnityServiceRegistrationModule : IModule
    {
        public void Load(IUnityContainer container)
        {
            container.RegisterType<IDatabaseFactory, DatabaseFactory>(new PerRequestLifetimeManager())
                     .RegisterType<IDatabase, Database>(new InjectionFactory(c => c.Resolve<IDatabaseFactory>().Get()))
                     .RegisterType<IUnitOfWork, UnitOfWork>();

            container.RegisterType(typeof(IRepository<>), typeof(Repository<>));

            container.RegisterType<IMapper<Blog, BlogInfo>, BlogMapper>()
                     .RegisterType<IMapper<Post, PostInfo>, PostMapper>()
                     .RegisterType<IMapper<Tag, TagInfo>, TagMapper>()
                     .RegisterType<IMapper<Comment, CommentInfo>, CommentMapper>();

            container.RegisterType<IBlogService, BlogService>()
                     .RegisterType<IPostService, PostService>()
                     .RegisterType<ITagService, TagService>()
                     .RegisterType<ICommentService, CommentService>();
        }
    }
}

And like other adapters the MvcExtensions will scan all the assemblies for IModule and pass the container for your registration. One special thing in line-11, for IDatabaseFactory we are using PerRequestLifetimeManager 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 PerRequestLifetimeManager is a custom class which is included in the Unity adapter.

You will find the above code in the bottom of this post. Just make sure the HttpApplication inherits from you preferred container’s HttpApplication, currently it is using Autofac.

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 PerRequestTask and in which scenario it is suitable.

So, stay tuned.

Download: MyBlog.zip

Shout it

When you create a new ASP.NET MVC application you will find that the global.asax contains the following lines:

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);
        }
    }
}

As the application grows, there are quite a lot of plumbing code gets into the global.asax 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:

        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<IModelBinder>);

            ValidatorConfiguration.Initialize("********");
            HtmlValidationExtensions.Initialize(ValidatorConfiguration.Rules);
        }

        private void OnEndRequest(object sender, System.EventArgs e)
        {
            if (((HttpApplication)sender).Context.Handler is MvcHandler)
            {
                CreateKernel().Get<ISessionSource>().Close();
            }
        }
        private void OnError(object sender, System.EventArgs e)
        {
            CreateKernel().Get<ISessionSource>().Close();
        }
        protected override IKernel CreateKernel()
        {
            return Factory.Kernel;
        }
        
        private static void PrecompileViews(SparkViewFactory viewFactory)
        {
            var batch = new SparkBatchDescriptor();
            batch.For<HomeController>().For<ManageController>();
            viewFactory.Precompile(batch);                  
        }

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.

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 BootstrapperTask to register individual services. Out of the box, it contains BootstrapperTask 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 BootstrapperTasks are in action you will find the global.asax pretty much clean like the following:

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) && (exception.GetHttpCode() == (int)HttpStatusCode.NotFound))
        {
            e.Dismiss();
        }
    }
}

The above code is taken from my another open source project Shrinkr, as you can see the global.asax is longer cluttered with any plumbing code. One special thing you have noticed that it is inherited from the UnityMvcApplication rather than regular HttpApplication. There are separate version of this class for each IoC Container like NinjectMvcApplication, StructureMapMvcApplication etc.

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 web.config) are created. The following is the custom task that is used to create those default users:

public class CreateDefaultUsers : BootstrapperTask
{
    protected override TaskContinuation ExecuteCore(IServiceLocator serviceLocator)
    {
        IUserRepository userRepository = serviceLocator.GetInstance<IUserRepository>();
        IUnitOfWork unitOfWork = serviceLocator.GetInstance<IUnitOfWork>();
        IEnumerable<User> users = serviceLocator.GetInstance<Settings>().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;
    }
}

There are several other Tasks in the Shrinkr that we are also using which you will find in that project. To create a custom bootstrapping task you have create a new class which either implements the IBootstrapperTask interface or inherits from the abstract BootstrapperTask class, I would recommend to start with the BootstrapperTask as it already has the required code that you have to write in case if you choose the IBootstrapperTask interface. As you can see in the above code we are overriding the ExecuteCore to create the default users, the MVCExtensions is responsible for populating the  ServiceLocator 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 enum, TaskContinuation as the return value, the TaskContinuation can have three values Continue (default), Skip and Break. The reason behind of having this enum is, in some  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 Continue. 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 DefaultOrder(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:

public class ConfigureBackgroundServices : BootstrapperTask
{
    private IEnumerable<IBackgroundService> backgroundServices;

    public ConfigureBackgroundServices()
    {
        Order = DefaultOrder + 1;
    }

    protected override TaskContinuation ExecuteCore(IServiceLocator serviceLocator)
    {
        backgroundServices = serviceLocator.GetAllInstances<IBackgroundService>().ToList();

        backgroundServices.Each(service => service.Start());

        return TaskContinuation.Continue;
    }

    protected override void DisposeCore()
    {
        backgroundServices.Each(service => service.Stop());
    }
}

That’s it for today, in the next post I will cover the custom service registration, so stay tuned.

Shout it

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 last release. Some of the major changes are:

  • 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.
  • The Project is now moved to CodePlex from the GitHub. 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.
  • MVC 1.0 support has been dropped.

I will be covering each features in my blog, so stay tuned!!!

Shout it

Few months back, I started blogging on developing a Url Shrinking Service in ASP.NET MVC, but could not complete it due to my engagement with my professional projects. Recently, I was able to manage some time for this project to complete the remaining features that we planned for the initial release. So I am announcing the official release, the source code is hosted in codeplex, you can also see it live in action over here.

The features that we have implemented so far:

Public:

  • OpenID Login.
  • Base 36 and 62 based Url generation.
  • 301 and 302 Redirect.
  • Custom Alias.
  • Maintaining Generated Urls of User.
  • Url Thumbnail.
  • Spam Detection through Google Safe Browsing.
  • Preview Page (with google warning).
  • REST based API for URL shrinking (json/xml/text).

Control Panel:

  • Application Health monitoring.
  • Marking Url as Spam/Safe.
  • Block/Unblock User.
  • Allow/Disallow User API Access.
  • Manage Banned Domains
  • Manage Banned Ip Address.
  • Manage Reserved Alias.
  • Manage Bad Words.
  • Twitter Notification when spam submitted.

Behind the scene it is developed with:

  • Entity Framework 4 (Code Only)
  • ASP.NET MVC 2
  • AspNetMvcExtensibility
  • Telerik Extensions for ASP.NET MVC (yes you can you use it freely in your open source projects)
  • DotNetOpenAuth
  • Elmah
  • Moq
  • xUnit.net
  • jQuery

We will be also be releasing  a minor update in few weeks which will contain some of the popular twitter client plug-ins and samples how to use the REST API, we will also try to include the nHibernate + Spark version in that release. In the next release, not sure about the timeline, we will include the Geo-Coding and some rich reporting for both the User and the Administrators.

Enjoy!!!

Shout it

One of the nice thing of our Telerik Extensions for ASP.NET MVC is, it gives you an excellent extensible platform to create rich view components. In this post, I will show you a tiny but very powerful ListView Component. Those who are familiar with the Webforms ListView component already knows that it has the support to define different parts of the component, we will have the same kind of support in our view component. Before showing you the markup, let me show you the screenshots first, lets say you want to show the customers of Northwind database as pagable list of business card (Yes the example is inspired from our RadControls Suite)

ListView-Customers

And here is the markup of the above view component.

<h2>Customers</h2>
<% Html.Telerik()
       .ListView(Model)
       .Name("customers")
       .PrefixUrlParameters(false)
       .BeginLayout(pager =>
                     {%>
                        <table border="0" cellpadding="3" cellspacing="1">
                            <tfoot>
                                <tr>
                                    <td colspan="3" class="t-footer">
                                        <% pager.Render(); %>
                                    </td>
                                </tr>
                            </tfoot>
                            <tbody>
                                <tr>
                      <%})
       .BeginGroup(() =>
                     {%>
                        <td>
                      <%})
       .Item(item =>
                     {%>
                        <fieldset style="border:1px solid #e0e0e0">
                            <legend><strong>Company Name</strong>:<%= Html.Encode(item.DataItem.CompanyName) %></legend>
                            <div>
                                <div style="float:left;width:120px">
                                    <img alt="<%= item.DataItem.CustomerID %>" src="<%= Url.Content("~/Content/Images/Customers/" + item.DataItem.CustomerID + ".jpg") %>"/>
                                </div>
                                <div style="float:right">
                                    <ul style="list-style:none none;padding:10px;margin:0">
                                        <li>
                                            <strong>Contact Name:</strong>
                                            <%= Html.Encode(item.DataItem.ContactName) %>
                                        </li>
                                        <li>
                                            <strong>Title:</strong>
                                            <%= Html.Encode(item.DataItem.ContactTitle) %>
                                        </li>
                                        <li>
                                            <strong>City:</strong>
                                            <%= Html.Encode(item.DataItem.City)%>
                                        </li>
                                        <li>
                                            <strong>Country:</strong>
                                            <%= Html.Encode(item.DataItem.Country)%>
                                        </li>
                                        <li>
                                            <strong>Phone:</strong>
                                            <%= Html.Encode(item.DataItem.Phone)%>
                                        </li>
                                        <li>
                                            <div style="float:right">
                                                <%= Html.ActionLink("Edit", "Edit", new { id = item.DataItem.CustomerID }) %>
                                                <%= Html.ActionLink("Delete", "Delete", new { id = item.DataItem.CustomerID })%>
                                            </div>
                                        </li>
                                    </ul>
                                </div>
                            </div>
                        </fieldset>
                     <%})
       .EmptyItem(() =>{%>
                        <fieldset style="border:1px solid #e0e0e0">
                            <legend>Empty</legend>
                        </fieldset>
                     <%})
       .EndGroup(() =>
                     {%>
                        </td>
                      <%})
       .EndLayout(pager =>
                     {%>
                                </tr>
                            </tbody>
                        </table>
                     <%})
       .GroupItemCount(3)
       .PageSize(6)
       .Pager<NumericPager>(pager => pager.ShowFirstLast())
       .Render(); %>

As you can see that you have the complete control on the final angel brackets and like the webform’s version you also can define the templates. You can also use this component to show Master/Detail data, for example the customers and its order like the following:

ListView-Orders

I am attaching the complete source code along with the above examples for your review, what do you think, how about creating some component with our extensions?

Download: MvcListView.zip

Shout it

Depending on the application sometimes we have to maintain some shared service throughout our application. Let’s say you are developing a multi-blog supported blog engine where both the controller and view must know the currently visiting blog, it’s setting , user information and url generation service. In this post, I will show you how you can handle this kind of case in most convenient way.

First, let see the most basic way, we can create our PostController in the following way:

public class PostController : Controller
{
    public PostController(dependencies...) { }

    public ActionResult Index(string blogName, int? page)
    {
        BlogInfo blog = blogSerivce.FindByName(blogName);

        if (blog == null)
        {
            return new NotFoundResult();
        }

        IEnumerable<PostInfo> posts = postService.FindPublished(blog.Id, PagingCalculator.StartIndex(page, blog.PostPerPage), blog.PostPerPage);
        int count = postService.GetPublishedCount(blog.Id);

        UserInfo user = null;

        if (HttpContext.User.Identity.IsAuthenticated)
        {
            user = userService.FindByName(HttpContext.User.Identity.Name);
        }

        return View(new IndexViewModel(urlResolver, user, blog, posts, count, page));
    }

    public ActionResult Archive(string blogName, int? page, ArchiveDate archiveDate)
    {
        BlogInfo blog = blogSerivce.FindByName(blogName);

        if (blog == null)
        {
            return new NotFoundResult();
        }

        IEnumerable<PostInfo> posts = postService.FindArchived(blog.Id, archiveDate, PagingCalculator.StartIndex(page, blog.PostPerPage), blog.PostPerPage);
        int count = postService.GetArchivedCount(blog.Id, archiveDate);

        UserInfo user = null;

        if (HttpContext.User.Identity.IsAuthenticated)
        {
            user = userService.FindByName(HttpContext.User.Identity.Name);
        }

        return View(new ArchiveViewModel(urlResolver, user, blog, posts, count, page, achiveDate));
    }

    public ActionResult Tag(string blogName, string tagSlug, int? page)
    {
        BlogInfo blog = blogSerivce.FindByName(blogName);

        if (blog == null)
        {
            return new NotFoundResult();
        }

        TagInfo tag = tagService.FindBySlug(blog.Id, tagSlug);

        if (tag == null)
        {
            return new NotFoundResult();
        }

        IEnumerable<PostInfo> posts = postService.FindPublishedByTag(blog.Id, tag.Id, PagingCalculator.StartIndex(page, blog.PostPerPage), blog.PostPerPage);
        int count = postService.GetPublishedCountByTag(tag.Id);

        UserInfo user = null;

        if (HttpContext.User.Identity.IsAuthenticated)
        {
            user = userService.FindByName(HttpContext.User.Identity.Name);
        }

        return View(new TagViewModel(urlResolver, user, blog, posts, count, page, tag));
    }
}

As you can see the above code heavily depends upon the current blog and the blog retrieval code is duplicated in all of the action methods, once the blog is retrieved the same blog is passed in the view model. Other than the blog the view also needs the current user and url resolver to render it properly. One way to remove the duplicate blog retrieval code is to create a custom model binder which converts the blog from a blog name and use the blog a parameter in the action methods instead of the string blog name, but it only helps the first half in the above scenario, the action methods still have to pass the blog, user and url resolver etc in the view model.

Now lets try to improve the the above code, first lets create a new class which would contain the shared services, lets name it as BlogContext:

public class BlogContext
{
    public BlogInfo Blog { get; set; }

    public UserInfo User { get; set; }

    public IUrlResolver UrlResolver { get; set; }
}

Next, we will create an interface, IContextAwareService:

public interface IContextAwareService
{
    BlogContext Context { get; set; }
}

The idea is, whoever needs these shared services needs to implement this interface, in our case both the controller and the view model, now we will create an action filter which will be responsible for populating the context:

public class PopulateBlogContextAttribute : FilterAttribute, IActionFilter
    {
        private static string blogNameRouteParameter = "blogName";

        private readonly IBlogService blogService;
        private readonly IUserService userService;

        private readonly BlogContext context;

        public PopulateBlogContextAttribute(IBlogService blogService, IUserService userService, IUrlResolver urlResolver)
        {
            Invariant.IsNotNull(blogService, "blogService");
            Invariant.IsNotNull(userService, "userService");
            Invariant.IsNotNull(urlResolver, "urlResolver");

            this.blogService = blogService;
            this.userService = userService;

            context = new BlogContext { UrlResolver = urlResolver };
        }

        public static string BlogNameRouteParameter
        {
            [DebuggerStepThrough]
            get { return blogNameRouteParameter; }

            [DebuggerStepThrough]
            set { blogNameRouteParameter = value; }
        }

        public void OnActionExecuting(ActionExecutingContext filterContext)
        {
            string blogName = (string) filterContext.Controller.ValueProvider.GetValue(BlogNameRouteParameter).ConvertTo(typeof(string), Culture.Current);

            if (!string.IsNullOrWhiteSpace(blogName))
            {
                context.Blog = blogService.FindByName(blogName);
            }

            if (context.Blog == null)
            {
                filterContext.Result = new NotFoundResult();
                return;
            }

            if (filterContext.HttpContext.User.Identity.IsAuthenticated)
            {
                context.User = userService.FindByName(filterContext.HttpContext.User.Identity.Name);
            }

            IContextAwareService controller = filterContext.Controller as IContextAwareService;

            if (controller != null)
            {
                controller.Context = context;
            }
        }

        public void OnActionExecuted(ActionExecutedContext filterContext)
        {
            Invariant.IsNotNull(filterContext, "filterContext");

            if ((filterContext.Exception == null) || filterContext.ExceptionHandled)
            {
                IContextAwareService model = filterContext.Controller.ViewData.Model as IContextAwareService;

                if (model != null)
                {
                    model.Context = context;
                }
            }
        }
    }

As you can see we are populating the context in the OnActionExecuting, which executes just before the controllers action methods executes, so by the time our action methods executes the context is already populated, next we are are assigning the same context in the view model in OnActionExecuted method which executes just after we set the  model and return the view in our action methods.

Now, lets change the view models so that it implements this interface:

public class IndexViewModel : IContextAwareService
{
	// More Codes
}

public class ArchiveViewModel : IContextAwareService
{
	// More Codes
}

public class TagViewModel : IContextAwareService
{
	// More Codes
}

and the controller:

public class PostController : Controller, IContextAwareService
{
    public PostController(dependencies...) { }

    public BlogContext Context
    {
        get;
        set;
    }

    public ActionResult Index(int? page)
    {
        IEnumerable<PostInfo> posts = postService.FindPublished(Context.Blog.Id, PagingCalculator.StartIndex(page, Context.Blog.PostPerPage), Context.Blog.PostPerPage);
        int count = postService.GetPublishedCount(Context.Blog.Id);

        return View(new IndexViewModel(posts, count, page));
    }

    public ActionResult Archive(int? page, ArchiveDate archiveDate)
    {
        IEnumerable<PostInfo> posts = postService.FindArchived(Context.Blog.Id, archiveDate, PagingCalculator.StartIndex(page, Context.Blog.PostPerPage), Context.Blog.PostPerPage);
        int count = postService.GetArchivedCount(Context.Blog.Id, archiveDate);

        return View(new ArchiveViewModel(posts, count, page, achiveDate));
    }

    public ActionResult Tag(string blogName, string tagSlug, int? page)
    {
        TagInfo tag = tagService.FindBySlug(Context.Blog.Id, tagSlug);

        if (tag == null)
        {
            return new NotFoundResult();
        }

        IEnumerable<PostInfo> posts = postService.FindPublishedByTag(Context.Blog.Id, tag.Id, PagingCalculator.StartIndex(page, Context.Blog.PostPerPage), Context.Blog.PostPerPage);
        int count = postService.GetPublishedCountByTag(tag.Id);

        return View(new TagViewModel(posts, count, page, tag));
    }
}

Now, the last thing where we have to glue everything, I will be using the AspNetMvcExtensibility to register the action filter (as there is no better way to inject the dependencies in action filters).

public class RegisterFilters : RegisterFiltersBase
{
    private static readonly Type controllerType = typeof(Controller);
    private static readonly Type contextAwareType = typeof(IContextAwareService);

    protected override void Register(IFilterRegistry registry)
    {
        TypeCatalog controllers = new TypeCatalogBuilder()
                                      .Add(GetType().Assembly)
                                      .Include(type => controllerType.IsAssignableFrom(type) && contextAwareType.IsAssignableFrom(type));

        registry.Register<PopulateBlogContextAttribute>(controllers);
    }
}

Thoughts and Comments?

Shout it

One of the exciting feature of ASP.NET MVC is(?) auto generating the view of the model with DisplayForModel/EditorForModel statement, it gives a nice extension point for the application developers to customize the view. But in the latest release (MVC2 RC2), it looks like the feature is no longer available. No, those methods are still available, but they are not working the same way as they were doing in the earlier versions. In rc2, if your model has any complex object, it will not render it . I know some of you like myself thought, one of the major changes in rc2 is the Input Validation vs. Model Validation in ASP.NET MVC and rest of it is bug fixing and some improvements. I did check the release note doc, where it is mentioned as

Templated helpers such as Html.EditorFor and Html.DisplayFor show only simple properties by default. If you need to show complex properties, you can create a custom template to show any set of properties.

Check the last line, it says to show the complex properties we have to create a custom template. But interestingly enough it does not work. Let me show you a very simple example, lets say that we have product and category class like the following:

public class Category
{
    public int Id { get; set; }

    public string Name { get; set; }
}

public class Product
{
    public int Id { get; set; }

    public string Name { get; set; }

    public decimal Price { get; set; }

    [UIHint("CategoryTemplate")]
    public Category Category { get; set; }
}

Check that we are using a custom template (CategoryTemplate) to show the category property.

And in the Controller:

public ActionResult Index()
{
    return View(new Product
                 {
                     Id = 1,
                     Name = "Product 1",
                     Price = 10.0m,
                     Category = new Category { Id = 2, Name = "Category 2" }
                 });
}

And in the View we want to render the product:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<ComplexObject.Models.Product>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Home Page
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <p>
        <%= Html.DisplayForModel() %>
    </p>
    <p>
        To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>.
    </p>
</asp:Content>

But when the view is rendered, there is no category:

CO1

I posted this issue in the Gu’s RC2 announcement post as well as in the CodePlex, but the answer that I got is somewhat confusing. I do not think this is a right decision to hide the complex object in the default implementation, I never hard anybody is having some issues with this features and I do not think it is the right time for this change as the MVC2 is in in RC, anyway feature is broken and needs to be resolved in the first place.

So, till there is a fix, what is the workaround? Lets write some Haacky code. First, lets see where the ASP.NET MVC take the decision to show/hide the model property. If you open the DefaultDisplayTemplates.cs and DefaultEditorTemplates.cs under the Html folder of the ASP.NET MVC Source code, you will find both of it has a method called ShouldShow.

private static bool ShouldShow(ModelMetadata metadata, TemplateInfo templateInfo)
{
    return
        metadata.ShowForEdit
        && metadata.ModelType != typeof (EntityState)
        && !metadata.IsComplexType
        && !templateInfo.Visited(metadata);
}

The only problematic checking is the IsComplexType which in turns check whether the type can be converted from the string type :

public virtual bool IsComplexType
{
    get { return !(TypeDescriptor.GetConverter(ModelType).CanConvertFrom(typeof (string))); }
}

So the workaround is either we override the ModelMetadata which is somewhat an overkill or we can create a TypeConverter for the complex object for which we have custom template to fool the ASP.NET MVC Framework. In this case it is the Category. So lets write a converter.

public class CategoryConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType == typeof(string) ? true : base.CanConvertFrom(context, sourceType);
    }
}

Now, decorate the Category with this converter:

[TypeConverter(typeof(CategoryConverter))]
public class Category
{
    public int Id { get; set; }

    public string Name { get; set; }
}

when you run the project you will find the category is shown like the following:

CO2

And that’s it. You can download the complete code from the following link.

Source Code: ComplexObject.zip

Shout it

I am announcing the beta of System.Web.Mvc.Extensibility.

There has been quite a few changes in this release :

  • Added support for PerWebRequest lifetime.
  • Removed the “base” suffix from the abstract class.
  • I am dropping the Autofac. After struggling quite a few days to add PerWebRequest support, I came to the conclusion that adding such support requires quite a lot of changes which is almost same as rewriting the Autofac itself. Though Autofac uses IScope for Lifetime management but internally it uses the enum instead of that interface. I will look forward to upcoming release of Autofac, if the next release supports custom lifetime management without creating a child container, I will again add it in the supported container list.
  • Both BootstrapperTask and PerRequestTask returns boolean in the Execute method. This comes handy when you want to break the execution of the tasks chain.
  • You can also set Skip=true (static) which would exclude the task from the execution list.
  • etc etc.

You can download the binaries from the following locations:

I will be also releasing few ASP.NET MVC Open source applications in coming weeks which depends on this framework.

So stay tuned!!!


Shout it

I am sorry to inform you that my MVP status has not been renewed for this year. Don’t worry folks it will not make any impact on the open source projects that I am involved over the years as well as our quest to become a better developer, I will be doing all the community works at the same sprit that I used to do before.

Happy new year to everyone!!!

Shout it
More Posts « Previous page - Next page »