对于我的项目,我目前为我的asp.net核心应用程序实现了一个ViewRender。它生成没有控制器的视图到html,使用以下代码可以正常工作:
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());
string viewgerendered = "";
try
{
using (var sw = new StringWriter())
{
var viewResult = _razorViewEngine.GetView(viewName, 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);
viewgerendered = sw.ToString();
return viewgerendered;
}
}
catch (Exception e)
{
object temp = e.Message + " - " + e.StackTrace;
return temp.ToString();
}
}
public Task RenderToStringAsync(string v)
{
throw new NotImplementedException();
}
}
来源:https://ppolyzos.com/2016/09/09/asp-net-core-render-view-to-string/
如果不重新启动应用程序本身,则不会更新对使用此渲染器的视图所做的更改。进一步潜入其中,视图被缓存。使用_razorViewEngine.GetView
方法提及的源内注释应该摆脱我的缓存问题。但是这不起作用。
我得到了什么,尝试通过略微修改ViewRenderService来找到注册新ViewRender的方法。
//Seems not to be available on asp.net core 2.0...
services.AddMvc().Configure<MvcViewOptions>(options =>
{
options.ViewEngines.Clear();
options.ViewEngines.Add(typeof(CustomViewEngine));
});
重载RazorViewEngine以暴露ViewLookupCache,假定视图缓存位于此处。
public class CustomViewEngine : RazorViewEngine
{
public CustomViewEngine(
IRazorPageFactoryProvider pageFactory,
IRazorPageActivator pageActivator,
HtmlEncoder htmlEncoder,
IOptions<RazorViewEngineOptions> optionsAccessor,
Microsoft.AspNetCore.Razor.Language.RazorProject razorProject,
ILoggerFactory loggerFactory,
System.Diagnostics.DiagnosticSource diagnosticSource) :
base(pageFactory, pageActivator, htmlEncoder, optionsAccessor,razorProject,loggerFactory, diagnosticSource){ }
public void RemoveCachedView(string view)
{
this.ViewLookupCache.Remove(view);
}
}
关于如何在asp.net core 2.0中为视图和清除特定视图/集合进行缓存,没有太多内容。基本上我想找到一种方法,出于性能原因,我可以将整个选择的缓存视图作为命令刷新。
修改13-04-2018
正如K Finley建议的那样,我尝试按照建议清空ViewLookupCache。简而言之;
在我的startup.cs ConfigureServices中(不完全确定这是否是自定义视图引擎的注册方式)。
services.AddSingleton<IRazorViewEngine, CustomViewEngine>();
services.AddSingleton<IViewRenderService, ViewRenderService>();
自定义视图引擎:
public class CustomViewEngine : RazorViewEngine
{
public CustomViewEngine(
IRazorPageFactoryProvider pageFactory,
IRazorPageActivator pageActivator,
HtmlEncoder htmlEncoder,
IOptions<RazorViewEngineOptions> optionsAccessor,
Microsoft.AspNetCore.Razor.Language.RazorProject razorProject,
ILoggerFactory loggerFactory,
System.Diagnostics.DiagnosticSource diagnosticSource) :
base(pageFactory, pageActivator, htmlEncoder, optionsAccessor, razorProject, loggerFactory, diagnosticSource)
{ }
public void RemoveViewFromCache(string viewName, string controller, bool isLayout, bool isPartial = false, string pageName = null, string areaName = null)
{
var key = new ViewLocationCacheKey(viewName, controller, areaName, pageName, !isLayout | !isPartial, isLayout ? null : new Dictionary<string, string>(StringComparer.Ordinal));
base.ViewLookupCache.Remove(key);
}
public void RemoveViewFromCache(string viewName, bool isLayout)
{
//Code uses this one
var key = new ViewLocationCacheKey(viewName, isLayout);
base.ViewLookupCache.Remove(key);
}
}
并修改了原始的ViewRenderService ...
public class ViewRenderService : IViewRenderService
{
private CustomViewEngine _razorViewEngine;
private ITempDataProvider _tempDataProvider;
private IServiceProvider _serviceProvider;
private IHostingEnvironment _hostingEnvironment;
public ViewRenderService(IRazorViewEngine razorViewEngine,
ITempDataProvider tempDataProvider,
IServiceProvider serviceProvider,
IHostingEnvironment hostingEnvironment)
{
_razorViewEngine = (CustomViewEngine)razorViewEngine;
...
try
{
using (var sw = new StringWriter())
{
_razorViewEngine.RemoveViewFromCache(viewName, false);
var viewResult = _razorViewEngine.GetView(viewName, viewName, false);
这些修改会使用第二种方法删除ViewLookupCache。但是它仍然无法正确更新我的观点。我必须注意视图没有自己的控制器。
答案 0 :(得分:2)
如果您查看RazorViewEngine来源,可以看到如何缓存视图。我将解释如何从缓存中删除视图,但您需要了解有关视图的一些知识才能使其正常工作。
在您的示例中,您只是根据名称(我假设视图名称)来查找缓存中的视图。这不会起作用,因为您需要使用ViewLocationCacheKey在缓存中查找视图。 ViewLocationCacheKey结构上有2个构造函数。
public ViewLocationCacheKey(
string viewName,
bool isMainPage)
public ViewLocationCacheKey(
string viewName,
string controllerName,
string areaName,
string pageName,
bool isMainPage,
IReadOnlyDictionary<string, string> values)
在RazorViewEngine中,每个都被调用,具体取决于视图的加载方式(FromPath或FromViewLocations)。根据我的情况,我有一个拥有完整Razor支持的CMS,任何类型的内容都只是一个Razor View,它通过RazorViewEngine渲染,因此缓存在Memory中。当对一段内容进行更新时,我会从ViewLookupCache中删除该视图,并允许它在下一次加载时重新填充。不幸的是,RazorViewEngine(目前)不允许你将Cache换成分布式缓存选项(Redis,Memcached等)。
以下是我在自定义视图引擎上处理它的方式。
public void RemoveViewFromCache(string viewName, string controller, bool isLayout, bool isPartial = false, string pageName = null, string areaName = null) {
var key = new ViewLocationCacheKey(viewName, controller, areaName, pageName, !isLayout | !isPartial, isLayout ? null : new Dictionary<string, string>(StringComparer.Ordinal))
base.ViewLookupCache.Remove(key);
}
我在更新时删除了视图,并在下次请求时自动重新加载和缓存视图。
如果您的应用正在使用ViewLocationExpanderValues执行任何操作,则您必须进行更改。只需在应用程序运行时检查ViewLookupCache集合,您就会开始了解此处发生的事情。
答案 1 :(得分:2)
您需要启用文件观察器:
在Dockerfile中添加环境变量DOTNET_USE_POLLING_FILE_WATCHER=true
或ENV DOTNET_USE_POLLING_FILE_WATCHER=true
。
答案 2 :(得分:1)
在ASP.NET Core 2.2及更高版本中,您可以做到
services.Configure<RazorViewEngineOptions>(opts => opts.AllowRecompilingViewsOnFileChange = true);
在ConfigureServices中,当视图引擎更改时,强制视图引擎重新编译视图。