Custom Metadata Attributes in ASP.Net MVC

Hello! It’s been a long time since I posted anything and trust me it does not feel good :) So here I am with an interesting post! This post discusses about how I put custom metadata attributes in to use for describing static information for a certain field.

I was in a situation where in I have to talk to a WCF service to update certain information. It goes like this:

  • Get a list of items that represents users belonging to different roles
  • Display a view that lists all the users in a grid and let users update them
  • Once the user is done, he/she clicks a button which finalizes the update by sending in all the users for a certain role in a sequence (synchronous)

For this task, I had booleans in order to represent the access for a certain role for a user. This would translate in to check boxes in the view and I didn’t want to ‘n’ number of partial views and model binders by making a simple boolean in to a complex field. The information related to every role is a constant and so I wanted to leverage that! So, I wanted to use the custom metadata feature, but alas, I needed some information on hard-wiring it to the framework. I went googling and found this StackOverflow answer – http://stackoverflow.com/a/5548384/312219! My idea builds on this!

The following classes are straight from the answer referred about so I am not going to detail them! The first class is the abstract class that represents a custom metadata attribute.

    public abstract class MetadataAttribute : Attribute
    {
        public abstract void Process(ModelMetadata modelMetaData);
    }

Then there is a custom model metadata provider shown below:

    public class CustomModelMetadataProvider : DataAnnotationsModelMetadataProvider
    {
        protected override ModelMetadata CreateMetadata(
            IEnumerable<Attribute> attributes,
            Type containerType,
            Func<object> modelAccessor,
            Type modelType,
            string propertyName)
        {
            var modelMetadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
            attributes.OfType<MetadataAttribute>().ToList().ForEach(x => x.Process(modelMetadata));
            return modelMetadata;
        }
    }

Which is associated to the framework as shown below in Global.asax.cs‘s Application_Start method

        protected void Application_Start()
        {
            // -- snip --

            ModelMetadataProviders.Current = new CustomModelMetadataProvider();
        }

Now that we have the wiring done, let me get to the core of this post!

My objective is to create an attribute that could hold a custom value. So I created the CustomValueAttribute class that inherits the MetadataAttribute class as shown below:

    public class CustomValueAttribute : MetadataAttribute
    {
        private readonly int _customValue;

        public CustomValueAttribute(int customValue)
        {
            _customValue = customValue;
        }

        public int CustomValue
        {
            get { return _customValue; }
        }

        public override void Process(ModelMetadata modelMetaData)
        {
            modelMetaData.AdditionalValues.Add("CustomValue", _customValue);
        }
    }

This class could now be used to decorate any property in a class. In my case I am using this attribute to decorate a couple of booleans.

    public class SampleEntry
    {
        public int Id { get; set; }
        public string Name { get; set; }

        [CustomValue(1)]
        public bool UserEnabled { get; set; }
        [CustomValue(2)]
        public bool NewsletterEnabled { get; set; }
    }

If you notice, UserEnabled and NewsletterEnabled are decorated with this attribute. Now, in my case the view handles the responsibility of displaying the checkboxes in a grid and I use a Session to hold all changes to an individual SampleEntry. Ignoring all those nitty gritty details, let me show how I am putting these CustomValueAttribute‘s to use.

Given below is the view model that includes a list of SamepleEntry items:

    public class SampleViewModel
    {
        public List<SampleEntry> Entries { get; set; }
    }

Here is the most interesting part! Given below is the action method that puts the custom attribute to use!

    public class SampleController : Controller
    {
        public ActionResult Index()
        {
            // Assume the view contains a list of "SampleEntry" items
            // Of which we just need the count of items that has "UserEnabled" to be true
            // And "NewsletterEnabled" to be true

            // Thus "UserEnabled" and "NewsletterEnabled" can be simple "checkboxes" in the view!
            // The reasoning is that in my case, the wcf service just needs the "id"'s of items
            // whose values are set to true

            // This would allow easy extensions and remove the necessity for if...else

            var model = GetModel();

            var requiredCustomValues = GetCustomValues();

            var props = typeof (SampleEntry).GetProperties(BindingFlags.Public | BindingFlags.Instance).ToList();

            foreach (var requiredCustomValue in requiredCustomValues)
            {
                var list = new List<int>();

                props.ForEach(prop =>
                {
                    var attr = prop.GetCustomAttribute<CustomValueAttribute>();
                    if (attr != null && requiredCustomValue == attr.CustomValue)
                    {

                        foreach (var i in model.Entries)
                        {
                            var value = prop.GetValue(i, null);
                            if ((bool)value)
                            {
                                list.Add(i.Id);
                            }
                        }
                    }
                });

                UpdateValues(list, requiredCustomValue);
            }

            return View();
        }

	// -- Snip --
}

Let me get to the fun part directly. The action method already contains some information on why I do this. GetCustomValues is a method that returns a list of values for which the wcf service expects id’s chosen by the user. In this example, it is just a dummy method that returns 2 integers as shown below:

        private List<int> GetCustomValues()
        {
            return new List<int> { 1,2 };
        }

Line 19 uses reflection to get all the properties of the SampleEntry class. Then as I said earlier for every value in GetCustomValues I loop through the properties that has CustomValue set to the required value and collect the id’s in a list. Finally, I call the UpdateValues method which would call the wcf service to report the selected values. For the sake of this post, this method does nothing:

        private void UpdateValues(List<int> list, int requiredCustomValue)
        {
            // This method would call the wcf service to update the values !!!
        }

I will be correcting this post as necessary, but, I guess you found this post interesting! I have to follow this method so as to not change the wcf service. But if I get a chance to update the service, I could find an easier way to do this!

Happy coding!

Share

Performing Activities Before an Application Starts Using the PreApplicationStartMethod Attribute

In this post I am going to discuss a very interesting, yet not so talked about feature of asp.net – pre application start method – PreApplicationStartMethod. I came across this feature while investigating ninject for mvc 3 and I was totally surprised about the existence of the attribute and also that I have never come across this! When you install ninject using nuget, nuget also adds a dependent package called WebActivator. This web activator is responsible for initializing ninject before the Application_Start event. Yes, you heard it right – before the application start event!

When I was looking up more about webactivator, I found this link which does a really good job of discussing about webactivator. But, I felt a few things could have been explained in detail, and so I decided to post this entry!

To begin with, let me discuss a little bit about System.Web.PreApplicationStartMethod. Before I get started here is the PreApplicationStartMethod attribute (without the methods expanded):

[AttributeUsage(AttributeTargets.Assembly, AllowMultiple=false)]
public sealed class PreApplicationStartMethodAttribute : Attribute
{
    // Fields
    private readonly string _methodName;
    private readonly Type _type;

    // Methods
    public PreApplicationStartMethodAttribute(Type type, string methodName);

    // Properties
    public string MethodName { get; }
    public Type Type { get; }
}

Did you notice the AllowMultiple property used by the AttributeUsage attribute decorating the PreApplicationStartMethodAttribute class? This indicates that, in your application, you CANNOT use this class more than once. Also note that this class is marked as sealed, implying this class cannot be extended by using this as a base class. WebActivator uses this class to hook itself to be started before the application starts. The PreApplicationStartMethodAttribute constructor has 2 parameters – First parameter is the Type of the class required to be called before an application starts and the second parameter is a string that represents the static method within the type to be called. WebActivator uses this attribute in its AssemblyInfo.cs file as shown below:

[assembly: PreApplicationStartMethod(typeof(WebActivator.PreApplicationStartCode), "Start")]

Here is the complete listing of the AssemblyInfo.cs file. WebActivator uses this class to register itself in its AssemblyInfo.cs file. Thus when the application starts, before Application_Start is called, asp.net calls the WebActivator.PreApplicationStartCode method. Before I describe this method let me describe the WebActivator.PreApplicationStartMethodAttribute attribute. Here is the complete listing of this class and I have given below the important lines of code relevent to this post.

namespace WebActivator {

    [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
    public sealed class PreApplicationStartMethodAttribute : Attribute {

	    // -- Snip --

        public void InvokeMethod() {
	       // -- Snip --
        }
    }
}

Note the AllowMultiple property again for this class specified by the AttributeUsage attribute, which is set to true, implying this class can be used any number of times in an application. Thus, every assembly can mark a class to be started before the application starts, by using the WebActivator.PreApplicationStartMethodAttribute attribute. Given below is an example of how ninject for mvc 3 uses this attribute. Note that just like the System.Web.PreApplicationStartMethod attribute, this attribute also takes 2 parameters of the same type – thus the web activator would call the static method specified by the second parameter in the type specified by the first parameter.

[assembly: WebActivator.PreApplicationStartMethod(typeof(DependencyInjectionMVC3.App_Start.NinjectWebCommon),"Start")]

// -- Snip --

namespace DependencyInjectionMVC3.App_Start
{
    using System;
    using System.Web;

