Home .NET Using Razor separately from ASP.NET MVC

Using Razor separately from ASP.NET MVC

by admin

In my work as a student I often have to write various laboratory and term papers. An integral part of these works (as well as in 80% of business programming tasks) is the code for reporting on the found items in a database or a long and complex operation. In desktop programming within the .NET Framework there are various ways to solve such problems :

  • Old school : format RTF no one abolished, but manually compose anything more complex than a colored text with fonts of different colors and links, I personally did not work. The method is effective, but the standard is not the easiest to understand, at latest version it’s scary to even look at
  • For Silverlight/WPF – formation FlowDocument with your own hands. The object model is definitely more convenient than forming the old format manually, but the option is also only for the brave
  • Third-party solutions like Crystal Reports may be a very powerful tool for creating reports, but it is not always necessary, in addition, it is not always possible to pull a couple or three additional software products 1
  • Using Microsoft Office Interop No, this is a mockery. Manual memory manipulation in a managed environment causes only a storm of joy. The novice programmer will drink more than one packet of coffee before coming to terms with this way of working.
  • Formation HTML To our joy, the standard allows you to create medium-formatted documents with CSS. Disadvantages – it is extremely difficult to make a document according to all requirements. But this is if there is a need. Pros: the simplicity of the standard and the general transition "in the clouds and browsers" stimulates the development of HTML.

The latter is what I’m going to talk about.
The easiest and most obvious option is to generate the HTML string manually. Those who are new to the platform will immediately start concatenating String objects, those who read the documentation will pay attention to the StringBuilder In any case, String.Format is not always the most convenient way to generate reports. But fellow platformers who use ASP.NET MVC can’t get enough of Razor performance engine And then the question arises: why not use the power of ASP.NET Razor to your advantage?
First of all, you need to connect the assembly System.Web.Razor It’s from the ASP.NET MVC delivery, so if the target computer doesn’t have it installed, you should take care to copy the necessary dlls locally.
Declare a base class from which we will inherit our view

public abstract class TemplateBase{public StringBuilder Buffer { get; set; }public StringWriter Writer { get; set; }public TemplateBase(){Buffer = new StringBuilder();Writer = new StringWriter(Buffer);}public abstract void Execute();// Writes into the string an expression like : "@foo.Bar".public virtual void Write(object value){// Don't need to do anything special// Razor for ASP.Net does HTML encoding here.WriteLiteral(value);}// Writes markup literals : "<p> Foo</p> "public virtual void WriteLiteral(object value){Buffer.Append(value);}// ... And here we can specify any other public properties, which will be passed to the Razor engine whether it wants them or not}

First of all, you need to initialize the engine.

private RazorTemplateEngine SetupRazorEngine(){// 1. specify that we want to use a C# description of the representationRazorEngineHost host = new RazorEngineHost(new CSharpRazorCodeLanguage());// 2. We specify a base class from which the representation is inherited. The one described above.host.DefaultBaseClass = typeof(TemplateBase).FullName;// 3. Specify the namespace and name of the view classhost.DefaultNamespace = "RazorOutput";host.DefaultClassName = "Template";// 4. Specifying the default namespaces (using)host.NamespaceImports.Add("System");// 5. Creating a new template enginereturn new RazorTemplateEngine(host);}

As you know, .NET supports on-the-fly code compilation. This is the feature that Razor uses. Hence, in our case we need to read the template file and save it to a separate assembly.

// Generating the template codeGeneratorResults razorResult = null;using (TextReader rdr = new StringReader( MyTemplatesString ))razorResult = _engine.GenerateCode(rdr);CSharpCodeProvider codeProvider = new CSharpCodeProvider();// Writing the compiled code to the assembly filestring outputAssemblyName = String.Format("Temp_{0}.dll", Guid.NewGuid().ToString("N"));CompilerResults results = codeProvider.CompileAssemblyFromDom(new CompilerParameters(new string[] {typeof(Form1).Assembly.CodeBase.Replace("file:///", "").Replace("/", "")}, outputAssemblyName), razorResult.GeneratedCode);

If all went well, the next use is simple :

Assembly asm = Assembly.LoadFrom(outputAssemblyName);if (asm == null){MessageBox.Show("Error while loading assembly");}else{Type typ = asm.GetType("RazorOutput.Template");if (typ == null){MessageBox.Show("Not found RazorOutput.Template in build {0}", asm.FullName);}else{TemplateBase newTemplate = Activator.CreateInstance(typ) as TemplateBase;if (newTemplate == null){MessageBox.Show("Cannot create a RazorOutput.Template instance or it doesn't inherit TemplateBase");}else{// here we assign all the data we need to newTemplate// ...newTemplate.Execute();string resultHTML = newTemplate.Buffer.ToString();newTemplate.Buffer.Clear();resultHTML; // nobody in their right mind would return String here, but this is just an example}}}

That’s pretty much it. The only question that remains is how exactly to specify these representations – via TemplateBase, or via a Razor syntax like

@functions {public string CustomerName { get; set; }public string ResetLink { get; set; }}

In the last case, you have to give up dynamic pattern generation, but it’s very easy to access this data.
So, with some simple moves, we avoided the temptation of writing "another" templating tool by using the powerful and convenient tool from MS

1 It is assumed that since you are writing under .NET Framework, it is supposed to be installed on the client. But Office, Crystal Reports, SQL Server, Visual Studio are not necessarily

You may also like