How To Create Your Own Asp.Net Mvc View Engine From Scratch

By Mike on 18 April 2013

There are a number of reasons you might want to create your own view engine for Asp.Net Mvc. Mine was that I wanted to have finer control over configuration. You can do a lot with the default view engine but you have to use the golden hammer of inheritance. And for some 'advanced' features like theming you need to modify it (how lucky that asp.net mvc is open source).

Anyway, regardless the reasons why you want to create your own view engine, here's how to build one from scratch. Warning: Code heavy post.

In Asp.Net MVc the view engine has 2 concerns: to locate a view and to instantiate a view. Note that it has nothing to do with the template parsing and rendering so the same view engine can be used to render Razor, Webforms, Spark etc. It's important to understand the difference between the view engine and the template engine.

Here, I want to create a flexible view engine, that is, it can be easily configured via conventions and can support any template engine.

public class FlexibleViewEngine:IViewEngine
{
    public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
    {    
    }
    
     public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
    {
    }
    
    public void ReleaseView(ControllerContext controllerContext, IView view)
    {
    }
}

These are the methods required by IViewEngine. You can see the ViewEngineResult which will be returned in both success and failure scenario. The difference is the when failed, it will contain a collection of searched view path, the ones you see in the yellow screen of death when asp.net mvc can't find a view.

I've said above that this view engine will know how to work with any template engine and this means that it will require view factories injected in it. For easy config, I've decided to have a FlexibleViewEngineSettings object where factories can be added.

public class FlexibleViewEngineSettings
    {
       
        public List<IViewFactory> ViewFactories { get; private set; }

      
        public List<IFindViewConvention> Conventions { get; private set; }
        
    }

 The Conventions list holds the conventions used to locate views.

The view engine accepts an action that can be used to add view factories and view locator conventions.

private FlexibleViewEngineSettings _settings=new FlexibleViewEngineSettings();

    //constructor
    public FlexibleViewEngine(Action<FlexibleViewEngineSettings> config=null)
    {
        if (config != null)
        {
            config(_settings);
        }
        
    }

How does a convention looks like?

public interface IFindViewConvention
    {
        bool Match(ControllerContext context, string viewName);
        string GetViewPath(ControllerContext controllerContext, string viewName);
        string GetMasterPath(ControllerContext controllerContext, string masterName);
    }

Each concrete convention must decide when to apply and how to create a path for a given view or layout. One example can be the case of an Ajax heavy site that still wants to be indexed by search engines. When a search crawler is detected, a special SEO tailored view can be used.

A view factory interface looks like this

public interface IViewFactory
    {
        bool IsSuitableFor(string fileExtension);
        IView Create(ViewCreationData settings);
        IView CreatePartial(ViewCreationData settings);
    }

The concrete factory will be used only for view paths ending with a suitable extension. This means that conventions (the view path generator) and factories work together. Although a partial view is a view, it's necessary to have separate methods because a partial view has special needs, for example, in razor case it should ignore _ViewStartPage .

Ok, so now we have conventions and view factories in our settings. Let's see how they are used by the view engine.

The main idea is that for a given view it processes all the conventions and uses the first which returns a valid view path. It then uses that path to search for a view factory which can handle the file extension. After that it asks the factory to create a IView instance which is returned via the ViewEngineResult object.

 If a returned view path isn't valid, it's added to a list of searched paths. If no conventions returned a valid path or there are no view factories which can handle it, an 'error' ViewEngineResult is returned containing the list of searched paths. That's all, pretty easy.

And once the view engine is built along with some conventions and view factories, just hook it up

ViewEngines.Engines.Clear();
    ViewEngines.Engines.Add(new FlexibleViewEngine(v =>
        {
            v.Conventions.Add(new MyViewConvention());
            //another view factory
            v.ViewFactories.Add(new MyViewTemplateFactory());
        }));

I've included a Razor view factory and the Asp.Net Mvc view conventions (cshtml only and with theme support) by default, so this configuration is for only when you want to use your own conventions or another template engine.

Here's an example of how to write a view factory