    using Microsoft.Web.Infrastructure.DynamicModuleHelper;

    using Ninject;
    using Ninject.Web.Common;

    public static class NinjectWebCommon
    {
	    public static void Start()
        {
            DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
            DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
            bootstrapper.Initialize(CreateKernel);
        }

        // -- Snip --
    }
}

Now let me get back to the PreApplicationStartCode.Start method. This method simply gets every assembly in the web applications bin directory, if the assembly uses the WebActivator.PreApplicationStartMethod attribute, gets a reference to it and calls the InvokeMethod method to execute the code that the assembly has designated to be run before the application starts. Its given below:

public class PreApplicationStartCode {
	public static void Start() {
	    // Go through all the bin assemblies
	    foreach (var assemblyFile in Directory.GetFiles(HttpRuntime.BinDirectory, "*.dll")) {
		var assembly = Assembly.LoadFrom(assemblyFile);

		// Go through all the PreApplicationStartMethodAttribute attributes
		// Note that this is *our* attribute, not the System.Web namesake
		foreach (PreApplicationStartMethodAttribute preStartAttrib in assembly.GetCustomAttributes(
		    typeof(PreApplicationStartMethodAttribute),
		    inherit: false)) {

		    // Invoke the method that the attribute points to
		    preStartAttrib.InvokeMethod();
		}
	    }
	}
}

That’s it! I guess I have accomplished conveying what I wanted to convey!!! Hope you enjoyed this post, do post your comments!

Share

Introducing sBlog.Net – An Open Source Blog Engine

Hello people! It’s been a very long time since I posted anything in this blog, but, here I am! This blog post is regarding something I have been working for a while – it’s a blog engine and I have named it sBlog.Net. The dedicated website is for this project is:


Its experimental and I am always open to questions and suggestions Even though, at this point it supports basic features of a blog, a lot more things are in my mind, so, watch out! . I will let you go to this website and read & experiment more about this.

Given below is a link to the demo of sBlog.Net that is hosted under somee.com. The site is hosted for free, and so you will be seeing a number of ads by somee.com. This demo is just to give you an idea of this blogging engine.


But, before you go let me also introduce you to a group I created to discuss things about sBlog.Net. It is:

Post your questions and comments at the google groups site, lets discuss!

Happy coding ;)

Share

C# bits – HandleUnknowAction and JSON Request Behaviors

Hello! Wow, it seems like an eternity since I posted anything! Anyways, I am back! In this post, I am going to discuss a few things that not many encounter often. Nevertheless, the ones discussed here will prove to be very useful. So check it out!

HandleUnknownAction method in mvc 3

The first thing I am going to discuss is about the HandleUnknownAction method available as a virtual method in the Controller base class. As the name implies, this method is available for us to handle unknown actions. This is very similar to method_missing in ruby and I blogged about this earlier here.

To explain this briefly I need to introduce you to the mechanism of how ASP.Net MVC 3 deas with a reqest. When you enter a url, the ASP.Net MVC’s routing module identifies the controller and the action method that would receive the request, creates an instance of that controller and invokes the selected action. If you want more information on this refer to my earlier blog post here. If the specified method is not found, the framework displays the 404 page as shown below:

You could handle this in a number of ways. A few of them are:

  • Have a catch-all route in your Global.asax.cs‘s list of routes
  • Override the HandleUnknownAction method in your controller and take some action

I am just going to discuss the 2nd method as there are a lot of stuff on the internet regarding the 1st method. Before looking into an example, let me introduce you to the signature of this method in the Controller base class.

protected virtual void HandleUnknownAction(string actionName);

If you notice, this method is marked as virtual meaning you can override this method in your controllers. So let me show how I used this method in a project of mine. I normally have a single base controller that other controller’s will inherit. This base controller will have to inherit from the Controller base class. Now, I could add methods that will be shared across various controllers across the project to this base controller. Given below is the code of the BaseController class that implements the HandleUnknownAction method. This could now be shared across any controller that inherits from the BaseController.

public class BaseController : Controller
{
   protected override void HandleUnknownAction(string actionName)
   {
      var strError = string.Format("Unable to find the specified action [{0}]", actionName);

      // Call the logger and log the exception
      Logger.Log(strError);

      // Now throw an exception that could be caught in Application_Error. More on this follows
      throw new ObjectNotFoundException(strError);
   }
}

First, in this method, I log the exception in to a database table to keep track of the happening. Hope you noticed my comment in line 10. You may have custom error attributes in your project (implementing the OnException method of HandleErrorAttribute). But in this case, this wouldn’t be hit and so you may have to use the Application_Error method in the Global.asax.cs file for the web project. [If you have any comments about this particular statement, post in the comments section, because I still have to dig in to the reason of why this happens]. By default, the virtual method in Controller throws an HttpException. So you could also call the base method using the following line after logging the exception.

base.HandleUnknownAction(actionName);

Or, as in the example shown above, I throw an ObjectNotFoundException which I will catch/handle in the Application_Error as shown below:

protected void Application_Error()
{
    var exception = Server.GetLastError();
    if (exception is ObjectNotFoundException)
    {
        Response.Redirect("/Home/Error");
    }
}

As shown above, in the Application_Error method, in line 3 I get the last error and see if it’s an ObjectNotFoundException. If it is, in line 6, I redirect to a custom error page that informs the user more information about the issue in hand. Here is the result after I implement the functionality above:

Now, you will notice that you are no longer redirected to the defaul 404 page as shown above and are redirected to the custom error page.

Let’s now move on to the next discussion:

Using Json based request / responses the correct way

You may have used jQuery’s $.ajax to issue ajax based requests in your website. As far as the data type returned is pure html you won’t have any issues. But if you want to deal with JSON using the GET method, which is a much cleaner way as you just get back the data required from the server rather than an entire chunk of html. There are a few gotchas that you have to remember. By default MVC 3 disallows JSON requests using the GET method due to avoid cross-site scripting attacks. Phil Haack has an excellent post about this here.

But, if the data you are intending to send/receive is not critical, you could still do that by just following a simple procedure. For serious purposes I would always recommend using the POST method for json. Before I get in to the problem with GET JSON requests let me briefly explain the problem. Given below is a page that just has a button. Clicking on the button would call an action method called GetProjectInfo by supplying a projectId. Just for the purposes of this post, the action method simply has a an object with fixed values (except the project id) being passed back as a JSON response for the request.

<h2>Get Json Result</h2>

<script type="text/javascript">
    $(document).ready(function () {
        $('#btnGet').click(function () {
            $.ajax({
                type: 'GET',
                url: "/Page/GetProjectInfo",
                contentType: "application/json; charset=utf-8",
                data: { 'projectId': 1 },
                dataType: 'json',
                success: function (data) {
                    alert(data.ProjectID + ' : ' + data.ProjectName);
                },
                error: function (xhr, ajaxOptions, thrownError) {
                    alert(thrownError);
                }
            });
        });
    });
</script>

<input type="button" id="btnGet" value="Get Project Info"/>

If you notice, in line 8, I send a GET request to the url /Page/GetProjectInfo by passing the projectId as a json object. Also note the dataType property in the request is set to JSON. Now let us look in to the GetProjectInfo action method.

[HttpGet]
public JsonResult GetProjectInfo(int projectId)
{
   var project = new Project
   {
        ProjectID = projectId,
        ProjectName = "Partial Collapsible Panel",
        ProjectCreatedBy = "Karthik",
        ProjType = ProjectType.Plugin
    };
    return Json(project);
}

The above method decorated with the HttpGet attribute simply gets the project id passed, creates an instance of a Project class and returns this as the response as a JSON object. But at this point, if you navigate to this url and click on the button, you will just see a message that says "Internal server error", implying the error callback being invoked. This is because by default GET JSON requests are denied. So you will have to change the request behavior to allow GET JSON requests. This is pretty simple. Just change line 11 to the following:

return Json(project, JsonRequestBehavior.AllowGet);

