RazorEngine to support @Html / @Url methods

I recently used the latest RazorEngine library to build unit tests for views.  However I didn’t get any sample code doing exactly what I wanted to do.  When I ran the simple view test, I got the following error:

RazorEngine.Templating.TemplateCompilationException: Unable to compile template. You can find the generated source code in .
– error: (28, 13) The name ‘Html’ does not exist in the current context

The reason is because by default RazorEngine didn’t support any html helper methods, such as Html.Raw.  You needed to do your own implementation and register through TemplateServiceConfiguration.  Below are a sample code to provide Html.Raw method when parsing the view.

using System.IO;
using System.Web.Mvc;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using RazorEngine;
using RazorEngine.Configuration;
using RazorEngine.Templating;

namespace OneStore.UnitTests.Views
{
    [TestClass]
    [DeploymentItem(@"Views\Test\index.cshtml", @"Views\Test\")]
    public class FaqPageTests
    {
        private static string viewTemplate;

        [ClassInitialize]
        public static void SetupView(TestContext context)
        {
            // You can get view template as below; remember to set DeploymentItem with correct path and set the view's "Copy to output directory" to "Copy if newer".
            viewTemplate = File.ReadAllText(@"Views\Test\index.cshtml");

            // 2 approaches to implement view test using RazorEngine library.
            // And there are 2 different syntax to construct the template service.
            // you can pick which approach and syntax you prefer.

            // Personally, I prefer "using (var service = ...)" syntax instead of assigning service to static instance property.
            // For appraoch, I prefer "FakeHtmlHelper" which controls exactly what the method should behave.
        }

        [TestMethod]
        public void TestOption1()
        {
            // Arrange
            string htmlMarkup = string.Empty;
            string template = "<div>Hello @Html.Raw(Model.Name)</div>";

            var config = new TemplateServiceConfiguration
            {
                BaseTemplateType = typeof(MyCustomTemplateBase1<>)
            };

            // Act
            using (var service = new TemplateService(config))
            {
                htmlMarkup = service.Parse(template, new { Name = "TestName" }, null, null);
            }

            // Assert
            htmlMarkup.Should().NotBeNullOrEmpty();
        }

        [TestMethod]
        public void TestOption2()
        {
            // Arrange
            string htmlMarkup = string.Empty;
            string template = "<div>Hello @Html.Raw(Model.Name)</div>";

            var config = new TemplateServiceConfiguration
            {
                BaseTemplateType = typeof(MyCustomTemplateBase1<>)
            };
            var service = new TemplateService(config);
            Razor.SetTemplateService(service);

            // Act
            htmlMarkup = service.Parse(template, new { Name = "TestName" }, null, null);

            // Assert
            htmlMarkup.Should().NotBeNullOrEmpty();
        }
    }

    public abstract class MyCustomTemplateBase1<T> : TemplateBase<T>
    {
        public readonly HtmlHelper<T> Html = new HtmlHelper<T>(new ViewContext(), new FakeViewDataContainer());
    }

    public class FakeViewDataContainer : IViewDataContainer
    {
        private ViewDataDictionary _viewData = new ViewDataDictionary();
        public ViewDataDictionary ViewData { get { return _viewData; } set { _viewData = value; } }
    }

    public abstract class MyCustomTemplateBase2<T> : TemplateBase<T>
    {
        public readonly FakeHtmlHelper<T> Html = new FakeHtmlHelper<T>();
    }

    public class FakeHtmlHelper<T>
    {
        public string Raw(string value)
        {
            return string.Format("[Html.Raw: {0}]", value);
        }
    }
}

Hope this sample code will help you to build your unit tests using RazorEngine.

Advertisements

My readings – 2014 week 52

  1. JavaScript Application Architecture on the road to 2015.
  2. AsyncTask, DefineJS ES6 Features: I think it is great to have a wrapper for running methods asynchronously.
  3. * General reference: Training for Software Developer
  4. Difference between List and ArrayList
  5. Algorithm: Solution using Ant Colony Optimization (ACO) for Travelling Sales Person (TSP) problem.
  6. The title of the post makes me read it: How to avoid 26 API requests on your page?  after reading, it is good to know that Asp.Net Web API supports DefaultHttpBatchHandler and already have client side library like jquery.batch and batchjs as well.
  7. Read this post if you want to create your own NuGet templates.
  8. If you want to store data off-line for client-side application, you can consider using Firebase; you can try out the tutorial.
  9. Fibonacci number is a common question you may be asked in an interview.  Do you want to know fast way to calculate a large fibonacci number; read this post.

Merry Christmas and Happy New Year!!

My readings – 2014 Week 51

  1. What’s new in C# 6.0
  2. Top 10 C# 6.0 language features; I love the conditional access operator.
  3. Want to learn CSS animation? if you are newbie, you can read this CSS Animation For Beginner post.
  4. Good post to share about doing animation correctly: Five ways to animate responsibly.
  5. Text on images from CSS Tricks.
  6. What is the performance for each popular client-side MVC framework?  Read this post to get the answer.
  7. Avoid SCSS @extend
  8. *This is one of todo task in my list; try different MV* framework.  Go visit: TodoMVC.
  9. If you need to write Installer for your program in .Net, you can try use this installer extension.

My readings – 2014 Week 50

  1. I read the first post about exposing additional fields using radio button; then I find another link inside it talking about checkbox hacks.  If you are developer and always think of using JavaScript to do your work first, then you should read these posts to explore different approach to do your work.
  2. Share CSS only loaders.
  3. See 5 different ways to swap out text.
  4. Learn more CSS properties – content and attr.
  5. Read a post about MVC ignore route and learn about “Catch-all” route syntax.
  6. I haven’t used Flux before; this is a good post to give an introduction of Flux.
  7. AngularJS performance in large applications
  8. A JS library, thaw.js to support synthetic asynchronous processing in JavaScript.

My readings – 2014 Week 49

  1. place you can find different style guides for reference.
  2. A JS library for interaction such as drag-and-drop similar to jQuery UI drag and drop.
  3. A cool websites listed some great CSS animiated examples.
  4. A post with details how to set up and use remote IE.
  5. A old post about nth CSS selector, but it is good to read it.
  6. You definitely needed to read these 2 posts if you are use @extend in your SASS – tell you when to use @extend and how @extend behaves in your SASS.
  7. To optimize a faster loading experience, you can try to apply critical path CSS using this tool.
  8. Do you know currentColor CSS property?
  9. If you are interested about speech recognition on the web, you will like to read this post.
  10. *Service worker – I believe this is the next hot topic that we will work on this and more libraries will be created for this; it makes client-side development more powerful.  You should read this, even you may not use it in the near future.
  11. Read a post talk about a 101 JS util library, which works with Vanilla JS; don’t know what is Vanilla.  Then I go to Vanilla site and find that is the most lightweight framework, already loaded in browsers, and faster to retrieve DOM using Id/tag name compared to other frameworks, e.g. jQuery, Dojo, Prototype JS, etc.  Need to take some time to try it.
  12. CSS clip-path with animation, it is so great to see how clip-path works with animation.