5

In a testing situation, I'd like to be able to use the default viewEngine to render a given ViewResult to HTML.

Currently, my views are WebForms-based. But I might have Spark or Razor views at some point. For now, I'd like to focus on WebForms. Can I render my views from a test?

Byron Sommardahl
  • 12,743
  • 15
  • 74
  • 131
  • You may want to consider browser based testing. That way you could support testing AJAX or javascript interaction. – Ryan Aug 19 '11 at 23:54
  • 1
    I have browser-based testing also through Selenium. But I am trying to test the actual HTML/Javascript that is being rendered. – Byron Sommardahl Aug 20 '11 at 00:45

1 Answers1

7

Here's a method that will let you render a ViewResult to a string. The only tricky part to using it in your context will be to Mock up a viable ControllerContext.

static string RenderPartialViewToString(ControllerContext context, ViewResultBase partialViewResult)
    {
        Require.ThatArgument(partialViewResult != null);
        Require.That(context != null);
        using (var sw = new StringWriter())
        {
            if (string.IsNullOrEmpty(partialViewResult.ViewName))
            {
                partialViewResult.ViewName = context.RouteData.GetRequiredString("action");
            }
            ViewEngineResult result = null;
            if (partialViewResult.View == null)
            {
                result = partialViewResult.ViewEngineCollection.FindPartialView(context, partialViewResult.ViewName);
                if(result.View == null)
                    throw new InvalidOperationException(
                                   "Unable to find view. Searched in: " +
                                   string.Join(",", result.SearchedLocations));
                partialViewResult.View = result.View;
            }

            var view = partialViewResult.View;
            var viewContext = new ViewContext(context, view, partialViewResult.ViewData,
                                              partialViewResult.TempData, sw);
            view.Render(viewContext, sw);
            if (result != null)
            {
                result.ViewEngine.ReleaseView(context, view);
            }
            return sw.ToString();
        }
    }
StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
  • Very helpful, thanks. Is there any blog post or other kind of explanation regarding how this was produced? – Jon Sep 21 '11 at 09:54
  • 1
    @Jon: I just used ILSpy to see what `ViewResultBase.ExecuteResult` does, and modified it to use a `StringWriter` instead of the request output stream. (I had to delve into `PartialViewResult.FindView` for part of it, too, since that's a protected method. The `Require.That` statements are just a concise way to say `if(!...) throw...`. – StriplingWarrior Sep 21 '11 at 15:12