andrewlocatelliwoodcock

Thoughts on Software

Archive for the ‘Razor’ Category

LoggingViewEngine: a concrete example of using the Shaver framework

with 6 comments

As I explained in Shaver View Engine: a more in-depth look, Shaver is a framework for an extensible view engine that allows views to be written in Razor syntax, captures the HTML/CSS output using the Razor view engine and then makes that output available for use via extension points so that the original Razor view can be repurposed to produce any output you want or perform additional tasks prior to returning to the browser, or both.

If the output you want can be produced from HTML, or make use of HTML, Shaver facilitates this but does nothing with the output itself: that task is left up to concrete implementations of the View Engine. Shaver is an abstract View Engine and we need concrete implementations in order to do anything useful.

This post is going to concentrate on a simple concrete implementation of the Shaver View Engine, LoggingViewEngine. The LoggingViewEngine returns the view as normal but first logs the rendered HTML via Log4Net. And all that is required to achieve this functionality is to change the View’s extension to cslog …

Read the rest of this entry »

Written by andrewlocatelliwoodcock

November 17, 2011 at 21:05

Shaver Framework API: ShaverView

with 5 comments

Following on from our in-depth introduction to Shaver and the first part of Shaver’s API, the second part of the API is the ShaverView: https://github.com/alfamale/Shaver/blob/master/ShaverViewEngine/ShaverView.cs.

ShaverView is an abstract class that implements the IView interface and provides a set of extension points. Just like ShaverViewEngine, ShaverView cannot be used directly but is intended to provide a framework and API. Have a look at Logging View EngineMailer View Engine and PDF View Engine to see examples of how this is done.

The API is made up of three abstract methods that must be overridden by each implementation (Setup, ActOnHtml and RenderView), a virtual method that may be overridden by an implementation if required (CaptureHtml) and two static helper methods (GetViewData and GetTempData), that extract view and temp data from the controller context.

ShaverView’s constructor accepts two parameters the ControllerContext and an instance of IView. Not co-incidentally, these objects are supplied to ShaverViewEngine’s CreateReturnView method and it is intended that View inheriting from ShaverView will be instantiated in the ViewEngine’s CreateReturnView method. Once again, have a look at Logging View EngineMailer View Engine and PDF View Engine to see examples of how this is done.

The constructor calls the API methods in the following order:

  1. Setup – performs any setup tasks required
  2. CaptureHtml – captures and returns the HTML rendered by the Razor View Engine
  3. ActOnHtml – acts on the HTML returned from the CaptureHtml method
Setup and ActOnHtml, as previously described, are abstract methods and must be implemented by each concrete View Engine using the Shaver framework. CaptureHtml is a virtual method: it provides a default implementation that captures the HTML output generated by the Razor View Engine but can be overridden if necessary. ActOnHtml accepts the HTML returned from the CaptureHtml method as well as the ControllerContext and the IView object and performs whatever custom tasks are required by this particular implementation of the Shaver framework.
The Render method is required by the IView interface and simply calls the RenderView abstract method. RenderView must be implemented by any concrete implementation of the Shaver framework and is intended to perform the rendering tasks required by the particular View Engine.

Written by andrewlocatelliwoodcock

November 8, 2011 at 22:31

Shaver Framework API: ShaverViewEngine

with 4 comments

Following on from the last post, let’s start our discussion of the Shaver API with the Shaver View Engine itself:https://github.com/alfamale/Shaver/blob/master/ShaverViewEngine/ShaverViewEngine.cs.

There are a couple of things to note: firstly, ShaverViewEngine inherits from RazorViewEngine so that we can re-use and co-opt all the power of the Razor View Engine without re-inventing the wheel: Shaver is about doing unexpected, unenvisioned things with existing Razor syntax not developing a new syntax!

Secondly, there are only two methods: CreateView and CreateReturnView. CreateView overrides Razor’s implementation of the standard CreateView method and uses it to create an IView object which is then passed, along with the ControllerContext to the virtual method CreateReturnView. Custom View Engines that implement the Shaver framework can perform any custom tasks required within their own implementation of CreateReturnView: it is the output of CreateReturnView that is returned to MVC, not the output of CreateView as might be expected. We are letting Razor do the hard work here – it already does it really well, we just want to make it easy to do something different with the output!

CreateReturnView is the first extension point in our Shaver API.

Note also that Shaver itself provides no code to register custom view extensions: Shaver is an abstract View Engine and as such does not provide complete functionality only an API. As such, it makes no sense to attempt to register custom view extensions within the Shaver View Engine itself, this is a task for each concrete implementation such as LoggingViewEngine.

