How to return rendered razor view from Web API controller

ASP.NET MVC4 Web API controller should return Razor view as html in json result property.

I tried controller

    public class TestController : ApiController
    {


        public HttpResponseMessage Get()
        {
            var body = RenderViewToString<object>("~/Views/Broneeri/Schedule.cshtml", new object() );
            return Request.CreateResponse(HttpStatusCode.OK, new { content = body } );
      }

    string RenderViewToString<T>(string viewName, T model)
        {
            ViewDataDictionary ViewData = new ViewDataDictionary(model);
            TempDataDictionary TempData = new TempDataDictionary();
            ControllerContext controllerContext = new System.Web.Mvc.ControllerContext();
            controllerContext.RouteData = new RouteData();

            controllerContext.RouteData.Values.Add("controller", "Schedule");
            using (var sw = new StringWriter())
            {
                var viewResult = ViewEngines.Engines.FindPartialView(controllerContext, viewName);
                var viewContext = new ViewContext(controllerContext, viewResult.View, ViewData,          
                           TempData, sw);
                viewResult.View.Render(viewContext, sw);
                viewResult.ViewEngine.ReleaseView(controllerContext, viewResult.View);
                return sw.GetStringBuilder().ToString();
            }
        }
     }

but got strange exception

System.NotImplementedException was unhandled by user code
HResult=-2147467263
Message=The method or operation is not implemented.
Source=System.Web
StackTrace:
at System.Web.HttpContextBase.get_Items()
at System.Web.Mvc.VirtualPathProviderViewEngine.GetPath(ControllerContext controllerContext, String[] locations, String[] areaLocations, String locationsPropertyName, String name, String controllerName, String cacheKeyPrefix, Boolean useCache, String[]& searchedLocations)
at System.Web.Mvc.VirtualPathProviderViewEngine.FindPartialView(ControllerContext controllerContext, String partialViewName, Boolean useCache)
at System.Web.Mvc.ViewEngineCollection.Find(Func`2 lookup, Boolean trackSearchedPaths)
at System.Web.Mvc.ViewEngineCollection.Find(Func`2 cacheLocator, Func`2 locator)

at line

var viewResult = ViewEngines.Engines.FindPartialView(controllerContext, viewName);

How to return html content from view in ASP.NET 4 Web API controller ?

Hi there,

Check out this article here: http://codetunnel.io/how-to-render-an-aspnet-mvc-view-to-a-string-from-within-the-controller/

Is it choking because it’s not really reading a Partial view from the controller? If it’s a view, not a partial, try using the ViewEngines.Engines.FindView method.

Let me know how it goes!

Hi!

Thank you.

My code is based on this article.

In my case Controller is derivered from APIController class. APIController does not have ControllerContext and thus this article code cannopt used directly.

So this code creates ControllerContext manually. It looks like this causes the exception.

How to fix this so that view as string can returned from APIController ? If base class is changed to Controller , this code works OK.

I changed FindPartialView to

var
viewResult =
ViewEngines.Engines.FindView(controllerContext,
viewName,
"Broneeri");

But same exception occurs.

View is defined as

@inherits ViewBase<Store.ViewModels.ScheduleViewModel>

@{
    Layout = null;
}

<p>Test</p>

View returns html fragment which is appended to page in browser in single page application.

Here we go. Try this. Basically what you’re going to do is create a bogus ControllerContext like you’re already trying to do, but do it a little better.

http://stackoverflow.com/questions/23494741/mvc-5-render-view-to-string

    public class ValuesController : ApiController
    {
        // GET api/values
        public HttpResponseMessage Get()
        {
            var body = RenderViewToString("Values", "~/Views/Home/Index.cshtml", new object());
            return Request.CreateResponse(HttpStatusCode.OK, new { content = body });
        }

        public static string RenderViewToString(string controllerName, string viewName, object viewData)
        {
            using (var writer = new StringWriter())
            {
                var routeData = new RouteData();
                routeData.Values.Add("controller", controllerName);
                var fakeControllerContext = new ControllerContext(new HttpContextWrapper(new HttpContext(new HttpRequest(null, "http://google.com", null), new HttpResponse(null))), routeData, new FakeController());
                var razorViewEngine = new RazorViewEngine();
                var razorViewResult = razorViewEngine.FindView(fakeControllerContext, viewName, "", false);

                var viewContext = new ViewContext(fakeControllerContext, razorViewResult.View, new ViewDataDictionary(viewData), new TempDataDictionary(), writer);
                razorViewResult.View.Render(viewContext, writer);
                return writer.ToString();
            }
        }
    }

    public class FakeController : ControllerBase  { protected override void ExecuteCore() { }  }

Thank you. In Mono this causes exception at line

razorViewResult.View.Render(viewContext, writer);

Object reference not set to an instance of an object
System.NullReferenceException

at System.Web.HttpRequest.get_IsLocal () <0x00026>
at System.Web.HttpRequestWrapper.get_IsLocal () <0x0001b>
at System.Web.WebPages.WebPageHttpHandler.ShouldGenerateSourceHeader (System.Web.HttpContextBase) <0x0001f>
at System.Web.WebPages.WebPageBase.ExecutePageHierarchy () <0x0002b>
at System.Web.Mvc.WebViewPage.ExecutePageHierarchy () <0x0005f>
at System.Web.WebPages.StartPage.RunPage () <0x0001f>
at System.Web.WebPages.StartPage.ExecutePageHierarchy () <0x00057>
at System.Web.WebPages.WebPageBase.ExecutePageHierarchy (System.Web.WebPages.WebPageContext,System.IO.TextWriter,System.Web.WebPages.WebPageRenderingBase) <0x000e5>
at System.Web.Mvc.RazorView.RenderView (System.Web.Mvc.ViewContext,System.IO.TextWriter,object) <0x00227>
at System.Web.Mvc.BuildManagerCompiledView.Render (System.Web.Mvc.ViewContext,System.IO.TextWriter) <0x000a8>
at Controllers.APIBase.RenderViewToString (string,string,object) 

How to use it in Mono ? In ASP.NET MVC4 it works.

It looks like exception occurs in this method:

https://github.com/mono/mono/blob/master/mcs/class/System.Web/System.Web/HttpRequest.cs#L1726

How to fix it ? Similar method called from regular controller using controller context works in Mono.

Maybe it is possible to create some wrapper so that WebAPI calls regular controller to get view as string or use RazorEngine to render view?

I posted this also in 

http://stackoverflow.com/questions/26854342/exception-in-mono-system-web-rendering-view-in-asp-net-web-api-controller

Leave a Reply