This instructs the framework that JSON GET requests are allowed and so the json content may be served if a GET request is received. Now when you click on the button you will see the intended display (alert) of the project id and the project name as "1 : Partial Collapsible Panel"! Given below is the complete method again for your reference!

[HttpGet]
public JsonResult GetProjectInfo(int projectId)
{
   var project = new Project
   {
        ProjectID = projectId,
        ProjectName = "Partial Collapsible Panel",
        ProjectCreatedBy = "Karthik",
        ProjType = ProjectType.Plugin
    };
    return Json(project, JsonRequestBehavior.AllowGet);
}

There isn't anything path-breaking in this post, but, still I hope you enjoyed this.

Happy coding!

Share

Generating an “Archives” menu in MVC 3

Hello! I am back! In this post, I am going to discuss a method using which you could generate a menu that lists the archives for your website. You would have seen this in number of website / blogs, even this blog for that matter, check out the section labelled “Archives” to your right. The intention of this post is to generate something similar.

The requirements of this archive list are as follows:

  • It goes in the reverse chronological order, begining with current month / year
  • An entry for a month/year can be present only if there are any items for that particular month/year
  • (At this point) lists all the month/year’s for which there is an item

To implement this I am going to use 2 interfaces (IEnumerator and IEnumerable) provided in the System.Collections assembly. Note that this post does not dwelve in to explaining this as MSDN does a really good job :) Here is the link to the MSDN article!

The IEnumerator interface is implemented so as to support simple iteration using the for loop. To facilitate simplicity (and to reduce the amount of code), I have also implemented the IEnumerable interface as it enables us to use the foreach method of looping, thus making the class that supplies the month/year combinations to be a collection.

To begin with, let use create a plain old simple c# object to represent an archive entry. A sample entry that a user would see is January 2012, and the corresponding Archive entry would have the following properties

Year = 2012, Month = 01 and MonthYear = January 2012.

public class Archive
{
   public string Year { get; set; }
   public string Month { get; set; }
   public string MonthYear { get; set; }
}

Then let’s create the class that would represent an item that a website would present to a user. I am calling it a Post. As stated before, the intention is to present a list of month/year, clicking on which would present a user with a list of post’s added during that date/time. So this class should necessarily contain a date/time apart from other fields. Here it is:

public class Post
{
  public string PostName { get; set; }
  public DateTime AddedDateTime { get; set; }
}

Now let’s get to the most interesting part! Let us create the collection class that will implement the functionality we wish to implement. Here is the code listing, some explanation follows the listing.

    public class ArchiveCollection : IEnumerator, IEnumerable
    {
        private readonly List<Post> _srcList;
        protected List<Archive> Archives = new List<Archive>();
        int _current = -1;

        public ArchiveCollection(List<Post> listToBeGrouped)
        {
            _srcList = listToBeGrouped;
            AddArchives();
        }

        public object Current
        {
            get { return Archives[_current]; }
        }

        public bool MoveNext()
        {
            _current++;
            return _current < Archives.Count;
        }

        public void Reset()
        {
            _current = -1;
        }

        public IEnumerator GetEnumerator()
        {
            return Archives.GetEnumerator();
        }

        protected virtual DateTime GetDateTime()
        {
            return DateTime.Now;
        }

        private void AddArchives()
        {
            var dateTime = GetDateTime();
            var currentYear = dateTime.Year;
            var currentMonth = dateTime.Month;
            var dateTimeFormatInfo = new DateTimeFormatInfo();

            var lastEntry = _srcList.OrderByDescending(p => p.AddedDateTime).LastOrDefault();

            if (lastEntry != null)
            {
                var endYear = lastEntry.AddedDateTime.Year;
                var endMonth = lastEntry.AddedDateTime.Month;

                // Probably could simplify using GroupBy !
                while (currentYear >= endYear)
                {
                    if (currentYear == endYear && currentMonth < endMonth)
                        break;

                    if (_srcList.Any(p => p.AddedDateTime.Year == currentYear && p.AddedDateTime.Month == currentMonth))
                    {
                        Archives.Add(new Archive
                        {
                            Year = currentYear.ToString(),
                            Month = currentMonth.ToString("00"),
                            MonthYear = string.Format("{0} {1}", dateTimeFormatInfo.GetMonthName(currentMonth), currentYear)
                        });
                    }

                    if (currentMonth - 1 < 1)
                    {
                        currentMonth = 12;
                        currentYear--;
                    }
                    else
                    {
                        currentMonth--;
                    }
                }
            }
        }
    }

Line 3 declares a readonly list of Post's that the collection would use to generate a list of month/year's. Remember, this list cannot have an entry where there are no posts, and that's why we expect a list of posts to look through. Then in line 4 a new list is created which will hold the archive entries. In the constructor, check out the AddArchives. This is the method that adds all the possible entries in to the list created in line 4. Lets get to this method directly, as other method's are simple, straight-forward and just implements the methods required by the interfaces.

Now, let's get to the most interesting method in this class which is the AddArchives method. In line 46, I first get the earliest entry in the list passed to this class. For example, current month/year is July 2012. If the earliest entry in the list was on 1st January 2011, that entry would be fetched by this line and the end year is thus assumed to be 2011 (line 50) and end month in line 51 will be 1.

Then in the while loop an archive entry is generated for each month/year starting from the current month/year going back to the last month/year in the list. Lines 55 - 56 is used to break the loop if for the end year, the loop crosses the end month.

Now that we have this collection ready, let me show you an example of how this could be used. To do this, I created a controller called the ArchivesController with the following action methods. There is also a static method that returns a list of Post entries that will be used by the collection. As shown in line 5, to use the collection, just instantiate an instance of ArchiveCollection passing the list of posts using the GetPosts method. The index view uses the collection passed as a model to list all the archive entries.

    public class ArchivesController : Controller
    {
        public ActionResult Index()
        {
            var archiveCollection = new ArchiveCollection(GetPosts());
            return View(archiveCollection);
        }

        private  static List<Post> GetPosts()
        {
            var posts = new List<Post>
                                   {
                                       new Post { PostName = "Post 1", AddedDateTime = DateTime.Parse("1/1/2012") },
                                       new Post { PostName = "Post 1", AddedDateTime = DateTime.Parse("12/1/2011") },
                                       new Post { PostName = "Post 1", AddedDateTime = DateTime.Parse("11/1/2011") },
                                       new Post { PostName = "Post 1", AddedDateTime = DateTime.Parse("10/1/2011") },
                                       new Post { PostName = "Post 1", AddedDateTime = DateTime.Parse("9/1/2011") },
                                       new Post { PostName = "Post 1", AddedDateTime = DateTime.Parse("8/1/2011") }
                                   };
            return posts;
        }
   }

Now, displaying the month/year's is not the only intention. We need to provide a link using which users will be able to drill-down and check out the posts for the selected month/year. To do this, lets add a route to the Global.asax.cs file. Here is that route:

routes.MapRoute("Archive", "archives/{year}/{month}",
                new { controller = "Archives", action = "ListByMonthYear" },
                new { year = @"\d{4}", month = @"[0-9]{1,2}" });

In the above snippet, first parameter is the route name, second parameter is the url format for the links generated is "archives/{year}/{month}", third parameter is the controller and action methods to be used for a request that follows this url format. The last parameter just indicates how the year & month parameters should be using a regular expression. "\d{4}" indicates that year should be a 4 digit number and "[0-9]{1,2}" indicates that month should be a 1/2 digit number. Now lets put this route to use in the Index view.

Here is the view listing for Index:

@model ArchiveCollection

@{
    ViewBag.Title = "title";
}

@foreach (Archive archive in Model)
{

@Html.RouteLink(archive.MonthYear, "Archive", new { year = archive.Year, month = archive.Month })

}

Line 7 loops through the model, using the Html.RouteLink helper method to generate a url using the url format specified in the Global.asax.cs file (line 9). The label used is the values in the MonthYear property.

Finally, lets add the ListByMonthYear action method that will take care of returning the posts for the requested month/year combination. When the user clicks on any of the archive links, this action method gets called, passing it the year and month. I leave the implementation to you, as it's out of scope for this post! The action method is given below:

public class ArchivesController : Controller
{
   // -- cut for brevity --

   public ActionResult ListByMonthYear(string year, string month)
   {
       // implementation omitted
       return View();
   }
}