Shaver cannot in fact be used directly: note that it is an abstract class: we need a concrete implementation of the Shaver framework to instantiate – Shaver cannot and does not do the job on its own. Have a look at Logging View EngineMailer View Engine and PDF View Engine to see examples of how this is done.

Next: the Shaver API: ShaverView

Written by andrewlocatelliwoodcock

November 7, 2011 at 20:54

Shaver Framework: a more in-depth look at the View Engine

with 9 comments

In my last post, I introduced the open source Shaver View Engine. In this post, I will expand on what Shaver is, what it does (and doesn’t do) and how it does it.

Read the rest of this entry »

Written by andrewlocatelliwoodcock

November 7, 2011 at 13:53

Introducing the Shaver Framework: an Open Source Project for ASP.Net MVC

with 4 comments

After my presentation at the MTUG Dev Day earlier this month, I have been asked a number of times for the source code of the sample custom view engines I used in my talk. The delay in posting the source code has been due to the fact that when I started looking at it, I realized that what I had done, with a bit of refactoring and re-engineering, could be made into quite a useful open source project. Hence the delay!

But finally, I am ready to announce the existence of Shaver, an ASP.Net MVC Open Source Project that allows the extension of the Razor View Engine to allow views to be written in standard Razor syntax but used to produce any type of output you want. Most custom view engines for ASP.Net MVC offer different syntax for writing your views in; Shaver reuses standard Razor syntax but allows you to perform any task you want with the output. Examples included in the project include a logging view engine, a view engine that converts HTML / CSS to PDF and displays the generated PDF instead and a mailer view engine that can produce a mail merge from a standard Razor view.

The possibilities are potentially endless …

In the hope that this will prove useful, I have now released this project under the GNU LGPL on GitHub: Shaver. Please have a look, play around with it, offer any constructive criticism and suggestions and let me know what you think!

Next: in-depth introduction to Shaver

Written by andrewlocatelliwoodcock

October 27, 2011 at 19:40

Custom View Engines: Registering custom extensions with your View Engine

leave a comment »

In my last post, I discussed how to tell ASP.Net MVC about the custom extensions for your fancy new custom views but how do you actually tell your new view engine that it should read them?

The first step of course is to create a custom view engine which is actually pretty simple: inherit from ViewEngine or another, existing view engine. In the examples I worked through in my MTUG presentation, I showed two custom view engines which both inherited from RazorViewEngine so that we could use standard Razor syntax, reuse the power of the Razor parser and yet use the output in novel ways: one custom view engine logged the HTML of every view it rendered, whilst the other actually rendered the view as a PDF file and returned a FileStreamResult rather than a standard Razor View.

In the example below our custom view engine, SampleViewEngine, inherits from ViewEngine. In the constructor, SampleViewEngine calls the ViewLocationFormats and PartialViewLocationFormats methods of the ViewEngine class and registers its interest in views ending in the extension .custom in the locations /Views/{Controller}/ and /Views/Shared{Controller}/.

 

public class SampleViewEngine: ViewEngine

{

public SampleViewEngine()

{

// This is where we tell MVC where to look for our files. This says

// to look for a file at “Views/{Controller}/{Action}.custom”

        base.ViewLocationFormats = new string[] { “~/Views/{1}/{0}.custom”, “~/Views/Shared/{0}.custom” };

        base.PartialViewLocationFormats = base.ViewLocationFormats;

}

/// <summary>

/// Overrides the ViewEngine’s CreateView method. Instantiates and returns a new SampleView

/// </summary>

/// <param name=”controllerContext”>ControllerContext of the calling Controller – contains ViewData, etc.</param>

/// <param name=”viewPath”>Path to the view</param>

/// <param name=”masterPath”>Path to the master file</param>

/// <returns>IView object that inherits from View</returns>

protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)

{

return new SampleView(controllerContext, viewPath, masterPath);

}

}

 

Note that the ViewLocationFormats and PartialViewLocationFormats methods accept not only the extension but also the location and name pattern of the view. They also accept an array of strings, which means that you can add as many locations, extensions and rules as you want. Just so we’re clear: your rules can reuse an existing extension but in a non-standard location as in the example below:

 

// reuse the .cshtml Razor extension but only recognize views that are in ~/Views/Reports/{Controller}/{Action} or ~/Views/Shared/Reports/{Controller}/{Action}

base.ViewLocationFormats = new string[] { “~/Views/Reports/{1}/{0}.cshtml”, “~/Views/Shared/Reports/{0}.cshtml” };

 

 

Written by andrewlocatelliwoodcock

October 20, 2011 at 20:55

Custom View Engines: Registering a custom extension and avoiding the “There is no build provider registered for the extension” error

with one comment

Once you’ve implemented a custom View Engine in ASP.Net MVC , and there will be subsequent posts covering how to do just this, there are another couple of steps to perform before your wonderful new view engine is wired up and rendering views.

