Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
with
97 additions
and 0 deletions.
@@ -0,0 +1,97 @@ | ||
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.ViewEngines; | ||
using Microsoft.AspNetCore.Mvc.ViewFeatures; | ||
using Microsoft.AspNetCore.Routing; | ||
using System; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
|
||
namespace RazorHtmlEmails.RazorClassLib.Services | ||
{ | ||
// Code from: https://github.com/aspnet/Entropy/blob/dev/samples/Mvc.RenderViewToString/RazorViewToStringRenderer.cs | ||
|
||
public class RazorViewToStringRenderer : IRazorViewToStringRenderer | ||
{ | ||
private IRazorViewEngine _viewEngine; | ||
private ITempDataProvider _tempDataProvider; | ||
private IServiceProvider _serviceProvider; | ||
|
||
public RazorViewToStringRenderer( | ||
IRazorViewEngine viewEngine, | ||
ITempDataProvider tempDataProvider, | ||
IServiceProvider serviceProvider) | ||
{ | ||
_viewEngine = viewEngine; | ||
_tempDataProvider = tempDataProvider; | ||
_serviceProvider = serviceProvider; | ||
} | ||
|
||
public async Task<string> RenderViewToStringAsync<TModel>(string viewName, TModel model) | ||
{ | ||
var actionContext = GetActionContext(); | ||
var view = FindView(actionContext, viewName); | ||
|
||
using (var output = new StringWriter()) | ||
{ | ||
var viewContext = new ViewContext( | ||
actionContext, | ||
view, | ||
new ViewDataDictionary<TModel>( | ||
metadataProvider: new EmptyModelMetadataProvider(), | ||
modelState: new ModelStateDictionary()) | ||
{ | ||
Model = model | ||
}, | ||
new TempDataDictionary( | ||
actionContext.HttpContext, | ||
_tempDataProvider), | ||
output, | ||
new HtmlHelperOptions()); | ||
|
||
await view.RenderAsync(viewContext); | ||
|
||
return output.ToString(); | ||
} | ||
} | ||
|
||
private IView FindView(ActionContext actionContext, string viewName) | ||
{ | ||
var getViewResult = _viewEngine.GetView(executingFilePath: null, viewPath: viewName, isMainPage: true); | ||
if (getViewResult.Success) | ||
{ | ||
return getViewResult.View; | ||
} | ||
|
||
var findViewResult = _viewEngine.FindView(actionContext, viewName, isMainPage: true); | ||
if (findViewResult.Success) | ||
{ | ||
return findViewResult.View; | ||
} | ||
|
||
var searchedLocations = getViewResult.SearchedLocations.Concat(findViewResult.SearchedLocations); | ||
var errorMessage = string.Join( | ||
Environment.NewLine, | ||
new[] { $"Unable to find view '{viewName}'. The following locations were searched:" }.Concat(searchedLocations)); ; | ||
|
||
throw new InvalidOperationException(errorMessage); | ||
} | ||
|
||
private ActionContext GetActionContext() | ||
{ | ||
var httpContext = new DefaultHttpContext(); | ||
httpContext.RequestServices = _serviceProvider; | ||
return new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); | ||
} | ||
|
||
} | ||
public interface IRazorViewToStringRenderer | ||
{ | ||
Task<string> RenderViewToStringAsync<TModel>(string viewName, TModel model); | ||
} | ||
} |