Now, when you launch the application and navigate to /Archives/Index, you will be able to see a list of archive entries, clicking on which would take you to the action method that in turn returns the entries for the selected month/year! Here is a screen shot from a sample run:

This is from a current project of mine and yes, I did write some unit tests, but I am yet to add them to this sample project.Here is the mock class that can be used. The sample project does not contain any unit tests, but feel free to use the following mock to create unit tests! If you recall from the listing of ArchiveCollection class, the GetDateTime method was marked as virtual. This is to assist us in writing mocks for this class. Note that it's not good to just have a public method and override it using the new keywork in the mock. Soon, I will also update the post with some unit tests in the coming days!

    public class MockArchiveCollection : ArchiveCollection
    {
        public MockArchiveCollection(List<Post> posts)
            : base(posts)
        {

        }

        public Archive Single(Archive archive)
        {
            return Archives.SingleOrDefault(a => a.Month == archive.Month && a.Year == archive.Year && a.MonthYear ==
archive.MonthYear);
        }

        protected override DateTime GetDateTime()
        {
            return DateTime.Parse("4/1/2012");
        }
    }

Here is a sample project for your perusal.

If you think that this could be improvised or you have any other comments, post them here! Happy coding!

Share

Providing the ability to upload (and choose) files in CKEditor

Hello all, feels like it’s been forever since I posted anything! So, here I am with an interesting post. This post is about providing the upload functionality in CKEditor using ASP.Net MVC 3. CKEditor is WYSIWIG html editor. This can be used for various purposes. A really appropriate example is a Content Management System (CMS). In a CMS users typically type in the contents of a page and styles them using various tools available in the editor. This enables users who do not know html to create pages . The free CKEditor javascript expects us to implement this. There are few examples out there, but they are not complete and you may be left to search for more information on how to get it working.

So, you might understand from the introduction that this is not a tutorial about using CKEditor. But still, I would like to give a really quick overview of how I got to add CKEditor. To begin with download the CKEditor source for ASP.Net from here. In the sample project attached, after extracting the zip file downloaded, I have add the contents of the “ckeditor” folder to a folder called “JavaScript” within the “Content” folder. Thus, Content/JavaScript will contain folders like adapters, images, lang, plugins etc. The attached sample project only contains the necessary files and not everything. Feel free to add everything if you like!

To use the CKEditor in its simplest form, all it takes is to add a text area. Given below is an example. To use CKEditor in your web pages the following scripts have to be added.

  • jquery
  • ckeditor.js (from Content/JavaScript folder)
  • adapters/jquery.js (from Content/JavaScript folder)

Then, for this example, the model class is PageViewModel. This class has a PageContent property to hold the contents of the ckeditor. Given below is the complete implementation. Explanation follows after the code.

@model HtmlEditor.Models.PageViewModel

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <title>CKEditor - File Uploads Demo</title>
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Content/Javascript/ckeditor.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Content/Javascript/adapters/jquery.js")" type="text/javascript"></script>
    <script type="text/javascript" language="javascript">
        $(document).ready(function () {
            jQuery('.adminRichText').ckeditor();
        });
    </script>
</head>
<body>
    <div>
        @using (Html.BeginForm())
        {
            @Html.TextAreaFor(m => m.PageContent, new { @class = "adminRichText" })
            <br />
            <input type="submit" value="Submit" />
        }

        <br />
        @Model.PageContent
    </div>
</body>
</html>

Line 1 specifies the model for this page. Lines 12-14 includes the necessary script (listed in the list above). Lines 16-18 is where the ckeditor plugin is applied to any element which has a class of adminRichText. From this point onwards the textareas with this class would show up as a ckeditor. In line
25, a text area is rendered using the standard html extension. Note that the class applied is the same as in line 17, for which we have applied the ckeditor plugin. Given below is a sample run:

Now let us get started with the part where there is less documentation. I am going to extend the simple implementation above to allow users to upload files and also use them to provide links in the content pages they create. To do this I need to introduce the config.js file. This file is used to provide the editor rendered various options like the width, height, ui color etc. Initially the Browse Server button and the Upload tabs are not displayed in the editor.

To enable these controls, the following properties have to be added.

CKEDITOR.editorConfig = function( config )
{
    config.filebrowserBrowseUrl = "/Uploads/Browse";
    config.filebrowserWindowWidth = 500;
    config.filebrowserWindowHeight = 650;
    config.filebrowserUploadUrl = "/Uploads/Upload";
};

Line 2 specifies the url which would display the files available in the server. This page will open in a popup, when the user chooses to select a file from the server.

Line 5 specifies the url which would take care of files uploaded using the ckeditor. We have the urls, so let us create a controller to actually take care of this. Add a controller called UploadsController within the Controller folder. Within this add 2 action methods – 1 to enable users to select a file and 1 to upload a file.

Let us look about the Upload action method to start with. With the config options, CKEDitor provides options to upload files and to select files from the server. This has the following tabs:

  • Link Info
  • Target
  • Upload
  • Advanced

Given below are the images with these tabs. First is the image that shows the option to select a file.

When the Browse Server button is clicked, the popup displays the files currently in the server as shown below:

Next is the image that shows the upload tab:

In order to upload a file, users go in to the 3rd tab, choose a file and hits the Send it to the Server button. When this button is hit, ckeditor calls the url specified in the config by filebrowserUploadUrl. It passes the file content using the key name as upload. It also passes in a CKEditorFuncNum which can be used to identify the instance of the ckeditor that made this upload call. CKEditor parameter holds the name of the textarea that holds this content and finally langCode indicates the language of the content passed. The following action method saves this file in to the server’s uploads folder and returns a view which just has the upload status. This status is shown by ckeditor once the upload is complete.

public ActionResult Upload(HttpPostedFileBase upload, string CKEditorFuncNum, string CKEditor, string langCode)
{
    string fileName = upload.FileName;

    string basePath = Server.MapPath("~/Uploads");
    upload.SaveAs(basePath + "\\" + fileName);

    return View();
}

Next, lets have a look at the action method that lists the files in the server and lets users choose them. This method also gets the CKEditorNum property as explained before. This page just returns a list of files in the server along with the CKEditorNum.

public ActionResult Browse(string CKEditorFuncNum)
{
      List<FileInformation> fileInfoList = GetCurrentFiles();

      var model = new FileListingViewModel
      {
        Files = fileInfoList,
        CKEditorFuncNum = CKEditorFuncNum
      };

      return View(model);
}

This is an important part in this post. Its pretty straight-forward to list the files. But we also have to let the user to select one and return it back to the editor. This is where the CKEditorNum comes in to the picture. Let me explain how. CKEditor provides a function called callFunction which can be used to serve this purpose. Given below is the code content of this page. Notice the hidden field added that provides the CKEditorFuncNum provided by ckeditor for identification.

@model HtmlEditor.Models.FileListingViewModel

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <title>Add</title>
    <script src="../../Scripts/jquery-1.5.1.min.js" type="text/javascript"></script>

    <script type="text/javascript">
        $(function () {
            $('a').click(function (e) {
                e.preventDefault();
                var ckEditorNum = parseInt($('#CKEditorFuncNum').val());
                window.opener.CKEDITOR.tools.callFunction(ckEditorNum, '/uploads/' + $(this).attr('href'), '');
                window.close();
            });
        });
    </script>
</head>
<body>
    <div>
        Select files<br /><br />
        @foreach (var item in Model.Files)
        {
            <a href="@item.FileName" style="font-size: larger;">@item.FileName</a>
            <br />
        }
        <br /><br />
        @Html.HiddenFor(m => m.CKEditorFuncNum)
    </div>
</body>
</html>

In the above snippet, lines 15 – 22 takes care of returning the selected file (jquery). To begin with, I stop the default action of the click of the anchor tag. Then, I get the CKEditorFuncNum added to the page as a hidden field [With multiple editors you may have to take care of this in a different way]. Note that the file browser opens as a popup. So the parent window is the one that has the ckeditor. So by calling the window.opener.CKEDITOR.tools.callFunction function, by passing in the CKEditorFuncNum, the uploads base folder name and the file name, ckeditor gets to know the selected file and popualtes that in the 1st tab (Link Info).

With this, we have achieved what we intended to achieve – to enable users to upload / select files from the server. Download a sample project that does this from here. Note that the project attached uses ckeditor 3.6.2, but the post links to the most latest version of ckeditor 3.6.3.

Share

Dependency Injection With Ninject And Extending It a Bit Further

In this post I am going to discuss a very interesting concept called “dependency injection (DI)” and also about extending the class that injects the dependencies further to achieve some more functionalities that I needed for a project of mine. I am going to use a mvc 3 application to explain about DI. DI is a type of interface programming that allows you to create loosely coupled systems. This increases testability and also reduces the amount of changes required to a project for adding / removing features. At this point it may be confusing, but once I discuss more about this with some examples, it will be much more clearer.

A system implementing DI could be pictured of as having 3 components:

  • Dependent Consumer
  • Dependency
  • Dependency Injector

Dependency consumer‘s are parts of the system that expects a concrete instance to implement something. Consider the following code listing (listing 1):

public class Consumer
{
    private DbAccessor _accessor;

    public Consumer(DbAccessor accessor)
    {
        _accessor = accessor;
    }

    public void DoSomething()
    {
       // -- snip --
    }
}

public class Tester
{
   public static void Main(string[] args)
   {
        DbAccessor accessor = new DbAccessor();
        Consumer consumer = new Consumer(accessor);
        consumer.DoSomething();
   }
}

If you notice the Main method, in order to create an instance of a Consumer, the method has to first create a DbAccessor instance. This is a Dependency. Thus, the method has to know about both the DbAccessor and Consumer. This is known as tight coupling. Because, if you change the name of this class to say DbType1Accessor and assuming this class is used a number of files, you have to change it in all of these files. A way better example is, say you want to replace DbAccessor with XmlAccessor you have to replace the same in all those numerous files. So with all of these facts, I am sure you understand why strong coupling is bad! Later in the post I will show how this strong coupling can be removed.

Now, let’s get to the most important component, the dependency injector. A Dependency Injector is a component that would help you to free the system from this coupling. And this post concentrates on adding a DI component for your project. I have always used “NInject” for implementing DI in my projects.

It’s extremely easy to setup and get started with NInject. To get started download, the NInject dll from here. For this post I was using NInject v2.0.0 (yeto to update to v2.2 :( ). Once you download the dll, add it to the project using “Add Reference”. Then create a class called NinjectControllerFactory and add the following code snippet to this file. This class is going to act as the principal class for implementing DI. If you notice this class inherits the DefaultControllerFactory, which is the default for the mvc framework.

A controller factory is a component of the mvc framework that helps in creating an instance of a controller as required by the mvc framework. In this case we are attempting to provide loose coupling to all the controllers. The controller factory, which is responsible for creating the controllers is overridden in this case so that when a controller is created now, the new controller factory would take the responsibility of creating an instance of the controoler and enabling the Ninject module to “inject” the dependency required by the controller.

public class NinjectControllerFactory : DefaultControllerFactory
{
	private IKernel kernel = new StandardKernel(new AplicationIocServices());

	protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
	{
	    if (controllerType == null)
        {
		    return null;
        }
	    return (IController)kernel.Get(controllerType);
	}

	private class AplicationIocServices : NinjectModule
	{
	    public override void Load()
	    {
		    Bind<IProductsRepository>().To<FakeProductsRepository>();
		    Bind<ICategoryRepository>().To<FakeCategoryRepository>();
	    }
	}
}

In the above code listing, line 3 creates an instance of StandardKernel which is required for the ninject module to work. The StandardKernel implements the IKernel interface which is used in the overriden GetControllerInstance method to return an instance of the required controller by passing the dependency needed by the controller. Note that, as this class is set to replace the DefaultControllerFactory, it’s very important to override the GetControllerInstance method to return an appropriate controller. If you notice line 3, an instance of the ApplicationIocServices instance is passed to the StandardKernel. This is a private class within the NinjectControllerFactory which is used to specify the bindings between an interface and a concrete instance. This class inherits from the NinjectModule class and overrides the Load method of the NinjectModule class.

Every line within the Load binds an interface to a concrete instance so that ninject can create a concrete type corresponding to the interface type passed when creating a controller instance. So when a controller requests a concrete type for IProductsRepository, ninject module returns an instance of FakeProductsRepository which could be used within the controller.

It’s not over if you just create this class. You have to inform the framework to use this instead of the DefaultControllerFactory using the Application_Start event in the Global.asax.cs file. This is done in line 8. ControllerBuilder class of mvc has the
Current property which is nothing but an instance of a ControllerBuilder for the current
application. The application’s controller factory is set to an instance of the NinjectControllerFactory we created earlier using the SetControllerFactory method of the ControllerBuilder instance. After this point, when a request is received for the HomeController (say), an instance of Home Controller will be created by our custom factory, by injecting in the required dependencies.

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);

    ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
}

Following is an example of how this is put to use. Let us assume that the HomeController has an action called Products that displays a list of products that this web site offers for purchase. Without DI, I will have to create an instance of FakeProductsRepository and use it in the controller as shown below:

public class HomeController : Controller
{
	public ActionResult Products()
	{
        FakeProductsRepository repository = new FakeProductsRepository();
	    return View(repository.Products);
	}
}

The above snippet has a strong coupling of the FakeProductsRepository with the HomeController. This is not good because it reduces testability and also makes you modify this code whenever something changes with the FakeProductsRepository class. For example, in case you want the controllers to receive a concrete instance of ProductsRepository instead of an instance of FakeProductsRepository, the only change required is the change in line 9. Thus even if a number of controllers uses the IProductsRepository dependency, nothing would change, as the only change required was in the NinjectControllerFactory class.

public class NinjectControllerFactory : DefaultControllerFactory
{
	// -- snip --

	private class AplicationIocServices : NinjectModule
	{
	    public override void Load()
	    {
		    Bind<IProductsRepository>().To<ProductsRepository>();
		    Bind<ICategoryRepository>().To<FakeCategoryRepository>();
	    }
	}
}

Now that we have set up DI, we can modify the code as shown below. Note that now, the fact that the controller expects a concrete type bound to IProductsRepository could be identified by the parameter to the constructor of the HomeController, which is IProductsRepository. From this point onwards, ninject takes care of creating an instance of the Home controller including passing to it an instance of the FakeProductsRepository because IProductsRepository is bound to FakeProductsRepository.

public class HomeController : Controller
{
	private IProductsRepository productsRepository;

    public HomeController(IProductsRepository productsRepo)
    {
          productsRepository = productsRepo;
    }

	public ActionResult Products()
	{
	    return View(productsRepository.Products);
	}
}

Extending the Ninject Module:

Now, let me get to the most important part of this post. What if I need to create a concrete instance somewhere in a class where Ninject does not come in to the picture? Thats what the remainder of the post is going to deal with. For this part, I again take up one of my favorite area of C# – type constraints :) Let’s add a method called GetConcreteInstance to the NinjectControllerFactory class. This method will be used to get a concrete instance based on the interface type passed. This is a generic method which takes in an interface as a type parameter, finds a concrete instance, casts it to the type T and returns it to the caller.

So, with this method, you don’t have pass every required instance to a controller. This method uses the TryGet method of the StandardKernel to see if a concrete instance exists for the type passed. If not available this method throws an exception.

public class NinjectControllerFactory : DefaultControllerFactory
{
	// -- snip

	public T GetConcreteInstance<T>()
	{
	    object instance = kernel.TryGet<T>();
	    if (instance != null)
        {
		    return (T)instance;
        }
	    throw new InvalidOperationException(string.Format("Unable to create an instance of {0}", typeof(T).FullName));
	}

	// -- snip --
}

Let us look in to an example on how this is put in to use in a controller. Before that let us add a helper class to call this method, so that we abstract the part of getting a reference to the controller factory. Its given below:

public static class InstanceFactory
{
	public static T CreateConcreteInstance<T>()
	{
	    NinjectControllerFactory factory =(NinjectControllerFactory)ControllerBuilder.Current.GetControllerFactory();
	    return (T)factory.GetConcreteInstance<T>();
	}
}

Now, I have added the Categories method to the HomeController. Let’s assume apart from this method, no other method requires the ICategoryRepository. So instead of injecting the dependency to the constructor, within the action method, I use the new helper created earlier to get a concrete instance of ICategoryRepository by passing in ICategoryRepository as the type parameter.

public class HomeController : Controller
{
	private IProductsRepository productsRepository;

	// -- snip --

	public ActionResult Categories()
	{
	    ICategoryRepository categoryRepo = InstanceFactory.CreateConcreteInstance<ICategoryRepository>();
	    return View(categoryRepo.GetCategories());
	}

