Skip to content

Instantly share code, notes, and snippets.

@cdroulers
Last active June 24, 2020 23:40
Show Gist options
  • Save cdroulers/9ed5b5b2e5c035a0e6912a88c7043f96 to your computer and use it in GitHub Desktop.
Save cdroulers/9ed5b5b2e5c035a0e6912a88c7043f96 to your computer and use it in GitHub Desktop.
Simple replacement for RazorLight in .NET Core 2.0 (licensed under The Unlicense https://choosealicense.com/licenses/unlicense/)
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 Emails
{
public class RazorTemplateRenderer
{
private readonly IRazorViewEngine viewEngine;
private readonly ITempDataProvider tempDataProvider;
private readonly IServiceProvider serviceProvider;
public RazorTemplateRenderer(
IRazorViewEngine viewEngine,
ITempDataProvider tempDataProvider,
IServiceProvider serviceProvider)
{
this.viewEngine = viewEngine;
this.tempDataProvider = tempDataProvider;
this.serviceProvider = serviceProvider;
}
public async Task<string> RenderView<TModel>(string name, TModel model)
{
var actionContext = this.GetActionContext();
var viewEngineResult = this.viewEngine.FindView(actionContext, name, false);
if (!viewEngineResult.Success)
{
throw new InvalidOperationException(string.Format("Couldn't find view '{0}'", name));
}
var view = viewEngineResult.View;
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,
this.tempDataProvider),
output,
new HtmlHelperOptions());
await view.RenderAsync(viewContext);
return output.ToString();
}
}
private ActionContext GetActionContext()
{
var httpContext = new DefaultHttpContext
{
RequestServices = this.serviceProvider
};
return new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
}
}
}
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace Backend
{
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", reloadOnChange: true, optional: true)
.AddJsonFile($"appsettings.{Environment.MachineName}.json", reloadOnChange: true, optional: true)
.AddEnvironmentVariables();
this.Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddLogging();
services.AddMvc();
RegisterRazorStuff(services);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseMvc();
}
public static void RegisterRazorStuff(IServiceCollection services)
{
services.Configure<RazorViewEngineOptions>(options =>
{
options.FileProviders.Clear();
// My use-case was with embedded files, but could be changed to Physical with similar parameters
options.FileProviders.Add(new EmbeddedFileProvider(Assembly.GetExecutingAssembly()));
options.ViewLocationFormats.Add("{0}.cshtml");
});
services.AddScoped<RazorTemplateRenderer>();
}
}
}
namespace Test
{
public class TestController : Controller
{
private readonly RazorTemplateRenderer renderer;
public TestController(RazorTemplateRenderer renderer)
{
this.renderer = renderer;
}
public void Get()
{
var model = new TestModel() { String = "TEST" };
// Uses EmbeddedFileProvider, but can be changed for PhysicalFileProvider
var htmlString = await this.templateRenderer.RenderView("FullNamespace.Of.View", model);
}
}
}
@mcintyre321
Copy link

OK to use this in an MIT licenced project (FormFactory)?

@cdroulers
Copy link
Author

@mcintyre321 Sure is! Sorry for the delay, I didn't get a notification for this!

@cdroulers
Copy link
Author

Updated the license!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment