Preprocessed Razor Templates

Preprocessed Razor Templates use the Razor templating language to create C# template classes that can be embedded into any project type, and used to generate HTML without the dependency and overhead of the System.Web.Mvc app. This makes them suited for things like mobile apps that need to generate content for an embedded web view, or tools that generate HTML reports.

Creating a Preprocessed Razor Template

Preprocessed Razor Template templates use the “Custom Tool” feature of MonoDevelop, which is modeled on similar functionality in Visual Studio. The file must be selected in the Solution Pad, then the Property Pad must be used to set the Custom Tool property to “RazorTemplatePreprocessor”. After this property is set, whenever the cshtml file is saved, a cs file with the same name will be regenerated, containing the class generated from the Razor file. This will be compiled into the project, and the generated class will be accessible from code completion.

Fortunately there is a file template that performs this step automatically. Simply create a new file using the Text Templating -> Preprocessed Razor Template template, and a cshtml file will be added with the Custom Tool property already set.

tutorial is available.

The Generated Class

The generated class is public partial, and its name is based on sanitizing the name of the cshtml file. Its namespace is based on the project’s default namespace and the project’s directory-to-namespace mapping policies. It has two methods that are intended to be used by consumers of the template:

public void Generate (TextWriter writer);
public string Generate ();

The first will execute the template and write its output to the provided TextWriter. The second is a convenience overload that executes the template, writes its output to a temporary StringWriter, and returns it as a string.

By default, the class inherits from a generated class that has the name except with “Base” appended. For example, the file Foo.cshtml would by default generate a file Foo.cs, containg the classes Foo and FooBase, with Foo inheriting from FooBase. The FooBase class is designed to be easy to extract into a separate file in order to share a common base class between several template, or customize its default generated members. All its members are commented explaining whether and why they are needed.

Customizing the Generated Class

Since the generated class is a partial class, members can be added by adding other class parts with the same name to the project. The generated class can also be customized through the use of several Razor directives.

Using

The standard Razor @using directive can be used to import a namespace, i.e. add a using statement to the generated file. Any number of instnces of the directive may be used.

Example:

@using Foo

Inherits

The standard Razor @inherits directive can be used to override the base class of the generated class, and cause the default base class not to be generated. This can be used to reduce code duplicated by sharing a single copy of the base class between multiple templates, or can be used to customize the base class. Only one instance of this directive may be provided.

Example:

@inherits MyBaseClass<SomeModel>

Model

The Razor directive @model may be used to specify a type that will be used for a model property, which can be used to pass data in to the template. It will cause a simple pubic get/set property called Model to be added to the generated class.

Example:

@model SomeModelType

Experimental Customizations

The following ways to customize the generated class are experimental, and not guaranteed to be available or behave the same in future versions of MonoDevelop. Use with caution.

Inherits Object

Using the inherits directive to specify the base class to be object, i.e.

@inherits object

will cause the members that would have been generated on the default generated base class to be placed drectly in the generated class.

Class

The \_\_class directive can be used to override the accessibility, name and namespace of the generated class. It may have one or two values. If there are two values, the first must specify the accessibility (public or internal), and the second must specify the name. The name may be fully qualified in order to override the namespace. If there is one value, it may be either the accessibility or the name. Only one instance of this directive may be provided. Some examples:

@__class SomeName
@__class internal SomeNamespace.SomeName
@__class internal

Property

The @\_\_property directive can be used to declare simple public get/set auto properties on the class, without having to use a partial class, a model class or a @functions block. The directive requires two values, the type and the name. Any number of instances of the directive may be used.

Example:

@__property SomeType SomePropertyName

Differences from Razor in ASP.NET MVC Web Apps

Aside from the obvious difference in how the cshtml files are compiled into the project instead of being compiled by a web server, there are a few differences in the generated code.

Model Property

Since there is no default base class, the @model directive doesn’t mimic the System.Web.Mvc.WebViewPage\<TModel\> mechanism of defining the model property on the base type and setting its type as a type parameter to the base class. Instead, the property is added directly on the generated class. To use a custom base class with a generic model property, simply omit the @model directive and instead specify the full closed name of the base class: @inherits SomeClass\<SomeModel\>.

Razor Helpers

The Razor templates preprocessor performs a small transformation to eliminate the System.Web.WebPages.HelperResult dependency from Razor helpers. Instead of returning an isnatnce of this type, they directly return an Action\<TextWriter\>, which the main Razor class uses to write to its output.