	// -- snip --
}

In the case of the CategoryController, DI is used as its more likely to be used throughout the controller. So I am just letting ninject take the responsibility for the CategoryController.

public class CategoryController : Controller
{
	private ICategoryRepository categoryRepository;

	public CategoryController(ICategoryRepository categoryRepo)
	{
	    categoryRepository = categoryRepo;
	}

	public ActionResult Index()
	{
	    return View(categoryRepository.GetCategories());
	}
}

Now that I have given you the full picture about DI, let me show how the code in listing 1 can be refactored to free it of the strong coupling.

public class Consumer
{
    private DbAccessor _accessor;

    public Consumer(DbAccessor accessor)
    {
        _accessor = InstanceFactory.CreateConcreteInstance<IDbAccessor>();
    }

    public void DoSomething()
    {
       // -- snip --
    }
}

public class Tester
{
   public static void Main(string[] args)
   {
        Consumer consumer = new Consumer();
        consumer.DoSomething();
   }
}

Given below is another high level implementation of how this new helper class/method could be used.

public class BaseClass
{
	private SomeBusinessFunction func;

	public BaseClass()
	{
	    func = new SomeBusinessFunction();
	}

	public void SomeMethod()
	{
	    func.DealWithSomething();
	}
	}

	public class DerivedClass : BaseClass
	{
	public DerivedClass()
	{

	}
}

public class SomeBusinessFunction
{
	private ICategoryRepository categoryRepo;

	public SomeBusinessFunction()
	{
	    categoryRepo = InstanceFactory.CreateConcreteInstance<ICategoryRepository>();
	}

	public List<Category> DealWithSomething()
	{
	    List<Category> categories = categoryRepo.GetCategories().ToList();

	    // -- do something --

	    return categories;
	}
}

Okay, I know that you have seen a lot code. You can download a sample project here. Hope you enjoyed this post. Happy coding!

Share

ASP.Net MVC Extreme – A Deep Dive Inside View Engines

I am back with another post in the ASP.Net MVC extreme series (as promised)! In this post lets dive into the internals of how a view is selected when an action method returns a View. MVC has the following default view engies – webform and razor and also lets us to add custom view engines. For more inforation on custom view engines, refer to my earlier post here. Custom view engines can be added using the Application_Start event as shown below:

protected void Application_Start()
{
   AreaRegistration.RegisterAllAreas();

   ViewEngines.Engines.Clear();
   ViewEngines.Engines.Add(new CustomRazorViewEngine());

   RegisterGlobalFilters(GlobalFilters.Filters);
   RegisterRoutes(RouteTable.Routes);
}

In the above snippet, ViewEngines is a static class provided by the framework in order to manage the view engies that the framework would look for when searching for views to render. The entire action starts with the ViewResultBase class, which is the base class ViewResult which is responsible for rendering html content to the client. There are a number of other result’s such as FileResult, JsonResult, JavaScriptResult etc and all of these derive from the ActionResult class. ViewResultBase has the ViewEngineCollection property and it’s defined as given below. The engines set up in Application_Start is provided to the ViewResult class using this property. More information on how these engines are used follows soon!

// From mvc sources/reflector
public ViewEngineCollection ViewEngineCollection {
   get {
      return _viewEngineCollection ?? ViewEngines.Engines;
   }
   set {
      _viewEngineCollection = value;
   }
}

A simple action method in mvc would resemble the following:

public ActionResult SomeActionMethod()
{
   return View();
}

The action method above returns the result of the View method from the Controller class. This method returns a ViewResult instance depending upong the parameters passed from the action method. Note that it could also be a PartialViewResult instance. The Controller type has multiple overloads of the View method. Their definitions are given below:

// From mvc sources/reflector
protected internal ViewResult View() {
    return View(null /* viewName */, null /* masterName */, null /* model */);
}

protected internal ViewResult View(object model) {
    return View(null /* viewName */, null /* masterName */, model);
}

protected internal ViewResult View(string viewName) {
    return View(viewName, null /* masterName */, null /* model */);
}

protected internal ViewResult View(string viewName, string masterName) {
    return View(viewName, masterName, null /* model */);
}

protected internal ViewResult View(string viewName, object model) {
    return View(viewName, null /* masterName */, model);
}

All of these overloads eventually call the following method:

// From mvc sources/reflector
protected internal virtual ViewResult View(string viewName, string masterName, object model) {
    if (model != null) {
	ViewData.Model = model;
    }

    return new ViewResult {
	ViewName = viewName,
	MasterName = masterName,
	ViewData = ViewData,
	TempData = TempData
    };
}

Similarly, the following method takes in an IView and has the following definition:

// From mvc sources/reflector
protected internal ViewResult View(IView view) {
   return View(view, null /* model */);
}

This method eventually calls the following method:

// From mvc sources/reflector
protected internal virtual ViewResult View(IView view, object model) {
    if (model != null) {
	ViewData.Model = model;
    }

    return new ViewResult {
	View = view,
	ViewData = ViewData,
	TempData = TempData
    };
}

If you notice the implementations of View, it creates an instance of ViewResult by passing the view name, master name, view data and temp data in the case of the first method and an IView object, view data and temp data in the case of the other method.

Coding best practices(feel free to skip this if you are aware of coding best practices): When you have a method that also has corresponding overloads, make sure that you don’t repeat the same code in both (or all) the places. Consider the following case. This method of handling overloads is bad!.

// bad practice, do not use!!!
public void FooMethod(int memberForYears, string userName)
{
   int totalDaysMemberFor = memberForYears * 365; // ignoring the fact about leap years
   int _membershipPoints = GetMembershipPoints();
   Console.WriteLine("User {0} was a member for {1} days and has {2} points", userName, totalDaysMemberFor, _membershipPoints);
}

public void FooMethod(int memberForYears, string userName, int membershipPoints)
{
   int totalDaysMemberFor = memberForYears * 365; // ignoring the fact about leap years
   int _membershipPoints = membershipPoints;
   Console.WriteLine("User {0} was a member for {1} days and has {2} points", userName, totalDaysMemberFor, _membershipPoints);
}

A nicer way to do this is given below. The refactored code below does not have repetitive code but utilizes the final method to display the results to the user. If you observe the above 2 methods, the only difference is the _membershipPoints bit which gets the value using the GetMembershipPoints method (not shown). So in the snippet below, the 1st overload is called by passing in the value from the method as the 3rd parameter.

// good practice
public void FooMethod(int memberForYears, string userName)
{
   FooMethod(memberForYears, userName, GetMembershipPoints());
}

public void FooMethod(int memberForYears, string userName, int membershipPoints)
{
   int totalDaysMemberFor = memberForYears * 365; // ignoring the fact about leap years
   int _membershipPoints = membershipPoints;
   Console.WriteLine("User {0} was a member for {1} days and has {2} points", userName, totalDaysMemberFor, _membershipPoints);
}

Before we dig in to the ViewResult class lets get a deeper understanding of the how this class is put in to use.

If you can recollect from my previous post, every controller in mvc implements the IController interface and this has the Execute method. When a request arrives, the Execute method is called. Within this method a call to the ExecuteCore method of the Controller is invoked. The ExecuteCode method then handles the responsibility to the ControllerActionInvoker.InvokeActionResult method. Within this method the ExecuteResult method of the ViewResultBase class is called, after executing the content of the action method according to the request. This method itself certainly deserves a post by the way! After this step the real action starts!!! Lets get in to that :)

The ExecuteResult method is given below:

// From mvc sources/reflector
public override void ExecuteResult(ControllerContext context) {
    if (context == null) {
	throw new ArgumentNullException("context");
    }
    if (String.IsNullOrEmpty(ViewName)) {
	ViewName = context.RouteData.GetRequiredString("action");
    }

    ViewEngineResult result = null;

    if (View == null) {
	result = FindView(context);
	View = result.View;
    }

    TextWriter writer = context.HttpContext.Response.Output;
    ViewContext viewContext = new ViewContext(context, View, ViewData, TempData, writer);
    View.Render(viewContext, writer);

    if (result != null) {
	result.ViewEngine.ReleaseView(context, View);
    }
}

Note line 13 in the above snippet. This line calls the FindView overridden in the ViewResult (and PartialViewResult) class(es) to find a matching view. This method, uses the ViewEngineCollection in the ViewResultBase class to get a list of the available view engines. And then ViewEngineCollection type’s FindView method is called to find an appropriate view. This is where the engines added come in to play. The ViewEngineCollection.FindView method is given below:

