Return View as String in .Net Core

Return View as String in .NET Core

Thanks to Paris Polyzos and his article.

I'm re-posting his code here, just in case the original post got removed for any reason.

Create Service in file viewToString.cs as below code:

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Routing;
 
namespace WebApplication.Services
{
    public interface IViewRenderService
    {
        Task<string> RenderToStringAsync(string viewName, object model);
    }
 
    public class ViewRenderService : IViewRenderService
    {
        private readonly IRazorViewEngine _razorViewEngine;
        private readonly ITempDataProvider _tempDataProvider;
        private readonly IServiceProvider _serviceProvider;
 
        public ViewRenderService(IRazorViewEngine razorViewEngine,
            ITempDataProvider tempDataProvider,
            IServiceProvider serviceProvider)
        {
            _razorViewEngine = razorViewEngine;
            _tempDataProvider = tempDataProvider;
            _serviceProvider = serviceProvider;
        }
 
        public async Task<string> RenderToStringAsync(string viewName, object model)
        {
            var httpContext = new DefaultHttpContext { RequestServices = _serviceProvider };
            var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
 
            using (var sw = new StringWriter())
            {
                var viewResult = _razorViewEngine.FindView(actionContext, viewName, false);
 
                if (viewResult.View == null)
                {
                    throw new ArgumentNullException($"{viewName} does not match any available view");
                }
 
                var viewDictionary = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary())
                {
                    Model = model
                };
 
                var viewContext = new ViewContext(
                    actionContext,
                    viewResult.View,
                    viewDictionary,
                    new TempDataDictionary(actionContext.HttpContext, _tempDataProvider),
                    sw,
                    new HtmlHelperOptions()
                );
 
                await viewResult.View.RenderAsync(viewContext);
                return sw.ToString();
            }
        }
    }
}

2. Add the service to the Startup.cs file, as:

using WebApplication.Services;

public void ConfigureServices(IServiceCollection services)
{
...
services.AddScoped<IViewRenderService, ViewRenderService>();
}

3. Add "preserveCompilationContext": true to the buildOptions in the project.json, so the file looks like:

{
"version": "1.0.0-*",
"buildOptions": {
"debugType": "portable",
"emitEntryPoint": true,
"preserveCompilationContext": true
},
"dependencies": {
"Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
"Microsoft.AspNetCore.Mvc": "1.0.1"
},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
}
},
"imports": "dnxcore50"
}
}
}

4. Define you model, for example:

public class InviteViewModel {
public string UserId {get; set;}
public string UserName {get; set;}
public string ReferralCode {get; set;}
public int Credits {get; set;}
}

5. Create your Invite.cshtml for example:

@{
ViewData["Title"] = "Contact";
}
@ViewData["Title"].
user id: @Model.UserId

6. In the Controller:

a. Define the below at the beginning:

private readonly IViewRenderService _viewRenderService;

public RenderController(IViewRenderService viewRenderService)
{
_viewRenderService = viewRenderService;
}

b. Call and return the view with model as below:

var result = await _viewRenderService.RenderToStringAsync("Email/Invite", viewModel);
return Content(result);

c. The FULL controller example, could be like:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using WebApplication.Services;

namespace WebApplication.Controllers
{
[Route("render")]
public class RenderController : Controller
{
private readonly IViewRenderService _viewRenderService;

public RenderController(IViewRenderService viewRenderService)
{
_viewRenderService = viewRenderService;
}

[Route("invite")]
public async Task<IActionResult> RenderInviteView()
{
ViewData["Message"] = "Your application description page.";
var viewModel = new InviteViewModel
{
UserId = "cdb86aea-e3d6-4fdd-9b7f-55e12b710f78",
UserName = "Hasan",
ReferralCode = "55e12b710f78",
Credits = 10
};
 
var result = await _viewRenderService.RenderToStringAsync("Email/Invite", viewModel);
return Content(result);
}

public class InviteViewModel {
public string UserId {get; set;}
public string UserName {get; set;}
public string ReferralCode {get; set;}
public int Credits {get; set;}
}
}

ASP.NET CORE Render Razor View to string with controller parameters

I think you may understand the usage of RenderRazorViewToString.This method is called by the following code:

Helper.RenderRazorViewToString(controller, "PartialViewName", model);

The second parameter is not the method name,it is the partial view name.It would not get to the IndexPartial method.

What you want is to parse the partial view with model to string.The model data get by manipulating query by searchValue and filterValue.

To meet your requirement,what you need do should be like below:

public string IndexPartial(string? searchValue, string? filterValue)
{
var model = _context.Pupils
.Where(a => a.Name.Contains(searchValue)&& a.Email.Contains(filterValue))
.FirstOrDefault(); //Manipulate query by searchValue and filterValue

//pass the correct model to the RenderRazorViewToString method
//then it would render the partial view to the correct string
var data = Helper.RenderRazorViewToString(this, "PartialViewName", model);
return data;
}

Result:
Sample Image

Render Partial View to HTML string in ASP.NET Core 2.2

Why Json result with html string? You can return a partial view directly to return html.

public IActionResult GetUpsertPartialView(MessageBoard messageBoard)
{

return PartialView("someviewname", messageBoard);
}

Render Razor View to string in ASP.NET Core

UPDATE July, 2016

Working fine on the following versions 1.0.0, RC2


Who's targeting aspnetcore RC2, this snippet might help you:

  • Create a separate Service, so you can use it either if you are not in a controller context, e.g. from a command line or on a queue runner, etc ...
  • Register this service in your IoC container in the Startup class

https://gist.github.com/ahmad-moussawi/1643d703c11699a6a4046e57247b4d09

Usage

// using a Model
string html = view.Render("Emails/Test", new Product("Apple"));

// using a Dictionary<string, object>
var viewData = new Dictionary<string, object>();
viewData["Name"] = "123456";

string html = view.Render("Emails/Test", viewData);

Notes

Links in Razor are rendered as relative URL, so this will not work on external views (like emails, etc ...).

As for now am generating the link on the controller and pass it to the view through the ViewModel.

Credit

The source is extracted from (Thanks To @pholly): https://github.com/aspnet/Entropy/blob/dev/samples/Mvc.RenderViewToString/RazorViewToStringRenderer.cs)

How to render an ASP.NET MVC view as a string?

Here's what I came up with, and it's working for me. I added the following method(s) to my controller base class. (You can always make these static methods somewhere else that accept a controller as a parameter I suppose)

MVC2 .ascx style

protected string RenderViewToString<T>(string viewPath, T model) {
ViewData.Model = model;
using (var writer = new StringWriter()) {
var view = new WebFormView(ControllerContext, viewPath);
var vdd = new ViewDataDictionary<T>(model);
var viewCxt = new ViewContext(ControllerContext, view, vdd,
new TempDataDictionary(), writer);
viewCxt.View.Render(viewCxt, writer);
return writer.ToString();
}
}

Razor .cshtml style

public string RenderRazorViewToString(string viewName, object model)
{
ViewData.Model = model;
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();
}
}

Edit: added Razor code.



Related Topics



Leave a reply



Submit