public class RazorViewFactory:IViewFactory
    {
        private string[] _extensions = new []{"cshtml","vbhtml"};
        public bool IsSuitableFor(string fileExtension)
        {
            return _extensions.Contains(fileExtension);
        }

        public IView Create(ViewCreationData settings)
        {
            return new RazorView(settings.Context, settings.ViewPath,settings.MasterPath, true,_extensions);
        }

        public IView CreatePartial(ViewCreationData settings)
        {
            return new RazorView(settings.Context, settings.ViewPath, null, false, _extensions);
        }
    }

That's all! You can check the entire FlexbileViewEngine code here

DRY Asp.Net Mvc Controllers

By Mike on 9 January 2013

Since reading Jimmy Boggard's post, I've been trying to DRY things in the Asp.Net Mvc land. Truth is, in every POST action you have to verify if the model is valid. Is not much code but it's repetitive and you do it because you have to. It's not like you can continue the action with an invalid model.

What if the controller would verify automatically that the model is valid and if it isn't , to return directly the view. So the controller action wouldn't be even called for an invalid model.

That is instead of this

public class HomeController:Controller
{

  [HttpPost] 
 public ActionResult CreatePost(Post model)
  {
    if (!ModelState.IsValid)
    { 
        model.Categories=GetAllCategories();  
        return View(model);
    }

    ProcessAndSaveModel(model);
    
    if (someError)
    {
       ModelState.AddModelError("key","something happened");
       model.Categories=GetAllCategories();
       return View(model);
    }
    return RedirectToAction("index");
  }

}

we would have this

[SmartController]
public class HomeController:Controller
{
  
 [HttpPost]
 public ActionResult CreatePost(Post model)
 {
   ProcessAndSaveModel(model);

   if (someError) ModelState.AddModelError("key","something happened");

  return RedirectToAction("index");
 }
 
}

Instead of 9 lines of code, we have now only 3. We've reduced the action size by 2/3! All just by decorating the controller with the SmartControllerAttribute. Pretty good!

In fairness, there is a bit more code involved but not as part of the controller. Some functionality was moved outside the controller but this just makes things more decoupled. The point is that in the first example we have 2 things repeating themselves:

  •  checking if the model is valid and
  •  populating the model before returning the View result.

In the second example, nothing repeats itself. Both examples have identical functionality.

Before diving in, let me tell that the SmartController is available as part of the newly released CavemanTools.Mvc (use Nuget to get it).

Although you've seen the SmartController, the actual feature is in fact implemented by the SmartActionAttribute. As you might have guessed the difference between them is that one works at the controller level (applies to all actions) while the other works at the action level (only the decorated action gets the feature).

How does it work? The Smart functionality is an action filter running before and after the action. It checks the modelstate validity and if it fails it uses a predefined policy, which by default is to return a view with the same name as the action. If before the action, the action won't be invoked at all. If the validation fails after the action, then the result returned by the action is ignored.

So you don't have to do the checks yourself. The action will be invoked ONLY if validation succeeds and the result will be executed ONLY if the second validation succeeds.

What about the case where a model needs to be populated? In many scenarios, the view model needs more than the info received from the request. In this example, our Post model needs the categories set. How does the magic works?

When preparing the model for a failed validation, the SmartAction checks if there is a class which can populate the model. That is, it asks the DI Container if it has an ISetupModel<T>, in this case an ISetupModel<Post>, like this (a trivial example, an actualy setup usually involves more than 1 line)

public class PostModelSetup:ISetupModel<Post>
{
  IRepository _repo;
   public PostModelSetup(IRepository repo) 
  {
    _repo=repo;
  }
 public void Setup(Post post)
 {
     post.Categories=_repo.GetAllCategories();
 }
}

If it exists, the object is used to populate the categories automatically. This is the functionality removed from the initial controller. Now we can use it anywhere we need to setup the Post model. When a GET request comes for the CreatePost we use this object to create the Post model like this