// From mvc sources/reflector
public virtual ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName) {
    if (controllerContext == null) {
	throw new ArgumentNullException("controllerContext");
    }
    if (string.IsNullOrEmpty(viewName)) {
	throw new ArgumentException(MvcResources.Common_NullOrEmpty, "viewName");
    }

    return Find(e => e.FindView(controllerContext, viewName, masterName, true),
		e => e.FindView(controllerContext, viewName, masterName, false));
}

The Find method called in line 10 uses the engines defined for the application to find an appropriate view. To explore more in to this method, it’s important to see the ViewEngines class.

// From mvc sources/reflector
public static class ViewEngines {
	private readonly static ViewEngineCollection _engines = new ViewEngineCollection {
	    new WebFormViewEngine(),
	    new RazorViewEngine(),
	};

	public static ViewEngineCollection Engines {
	    get {
		return _engines;
	    }
	}
}

ViewResultBase class’s ViewEngineCollection property is set to the ViewEngines.Engines property, which is initialized with an instance of the ViewEngineCollection class created by passing the 2 default view engines available in mvc 3. If you remember (yes it’s been a long post ;) ) we use the ViewEngines.Engines property to add custom view engines. The Find method uses the engines set during instantiation to find an appropriate view. The view engine collection would either have the default engines or the custom engines or both. If this process fails, you see the generic error screen (given below) that lists all the locations searched by the framework.

As you may know, the action starts from the controller. Refer to my earlier post for more details about this. In a future post I will also try to connect the dots between these 2 posts, if I feel anything is missing. Also, I am reviewing this post to catch anything I missed, so it may be updated in the following days!

Finally, do post your comments and happy coding!

Share

ASP.Net MVC – Custom View Engines (Using the razor view engine as the base)

Okay, it’s ASP.Net MVC 3 time again! In this post I am going to discuss about custom view engines. I do not have a lot of real-time experience with custom view engines, but I wanted to try out one of my ideas of organizing the folder in a way that I feel was much more clearer. This is what I am talking about:

Views/
...Home/
......Pages/
.........Page1.cshtml
.........Page2.cshtml
......PartialPages/
........._UserControl1.cshtml
........._UserControl2.cshtml

From the textual folder structure above, I guess my intention is clear. In case you are familiar with the folder structure of MVC, There is a single “Views” folder and within this folder there are individual folders for every controller. Finally, the user controls and pages go in to these folders. If a page/user control is being shared it goes in to the “Shared” folder. In simple words, I just wanted to segregate the cshtml files further by creating a “Pages” and “PartialPages” folder.

As the name suggests, pages would go in to the “Pages” folder and user controls would go in to the “PartialPages” folder. To implement this I have created a custom view engine by inheriting the RazorViewEngine class. As the location of every file would change, we have to specify this by overriding the base string arrays that specify the possible locations of a certain type of a file (master, page, partial page).

Given below is the complete class. “%1″ in every possible path would have to be replaced with either “Pages” or “PartialPages” depending upon the method in question.

public class CustomRazorViewEngine : RazorViewEngine
{
	public CustomRazorViewEngine() : base()
	{
	    AreaViewLocationFormats = new string[] { "~/Areas/{2}/Views/{1}/%1/{0}.cshtml",
						     "~/Areas/{2}/Views/{1}/%1/{0}.vbhtml",
						     "~/Areas/{2}/Views/Shared/%1/{0}.cshtml",
						     "~/Areas/{2}/Views/Shared/%1/{0}.vbhtml" };
	    AreaMasterLocationFormats = new string[] { "~/Areas/{2}/Views/{1}/%1/{0}.cshtml",
						       "~/Areas/{2}/Views/{1}/%1/{0}.vbhtml",
						       "~/Areas/{2}/Views/Shared/%1/{0}.cshtml",
						       "~/Areas/{2}/Views/Shared/%1/{0}.vbhtml" };
	    AreaPartialViewLocationFormats = new string[] { "~/Areas/{2}/Views/{1}/%1/{0}.cshtml",
							    "~/Areas/{2}/Views/{1}/%1/{0}.vbhtml",
							    "~/Areas/{2}/Views/Shared/%1/{0}.cshtml",
							    "~/Areas/{2}/Views/Shared/%1/{0}.vbhtml" };
	    ViewLocationFormats = new string[] { "~/Views/{1}/%1/{0}.cshtml",
						 "~/Views/{1}/%1/{0}.vbhtml",
						 "~/Views/Shared/%1/{0}.cshtml",
						 "~/Views/Shared/%1/{0}.vbhtml" };
	    MasterLocationFormats = new string[] { "~/Views/{1}/%1/{0}.cshtml",
						   "~/Views/{1}/%1/{0}.vbhtml",
						   "~/Views/Shared/%1/{0}.cshtml",
						   "~/Views/Shared/%1/{0}.vbhtml" };
	    PartialViewLocationFormats = new string[] { "~/Views/{1}/%1/{0}.cshtml",
							"~/Views/{1}/%1/{0}.vbhtml",
							"~/Views/Shared/%1/{0}.cshtml",
							"~/Views/Shared/%1/{0}.vbhtml" };
	    FileExtensions = new string[] { "cshtml", "vbhtml" };
	}

	protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
	{
	    return base.CreateView(controllerContext, viewPath.Replace("%1","Pages"), masterPath.Replace("%1","Pages"));
	}

	protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
	{
	    return base.CreatePartialView(controllerContext, partialPath.Replace("%1","PartialPages"));
	}

	protected override bool FileExists(ControllerContext controllerContext, string virtualPath)
	{
	    return (base.FileExists(controllerContext, virtualPath.Replace("%1", "Pages")) ||
		    base.FileExists(controllerContext, virtualPath.Replace("%1", "PartialPages")));
	}
}

To download the file, click here (right click – save as – remove the .txt extension).

As you see above, to implement your custom view engine, you just have to override the following 3 methods:

  • CreateView – This method is called with the corresponding parameters if the view requested is a page
  • CreatePartialView – This method is called with the corresponding parameters if the view requested is a partial page / user control
  • FileExists – This method also has to be overridden in this case because the implementation of this method in the base class won’t know where to look for the file because of the %1 in the path. If this method is not overridden FileExists would always return false which would cause view engine to fail in the process of finding a matching view even if one exists

Now, update _ViewStart.cshtml to specify the location of the master page as shown below:

@{
    Layout = "~/Views/Shared/Pages/_Layout.cshtml";
}

Once we have the class that implements the custom razor engine, and the corresponding change to the _ViewStart.cshtml file, we have to inform the framework to use this instead of the default engine, as the default engine won’t work anymore as the folder structure has changed. To do this modify the Application_Start method in Global.asax.cs to include lines 5 & 6. Line 5 clears all the engines currently added (in this case, just the default engine) and line 6 adds the new custom engine we created.

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    ViewEngines.Engines.Clear();
    ViewEngines.Engines.Add(new CustomRazorViewEngine());

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
}

Also, look forward to another post that dwelves in to internals of view engines in mvc 3!!!

Post your comments and happy coding!

Share

MVC Custom Model Binders and CheckBoxList

Back to ASP.Net MVC! In this post, I am going to discuss about custom model binders and a real-time use of custom model binders in ASP.Net MVC. Before getting in to custom model binders, as the name suggests, there is also a default model binder. If you are interested in custom model binders for mvc, I am sure you are aware about the model binding capabilities of the ASP.Net MVC framework. For starters let me shortly introduce you to default model binding. Assume there is a class as given below:

public class UserInfo
{
    public string UserName { get; set; }
    public string UserEmail { get; set; }
}

With this object, you can do the following to get these 2 information from a user. A default model binder comes in to picture in this case.

  • Have an action method, called, Index
  • The action method returns a view which is strongly typed to the UserInfo class
  • Have an action method called Index decorated with the [HttpPost] attribute and taking UserInfo as a parameter
  • When user enters something and presses the “Submit” button, the action method decorated with [HttpPost] is called
  • The DefaultModelBinder takes the responsibility of mapping the route values and form values to an instance of UserInfo and then passes it to the action method

