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:
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
Is There a Reason Image.Fromfile Throws an Outofmemoryexception for an Invalid Image Format
How to Submit Http Form Using C#
Views in Separate Assemblies in ASP.NET MVC
Parse a Number from Exponential Notation
How to Determine If a Type Implements a Specific Generic Interface Type
String Concatenation Using '+' Operator
Uwp Binding in Style Setter Not Working
An Object Reference Is Required to Access Non-Static Member
Asp.Net: Invalid Postback or Callback Argument
Running Scripts in HTMLagilitypack
Configure the Authorization Server Endpoint
Unity Singleton Manager Classes
Cause of Error Cs0161: Not All Code Paths Return a Value
How to Sort Strings Alphabetically While Accounting for Value When a String Is Numeric