[SmartController]
public class HomeController:Controller
{
  /* .. Constructor with dependencies ... */
  
  
  public ActionResult CreatePost()
 {
  var model= new PostModelSetup(repository).Create();
  model.SelectedCategoryId= 2;
  return View(model);
 }


//This action is unchanged 
 [HttpPost]
 public ActionResult CreatePost(Post model)
 {
   ProcessAndSaveModel(model);

   if (someError) ModelState.AddModelError("key","something happened");

  return RedirectToAction("index");
 }
}

We achieved DRY for the setup of the model also. Without these, you would have to repeat yourself in 3 places: once in the GET CreatePost and twice in the POST CreatePost.

You can read about more Smart features here. Keep your controllers DRY!

Elegant Domain Events Setup In Asp.Net Mvc

By Mike on 13 June 2012

I consider the Domain Events Pattern an elegant way of communicating between layers with minimum of coupling and I even coded a light library for it (Domain Events Toolkit). I'm using both the pattern and the library in Fulldot to handle some operations.


Best example is when a user submit a comment. One the comment is saved you want to notify the admin or the post author , usually via an email. Other example is the Pingback functionality, after writing a post the pingback module searches the content for urls and tries to ping them. These kinds of operations are performed as a result of a domain update.

The steps are usually these:
- Create the event and the event handler types
- register the event handler
- raise event
- event is handled
- cleanup

In a web application, since every request executes independently, the handlers make sense only for dome actions and this means you have something like this (using Domain Events Toolkit)

public class CommentSubmittedEvent:IDomainEvent
{
    /* ... implementation ... */
}

public class SendEmailAfterCommentHandler:DomainEventHandlerBase<CommentSubmittedEvent>
{
  /* constructor with dependencies, implementation */
}


//in the controller
 public ActionResult AddComment(AddCommentModel model)
        {
            var sendEmail= new SendEmailAfterCommentHandler(_repository);
			using (_events.RegisterHandler(sendEmail))
			 {
			      var cmd = Fulldot.FactoryCreate.AddCommentCommand(model, this.GetUserContext(), Request.UserHostAddress);
				  this.Handle(cmd);
			 }
			
        }

A bit of explanation is required for the controller. Aside Domain Events I also use a Command based architecture to update the domain. The first line just creates that command. The second sends the command to a command handler which will actually do the real work.  The command handler is setup in the Container, while the 'Handle' method is provided by CavemanTools Mvc. In a nutshell it will ask the Container for a handler for the command, then it will execute it.

Once the command has been executed, a new domain event is raised , which will be handled by an instance of LocalDomainEventManager (the _events variable) provided by the Domain Events Toolkit. While it's pretty clean, things will go much uglier if you want to setup more handlers for the event. For example, after changing a post, besides the Pingback I want the post processed by Lucene.Net (or another full text search service). We have 2 handlers now and the code will get uglier, all because of the setup of the handlers.

And in fairness, this is an infrastructural concern, the controller shouldn't care about the setup of the domain events manager. Yes we can delegate that to a Service and then simply call the Service method. But we can do it better, using Filter Actions.

Simply put, it looks like this

[HandleDomainEvent(typeof(NotifyCommentHandler))]
        public ActionResult AddComment(AddCommentModel model)
        {
            var cmd = Fulldot.FactoryCreate.AddCommentCommand(model, this.GetUserContext(), Request.UserHostAddress);
            this.Handle(cmd);
            return RedirectToRoute("post",new {slug="comments",id=model.PostId});
        }

Just decorate the action with the types fo the handlers. It makes it so easy to add/ remove handlers without cluttering the real controller code and the intention is much clearer.


And this is the HandleDomainEventAttribute

[AttributeUsage(AttributeTargets.Method)]
    public class HandleDomainEventAttribute:ActionFilterAttribute
    {
        private const string ContextKey = "_dispose_handlers";
        private IEnumerable<Type> _handlers;
        public HandleDomainEventAttribute(params Type[] handlers)
        {
            handlers.MustNotBeNull();
            _handlers = handlers;
        }

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            List<IDisposable> _res= new List<IDisposable>();
            var events = DependencyResolver.Current.GetService<IDomainEventsManager>();
            foreach(var tp in _handlers)
            {
                var h = DependencyResolver.Current.GetService(tp) as IHandleDomainEvent;
                _res.Add(events.RegisterHandler(h));
            }
            HttpContextRegistry.Set(ContextKey,_res);            
        }

        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            var disp = HttpContextRegistry.Get<List<IDisposable>>(ContextKey);
            if (disp==null) return;
            disp.ForEach(d=>d.Dispose());

        }
    }