As you noticed in the listing above, default model binders make it easy in case you have a simple object as above. But, if your model is not a simple object, you may have to use custom model binders. Let us consider building a check box list. In this case, you display an arbitrary list of check box items. So the default model binder would not suffice. So in order to resolve this issue, we need custom model binders. Towards the end of the post, there is a fully working project that utilizes the check box list user control I have created. I hope it acts as a resource to explain the project more comprehensively than I could do here. Without further ado, let me get started on how custom model binders could be used.

The intention is to create a check box list which does not enforce any limits on the number of items. Every check box item could be considered as a collection of the following elements:

  • A check box itself
  • A label containing what the check box represents
  • A hidden field to store the value
  • A hidden field to store the check box state

Note: This implementation is quite different from other ways of implementing a check box list. Towards the end of this post, there are a few helpful links. Have a look at them too!

In order to create these elements, I am using a few custom html helper extensions. This is contained within a class called CustomHtmlHelpers. I am not going to list out the content of this file, but, just give a short description of what every method does.

  • CheckBoxInput – This method creates a chechbox (without a label), a hidden field to track the status of the checkbox. This is required because, if the checkbox is unchecked, there won’t be a value posted to the server when the submit button is clicked. In general, check box lists available on the internet will help you get the values checked by the user, but you will have to regenerate the mode using a database query (or something else). But in this case I reconstruct the entire list using the form values posted.
  • CheckBoxInputLabel – This method creates a label for every checkbox. Clicking on this label would also
  • CheckBoxValue – This generates a hidden field that holds the values for the checkbox
  • CheckBoxListHeader – This generates a header for every individual check box list. This contains a label and a hidden field to store the header

With these extensions, the following user control denotes a sigle check box list:

@model SampleAppForCheckBoxList.Models.CheckBoxListViewModel
@using SampleAppForCheckBoxList.Infrastructure

<div class="cpHeader">
    @Html.CheckBoxListHeader(Model.HeaderText)
</div>
<div class="cpContent">
    @foreach (var item in Model.Items)
    {
        @Html.CheckBoxValue(Model.HeaderText, item, Model.Items.IndexOf(item))
        @Html.CheckBoxInput(Model.HeaderText, item, Model.Items.IndexOf(item))
        @Html.CheckBoxInputLabel(Model.HeaderText, item, Model.Items.IndexOf(item))
        <br />
    }
</div>

If you notice in the above snippet, section under “cpHeader” denotes the header area and “cpContent” denotes the content area – where all the check boxes are listed. Line 2 imports the custom html helper described in the earlier step.

Note: This could also be added to the web.config.

Now, let us create a custom model binder. A custom model binder in ASP.Net MVC should implement the IModelBinder interface. This interface has a single method called BindModel which returns an object. Given below is the implementation of this custom model binder.

public class CheckBoxListViewModelBinder : IModelBinder
{
	public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
	{
	    List<CheckBoxListViewModel> models = new List<CheckBoxListViewModel>();

	    string[] formKeys = controllerContext.HttpContext.Request.Form.AllKeys.ToArray();

	    List<string> rootItems = formKeys.Where(s => s.StartsWith("hdrTitle")).ToList();

	    foreach (var item in rootItems)
	    {
		string hdrValue = item.Split('_')[1];
		string[] txtValues = formKeys.Where(s => s.StartsWith("lblLabel_" + hdrValue)).ToArray();
		string[] valValues = formKeys.Where(s => s.StartsWith("valValue_" + hdrValue)).ToArray();
		string[] hdnValues = formKeys.Where(s => s.StartsWith("hdnChk_" + hdrValue)).ToArray();

		CheckBoxListViewModel model = new CheckBoxListViewModel();
		model.HeaderText = Regex.Replace(hdrValue, "([a-z])([A-Z])", "$1 $2");
		model.Items = new List<CheckBoxListItem>();
		for (int index = 0; index < txtValues.Count(); index++)
		{
		    CheckBoxListItem _item = new CheckBoxListItem();
		    _item.Text = bindingContext.GetValue(txtValues[index]);
		    _item.Value = bindingContext.GetValue(valValues[index]);
		    _item.IsChecked = bool.Parse(bindingContext.GetValue(hdnValues[index]));

		    model.Items.Add(_item);
		}

		models.Add(model);
	    }

	    if (rootItems.Count == 1)
		return models.First();
	    else
		return models;
	}
}

As you can see from the code listing above, the method receives 2 parameters: a ControllerContext instance and a ModelBindingContext instance. The bindingContext can be used to get the value posted for a certain input element, but, it does not provide a method by which we can get a list of all the fields posted. So I use the Form property from the controllerContext.HttpContext.Request.Form instance. Then as you noticed from the html helper, every element uses a certain id/name format. Using this the values are gathered for every element including the header text. Following is a high level algorithm:

  • Find out the number of header elements – this denotes the number of check box lists used. The id/name format is
    hdrTitle_{header_Text}
  • Then using this every other element can be identified as given below

    • Text of the check box is identified using id/name format of lblLabel_{header_Text}_{index}
    • Value of the check box is identified using id/name format of valValue_{header_Text}_{index}
    • Check box checked status of the check box is identified using id/name format of hdnChk_{header_Text}_{index}
  • A CheckBoxListViewModel object is contructed for every check box list and returned.

Now that we have a custom binder, let us see how to put this in to use. You will have to instruct the framework to invoke this binder in case an action method has a parameter of this type. So adding the following 2 lines to Global.asax.cs Application_Start method would take care of this.

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    ModelBinders.Binders.Add(typeof(CheckBoxListViewModel), new CheckBoxListViewModelBinder());
    ModelBinders.Binders.Add(typeof(List<CheckBoxListViewModel>), new CheckBoxListViewModelBinder());

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
}

Lines 5 & 6 are of prime importance. These lines indicate that if a parameter of type CheckBoxListViewModel or List<CheckBoxListViewModel> is expected, initialize an instance of CheckBoxListViewModelBinder and pass the controller context and the binding context.

Another important thing to notice is the jquery required to store the status of the check box in the hidden field created for this purpose. Following is the jquery required to do this.

$(document).ready(function () {
    $('.chkClickable').click(function () {
        if ($(this).is(':checked')) {
            $(this).next('.hdnStatus').val('true');
        }
        else {
            $(this).next('.hdnStatus').val('false');
        }
    });
});

Finally, let us put this in to use. If you look in to the DemoController this user control is put in to use as given below:

public ActionResult Index()
{
    return View(GetModel());
}

[HttpPost]
public ActionResult Index(CheckBoxListViewModel model)
{
    ViewData["Choices"] = string.Join(",", model.GetSelectedItems());
    return View(model);
}

private CheckBoxListViewModel GetModel()
{
    var model = new CheckBoxListViewModel();
    model.HeaderText = "Select Languages";
    model.Items = new List<CheckBoxListItem>{ new CheckBoxListItem { Text = "C#", Value = "CSharp", IsChecked = false },
					      new CheckBoxListItem { Text = "Ruby", Value = "Ruby", IsChecked = false },
					      new CheckBoxListItem { Text = "PHP", Value = "PHP", IsChecked = false },
					      new CheckBoxListItem { Text = "Java", Value = "Java", IsChecked = false },
					      new CheckBoxListItem { Text = "Scala", Value = "Scala", IsChecked = false }
    };

    return model;
}

GetModel is simply a method that returns a view model for the check box list. This contains a header text and the items to be displayed in the list. Note that this could very well be a call to the database. The Index action method passes this to the view and the view would in turn pass it on to the user control which would display it.

The action method Index decorated with the [HttpPost] attribute would be invoked when the user submits the form. The method has a CheckBoxListViewModel parameter. So during the post action mvc would invoke the custom binder and repopulate with the user’s choices. The model has the GetSelectedItems method which could be used to identify the items selected by the user.

The project also has another example which has 2 check box lists. This is where the following line from the Global.asax.cs class comes in to use:

ModelBinders.Binders.Add(typeof(List<CheckBoxListViewModel>), new CheckBoxListViewModelBinder());

Note that this method would post a lot more fields (data) in the request than the other method which only posts the selected values.

A demo always helps isn’t it? Here it is!!!

Download the sample app with the user control and associated code files here

Link to github for this project is here – You will be able to get the most latest from here always, because I will check in here in case I make any changes.

Some nice links:

  • Another implementation of check box list is here. I do have similar implementation that returns only the selected values. My implementation uses mvc templates instead of html extensions. When I get a chance I will post my implementation too.
  • A link about a fix for mvc check boxes is here.

Happy coding! Post your comments!!!

Share