Question

I'm using the RazorEngine and the Parse method throws an error if I specify the layout in the view. If I don't specify it then the Parse is successful but the layout is not present (it seems to ignore that the layout if specified in _ViewStart.cshtml). Please advise on tell me how do I get the RazorEngine Parse method to work successfully with the layout?

I have included the C#, view, and layout below:

private String GetViewHtmlIncludingLayout(Controller controller, Object model, String view)
{       
    // this returns the view as string, including its razor markup      
    string template = ControllerBaseExtensions.GetViewTemplate(controller, view);    
    // this converts the razor markup view to html
    string result = Razor.Parse(template, model);
    return result;
}

View

@using Carnotaurus.GhostPubsMvc.Web.Models
@model AboutModel
@{
    Layout = "~/Views/Shared/_Layout.cshtml";
    ViewBag.Title = "About us";
}

<!-- Subhead
================================================== -->
<header class="jumbotron subhead">
    <div class="container">
        <div>
            <h1>@Model.JumboTitle</h1>
            <p class="lead">
                About ghost pubs.com
            </p>
        </div>
    </div>
</header>

<div class="container">

    <!-- Docs nav
    ================================================== -->
    <div class="row">
        <div class="span4">
            <div>
                <div>
                    <img class="img-circle face-relative" src="~/Content/bootstrap/2.3.1/img/ghostpubs/padded-logo-125x125.png" alt="Ghost Pubs" title="Ghost Pubs" />
                </div>
            </div>
        </div>

        <div class="span8">

            <!-- Well
          ================================================== -->
            <section id="well">
                <div class="page-header">
                    <h1>All about Ghost Pubs dot Com</h1>
                </div>
                <h2>Let's tell you who we are</h2>
                <div class="well well-large">
                    <p>
                        We are chaps involved in running <a href="http://www.myPubGuide.com">myPUBGUIDE.com</a>.
    We have noticed that almost sixty public houses close each month. Therefore, given
    the success of myPUBGUIDE, we thought it would be a good idea to launch a similar
    website for drinking establishments that are haunted, closed, abandoned, and demolished.
                    </p>
                    <p>
                        Clearly such establishments do not belong on an active pub search. These deserve
    a special website of their own, where your contribution would be encouraged. We
    intend to launch this website in early 2014. We are sure that you have a ghost story
    to share with us about your old local.
                    </p>
                    <p>
                        As the name suggests Ghost Pubs we are looking for any information you can give
    regarding any hauntings or paranormal phenomena regarding your local pub.
                    </p>
                </div>

                <hr>
            </section>
        </div>
    </div>
</div>

Layout

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
    <meta name="viewport" content="width=device-width" />
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
    <!-- styles -->
    <link href="@Url.Content("~/content/bootstrap/2.3.1/css/bootstrap.css")" rel="stylesheet">
    <link href="@Url.Content("~/content/bootstrap/2.3.1/css/bootstrap-responsive.css")" rel="stylesheet">
    <link href="@Url.Content("~/content/bootstrap/2.3.1/css/docs.css")" rel="stylesheet">
    <link href="@Url.Content("~/content/bootstrap/2.3.1/css/ghostpubs/docs2.css")" rel="stylesheet">
    <link href="@Url.Content("~/content/bootstrap/2.3.1/css/prettify.css")" rel="stylesheet">
    <link href="@Url.Content("~/content/bootstrap/2.3.1/font-awesome/css/font-awesome.css")" rel="stylesheet">
    <link href="@Url.Content("~/content/bootstrap/2.3.1/css/bootswatch.css")" rel="stylesheet">
</head>
<body data-spy="scroll" data-target=".bs-docs-sidebar">

    <!-- Navbar
    ================================================== -->
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="navbar-inner">
            <div class="container">
                <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="brand" href="/home/index">GhostPubs.com</a>
                <div class="nav-collapse collapse">
                    <ul class="nav">
                        <li>
                            <a href="/home/index">Home</a>
                        </li>
                        <li>
                            <a href="/home/index">News</a>
                        </li>
                        <li>
                            <a href="/home/index">Search</a>
                        </li>
                        <li>
                            <a href="/home/about">About us</a>
                        </li>
                        <li class="">
                            <a href="#" style="display: none">Not wired-up</a>
                        </li>
                        <li>
                            <a href="/bootstrap/index" style="display: none">Bootstrap example - Home</a>
                        </li>
                        <li>
                            <a href="/bootstrap/javascript" style="display: none">Bootstrap example- JavaScript</a>
                        </li>
                    </ul>
                </div>
            </div>
        </div>
    </div>

    @RenderBody()

    <!-- Footer
    ================================================== -->
    <footer class="footer">
        <div class="container">
            <span class="label label-info">Designed and developed by <a href="http://carnotaurus.philipcarney.com" target="_blank">Philip Carney</a> </span>
        </div>
    </footer>

    @Scripts.Render("~/bundles/jquery")
    @RenderSection("scripts", required: false)

    <!-- Le javascript
    ================================================== -->
    <!-- Placed at the end of the document so the pages load faster -->
    <script src="@Url.Content("~/content/bootstrap/2.3.1/js/bootstrap.js")"></script>
    <script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script>
    <script src="@Url.Content("~/content/bootstrap/2.3.1/js/jquery.js")"></script>
    <script src="@Url.Content("~/content/bootstrap/2.3.1/js/bootstrap-transition.js")"></script>
    <script src="@Url.Content("~/content/bootstrap/2.3.1/js/bootstrap-alert.js")"></script>
    <script src="@Url.Content("~/content/bootstrap/2.3.1/js/bootstrap-modal.js")"></script>
    <script src="@Url.Content("~/content/bootstrap/2.3.1/js/bootstrap-dropdown.js")"></script>
    <script src="@Url.Content("~/content/bootstrap/2.3.1/js/bootstrap-scrollspy.js")"></script>
    <script src="@Url.Content("~/content/bootstrap/2.3.1/js/bootstrap-tab.js")"></script>
    <script src="@Url.Content("~/content/bootstrap/2.3.1/js/bootstrap-tooltip.js")"></script>
    <script src="@Url.Content("~/content/bootstrap/2.3.1/js/bootstrap-popover.js")"></script>
    <script src="@Url.Content("~/content/bootstrap/2.3.1/js/bootstrap-button.js")"></script>
    <script src="@Url.Content("~/content/bootstrap/2.3.1/js/bootstrap-collapse.js")"></script>
    <script src="@Url.Content("~/content/bootstrap/2.3.1/js/bootstrap-carousel.js")"></script>
    <script src="@Url.Content("~/content/bootstrap/2.3.1/js/bootstrap-typeahead.js")"></script>
    <script src="@Url.Content("~/content/bootstrap/2.3.1/js/bootstrap-affix.js")"></script>

    <script src="@Url.Content("~/content/bootstrap/2.3.1/js/holder.js")"></script>
    <script src="@Url.Content("~/content/bootstrap/2.3.1/js/prettify.js")"></script>

    <script src="@Url.Content("~/content/bootstrap/2.3.1/js/application.js")"></script>
