I have been working on a simple side project. It is a idea of View Engine that uses Database in order to get Views. It is maybe not so useful scenario, but a good one to learn more about inner workings of Asp.Net MVC and also NoSql databases. There is a  big hype around NoSql. I will use RavenDB because this implementation is very close to .Net community.

First we will explore ViewEngines and HTML response generation,then we will move into the custom View Engine World. If you are interested dear reader then “Stay while and listen …” Open-mouthed smile

ViewEngine

ViewEngine is responsible for HTML generation that is sent back to the client. Programmers with Asp.Net background should be familiar with WebForms Engine that uses <% %> syntax and WebControls . There are other ViewEngines like RazorEngine, which is quite popular right now, but we won’t discuss this here as it is not important for this post.

 

image

Pic 1. Simplified Request/Response cycle

 

Every  ViewEngine implements IViewEngine interface

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

This interface contains method responsible for ViewEngineResult generation,

ViewEngineResult class is a simple data container holding information about ViewEngine we are using and instance of View class.

View class is an implementation IView interface which is very simple and contains only one method.

  public interface IView
  {
    void Render(ViewContext viewContext, TextWriter writer);
  }

This is a very simple interface  that contains Render method which has access to TextWriter that should be used to write data that will be displayed in a response sent back to client. This is almost like Render method inside WebControls.

Ok lets go back to ViewEngine. Unfortunately, or to be honest that is a very good decision, WebFormViewEngine is not directly implementing IViewEngine.

There is another layer in form of VirtualPathProviderViewEngine. This class is implementing IViewEngine and is responsible for adding “physical path” support, if you want to use files stored on your server’s file system you should create custom ViewEngine that extends this class.

Summarising:

image

Pic 2. Simplified WebFormsViewEngine Request/Response

Simple Custom ViewEngine

Ok so we “hopefully” know how the whole ViewEngine stuff works, so lets do our own one. Yey \o/

Our first ViewEngine will be very simple and we will call it HelloWorldViewEngine.

    public class HelloWorldViewEngine : IViewEngine
    {
        public ViewEngineResult FindPartialView(ControllerContext controllerContext,
             string partialViewName, bool useCache)
        {
            return new ViewEngineResult(new HelloWorldView(), this);
        }
        public ViewEngineResult FindView(ControllerContext controllerContext,
              string viewName, string masterName, bool useCache)
        {
            return new ViewEngineResult(new HelloWorldView(), this);
        }
        public void ReleaseView(ControllerContext controllerContext, IView view)
        {
            IDisposable disposable = view as IDisposable;
            if (disposable == null)
                return;
            disposable.Dispose();
        }
    }

ReleaseView method is a copy/paste code from Microsoft Code. As you can see this method should be used to dispose View instance.

FindPartialView and FindView methods are only returning DummyViewEngineResult. Unfortunately we had to create our own implementation of IView interface called HelloWorldView because WebFormView uses physical files and I couldn’t get it  to render something.

    public class HelloWorldView : IView
    {
        public void Render(ViewContext viewContext, TextWriter writer)
        {
            writer.WriteLine("Hello World");
        }
    }

This View is very simple and prints out only “Hello World” message. CoolSmile with tongue out

In order to use this “awesome” ViewEngine we have to register it inside Global.asax file.

protected void Application_Start()
{
      AreaRegistration.RegisterAllAreas();
      ViewEngines.Engines.Clear();
      ViewEngines.Engines.Add(new HelloWorldViewEngine());
      RegisterRoutes(RouteTable.Routes);
}

First we are clearing all the Engines that are currently used and then we are adding our own custom one.

Hopefully on the start you will see beautiful “Hello World” message Smile.

 

DBViewEngine

I  will make Database based on RavenDB just 4fun and in order to use it for the first time.

RavenDB ?

Raven is a .NET Linq enabled Document Database, focused on providing high performance, schema-less, flexible and scalable NoSQL data store for the .NET and Windows platforms.</blockquote> In short NoSql :

Pros
  • Good when your app is used for many Reads
  • Scalability benefits
  • No strict schema 
  • Less problems with data mappings
Cons
  • Bad when your app is used for many Writes

I won’t get into details about RavenDB so lets start implementing our first version of DBViewEngine.

RavenDB DAL

In order to retrieve data we will make a simple DAL.

Page Entity

For this simple scenario we are persisting objects only with ViewName and HTML data.

    public class Page
    {
        public string Html { get; set; }
        public string ViewName { get; set; }
    }

Html is an actual data that will be rendered by browser.

GetPageByViewName
       public Page GetPageByViewName(string viewName)
        {
            using (var session = _store.OpenSession())
            {
                return session.Query<Page>().Where(x => x.ViewName == viewName).FirstOrDefault();
            }
        }

A simple function to get page by viewname this one will be used by the engine to get the data about the page.

 

image

In DB we gonna store two pages About and Home. They will only display simple message like “Welcome to the about page”.

ViewEngine

So now the best part. How to link ViewEngine with DB.

IViewEngine interface has a definition of FindView method. This method has all the data we want right now including ViewName parameter. So let’s implement this method.

        public ViewEngineResult FindView(ControllerContext controllerContext,
                string viewName, string masterName, bool useCache)
        {
            var page = new PageDal().GetPageByViewName(viewName);
            return new ViewEngineResult(new DBView(page), this);
        }

Little test:

Url - /Home/About

And yuppi we have a message indicating that this is a correct site.

Source Code

Conclusion

Asp.Net MVC architecture is quite easy to modyfi and extend. In this post we analysed how we can implement our different ViewEngine which is using RavenDB as a source of the files,