One of the first things you may encounter is the dreaded “There is no build provider registered for the extension ‘.xxxx'” error. This is actually quite straightforward to fix and is one case where everything you need to know is actually included in the error message! Basically, ASP.Net MVC expects a <buildProviders> section that matches your new extension in the local web.config, machine-level web.config or machine.config and hasn’t found one. The example below shows how to fix this: add the relevant sections! In this case, we are registering two extensions and stating that the extensions should be interpreted with the Razor View Engine. These examples are actually the LoggingViewEngine and PdfViewEngine mentioned in my last post, both of which extend the RazorViewEngine to leverage its syntax and parsing and extend it by using the output in novel ways:

<system.web>

<compilation debug=”true” targetFramework=”4.0″>

<assemblies>

.

.

.

.

</assemblies>

<buildProviders>

<add extension=”.cslog” type=”System.Web.WebPages.Razor.RazorBuildProvider, System.Web.WebPages.Razor”/>

<add extension=”.cspdf” type=”System.Web.WebPages.Razor.RazorBuildProvider, System.Web.WebPages.Razor”/>

</buildProviders>

</compilation>

</system.web>

 

The second step is to tell ASP.Net MVC how to interpret these extensions and register the View Engines that will deal with them. And again, it’s simple once you know that it needs to be done 🙂

In the Global.asax.cs, add the highlighted lines below to the Application_Start method:

protected void Application_Start()

{

AreaRegistration.RegisterAllAreas();

 

            // add the new extensions to the collection of languages supported by Razor

            RazorCodeLanguage.Languages.Add(“cslog”, new CSharpRazorCodeLanguage());

            RazorCodeLanguage.Languages.Add(“cspdf”, new CSharpRazorCodeLanguage());

 

            // register the extensions

            WebPageHttpHandler.RegisterExtension(“cslog”);

            WebPageHttpHandler.RegisterExtension(“cspdf”);

 

RegisterGlobalFilters(GlobalFilters.Filters);

RegisterRoutes(RouteTable.Routes);

RegisterViewEngines(ViewEngines.Engines);

}

 

and add the following method:

public static void RegisterViewEngines(ViewEngineCollection viewEngines)

{

viewEngines.Clear();

viewEngines.Add(new RazorViewEngine());

viewEngines.Add(new LoggingViewEngine.LoggingViewEngine());

viewEngines.Add(new PdfViewEngine.PdfViewEngine());

}

 

And there you have it: we have registered two new extensions, told ASP.Net MVC to react to them and added the View Engines that know how to support them to the View Engines collection.

Simples!

 

Written by andrewlocatelliwoodcock

October 18, 2011 at 22:43

Dev Day II – October 10th, 2011 – Update

with 5 comments

{EAV_BLOG_VER:8551b89f31ea387b}I enjoyed Dev Day II yesterday – it was a well-attended event and the presentations were interesting. I especially enjoyed Kieran Logan’s presentation on RoleConnect.com‘s use of NoSQL, Azure and Lucene.Net.

I forgot to say it at the time, but I am putting my own presentation up here for anyone who’s interested: ASP.Net MVC.

When I get a bit more time will add posts on the custom view engines I developed for the talk – LoggingViewEngine and PdfViewEngine: respectively, a custom View Engine to Log View HTML automatically and a custom View Engine to render a standard Razor view as a PDF instead.

And I will get round to finishing my series on C# encryption and decryption soon as well …

Written by andrewlocatelliwoodcock

October 11, 2011 at 19:35

Posted in ASP.Net MVC, C#, Razor, View Engines

Tagged with ,

Escaping the @ character in ASP.Net MVC Razor Views

with 6 comments

The Razor view engine uses the ‘@’ character to identify code directives within the view. So, what do you do if you need to use an @ character within a Razor code statement block? You simply escape it with @@: @@ is the escape character for @ in Razor views.

Razor, like most things MVC, is actually pretty smart however and tries to work out from context when an ‘@’ is just an ‘@’ and where it marks C# (or VB.Net) code.

One of the main uses for this is to identify email addresses within a Razor view – it should not be necessary to escape the @ character in an email address.

Written by andrewlocatelliwoodcock

May 10, 2011 at 20:14

Posted in ASP.Net MVC, Razor

Tagged with , , , ,

Displaying a Base64-encoded string as an image in a view

with 2 comments

Following on from my previous posts covering the server-side code to display a base64-encoded string as an image in MVC, I thought it would be useful to show how to write a View to actually display the re-hydrated image. What hoops will we have to jump through, what arcane secrets must be learnt?

Read the rest of this entry »

Written by andrewlocatelliwoodcock

April 30, 2011 at 11:20