</body>
</html>

The error is: Object reference not set to an instance of an object.

There is no inner error but the stack trace says:

  at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context) in c:\_git\RazorEngine\src\Core\RazorEngine.Core\Templating\TemplateBase.cs:line 139
   at RazorEngine.Templating.TemplateService.Run(ITemplate template, DynamicViewBag viewBag) in c:\_git\RazorEngine\src\Core\RazorEngine.Core\Templating\TemplateService.cs:line 608
   at RazorEngine.Templating.TemplateService.Parse(String razorTemplate, Object model, DynamicViewBag viewBag, String cacheName) in c:\_git\RazorEngine\src\Core\RazorEngine.Core\Templating\TemplateService.cs:line 439
   at RazorEngine.Razor.Parse(String razorTemplate, Object model) in c:\_git\RazorEngine\src\Core\RazorEngine.Core\Razor.cs:line 251
   at Carnotaurus.GhostPubsMvc.Web.Controllers.HomeController.GetViewHtmlIncludingLayout(Controller controller, Object model, String view, String layoutPath) in c:\test\GhostPubsMvc4\Carnotaurus.GhostPubsMvc.Web\Carnotaurus.GhostPubsMvc.Web\Controllers\HomeController.cs:line 59
   at Carnotaurus.GhostPubsMvc.Web.Controllers.HomeController.CreateHtmlPage(AboutModel model, String view, String layoutPath, String targetFilename) in c:\test\GhostPubsMvc4\Carnotaurus.GhostPubsMvc.Web\Carnotaurus.GhostPubsMvc.Web\Controllers\HomeController.cs:line 41
   at Carnotaurus.GhostPubsMvc.Web.Controllers.HomeController.About() in c:\test\GhostPubsMvc4\Carnotaurus.GhostPubsMvc.Web\Carnotaurus.GhostPubsMvc.Web\Controllers\HomeController.cs:line 34
   at lambda_method(Closure , ControllerBase , Object[] )
   at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
   at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.ActionInvocation.InvokeSynchronousActionMethod()
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<BeginInvokeSynchronousActionMethod>b__36(IAsyncResult asyncResult, ActionInvocation innerInvokeState)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
   at System.Web.Mvc.Async.AsyncResultWrapper.End[TResult](IAsyncResult asyncResult, Object tag)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3c()
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass45.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3e()
Was it helpful?

Solution

Here I have one of the best and alternate solutions for your problems which will work both view and PartialView. It means with or without Layout in Views. Given solutions exactly return string which you have implemented in your methods. I have already posted this solutions at https://stackoverflow.com/a/18978036/2318354. Now here I will explain in details with Controller, Views and Models.

First of create one class with following methods.

public static class RazorViewToString
{
    public static string RenderRazorViewToString(this Controller controller, string viewName, object model)
    {
        if (controller == null)
        {
            throw new ArgumentNullException(nameof(controller), "The parameter controller cannot be null.");
        }

        if (controller.ControllerContext == null)
        {
            return string.Empty;
        }

        controller.ViewData.Model = model;
        using (var sw = new StringWriter())
        {
            var viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
            var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
            viewResult.View.Render(viewContext, sw);
            viewResult.ViewEngine.ReleaseView(controller.ControllerContext, viewResult.View);
            return sw.GetStringBuilder().ToString();
        }
    }

}

Now create one simple Model name it as Test.cs

public class Test
{
    public string Name { get; set; }
}

Your Controller should be like this

public ActionResult Index()
{
    Test test = new Test();
    test.Name = "XYZ";
    string html = RazorViewToString.RenderRazorViewToString(this, "~/Views/Test/index.cshtml", test);
    return View();
}

Now even in your Views you use Layout or not it will work fine as your View may be like this

@model W2G.Models.Test
@using W2G.App_GlobalResources;
@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
This is test @Model.Name

So above solutions will return exact you want from your Razor.Parse

I hope it will help you.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top