Half of work is done here, the other half is done by the DI Container. Every event handler is registered in the Container (which will take care of all dependencies required) then the attribute just ask for them, registers them to the domain events manager (also supplied by the Container) and after the action is finished, disposes them.

     So for the modify post case  (after which we want both the pingback and the full text search update), the controller action only gets the attribute.

[HandleDomainEvent(typeof(PingbackHandler), typeof(FTSUpdateHandler))]

One line of code, elegant and efficient.

Understanding the Model in MVC

By Mike on 8 February 2012

When you learn about MVC, you hear that M stands for Model and when you ask "what does the Model mean" you get a response similar to this:
"The model manages the behavior and data of the application domain, responds to requests for information about its state (usually from the view), and responds to instructions to change state (usually from the controller)". Using  a more simple wording, the Model is the data structure and the  database access. This  is even more emphasized by the various OR/M tutorials which shows you how easily you can make a blog engine or something like that (as a funny fact, I'm working on a blogengine/light cms for asp.net mvc and let me tell you that a blogengine with Wordpres like features is far from easy to build, no matter the magic framework or OR/M used)

However, in time you'll learn about Domain Driven Design (DDD) and start talking about a Domain Model as well. Does this means there  are 2 Models now? Oh wait, with an OR/M you only need to define the Model there, 'cuz the OR/M itself takes care of the database handling. But  doing DDD (or having a properly layered application) you see that the Domain Model and the database Model are a bit different in structure and more over, the domain model has behaviors or relationships quite hard to define in an OR/M or any db access class. Things are getting confusing since MVC only as one M and it seems that more than one are needed in practice. It took me quite a lot of time to figure it out that the M is actually a polymorphic beast and you don't even need DDD for that to happen, it's just its nature.

In a standard MVC application , the View itself needs a Model and you guessed it, it's a different model than the Model. It might use parts of the Model but it's different and here is the truth: you are using a different Model in diferent contexts. A view displays specific data and should not know about anything else. That data you pass to the View is the View Model, pretty simple that. The View Model contains only bits required by the View and not the whole object pulled out from the database.

The Domain Model (or the Business Logic layer) represents the real-life (business) problems solved by the application , it's the purpose the application was developed for. It usually contains objects with behavior that work together to provide the actual functionality. That's the core of an application and should  mimic the real situations the best it can.

And then we have the Persistence Model (a.k.a the database schema) which models what data to save and the way the data will be saved. The OR/Ms deal with that model and sadly, that's what a lot of developers think the Model is.

However as you've seen above, there are different models and a developer should understand that there are multiple points of view (no pun intended) in an application. When thinking about the core of the application, we need to forget about the database or how the information will be shown. When thinking about the persistence of data, we care only about what to store, how to store it and how to retrieve it in an optimum way.  When displaying data in a view, only the data relevant to that context should exist in an easy to use form. If you need only id and name, don't get the full User object or the whole row from a table, retrieve just those fields.

But doesn't this mean you have to duplicate code? Well, yes and no. Depending on the application, the Domain Model could be so thin that it simply isn't different enough from the Persistence Model and in that case one Model is enough, even the VIew can use directly the Persistence Model. These are, however, VERY simplistic CRUD applications and I think quite a lot of applications are at least of average complexity and for these, I think a very clearly defined layer (and context) bound Model is better. One of the most important things if not the most important in development is code MAINTAINABILITY and having different Models helps a lot in this matter.

For a quick cheat-sheet here's how you differentiate between the models
- Persistence  Model deals with what to save and how to store data. Here you model data structure.
- Domain Model represents in code the real life, business situations, problems and solutions. It tries to model the natural, humanly way of defining them. Basically you model behaviour here.
- View Models means the specific data for a single view. That data has no real behaviour, it's just a POCO.