参数 'ViewName' 与渲染视图中的任何可用视图都不匹配字符串 asp.net 核心
Parameter 'ViewName' does not match any available view in render view to string asp.net core
我正在使用 .net6,我想将视图呈现为字符串以发送电子邮件,但我收到错误消息:
视图寻址正确,但无法渲染。
控制器(项目。Web/Controllers/AccountController.cs):
string body = _viewRender.RenderToStringAsync("~/Views/Account/Email/EmailBody.cshtml", user);
SendEmail.Send(register.Email, "Activation email", body);
将视图呈现为字符串 class(Project.Core/Convertors/RenderViewToString.cs):
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 PotLearn.Core.Convertors
{
public interface IViewRenderService
{
string RenderToStringAsync(string viewName, object model);
}
public class RenderViewToString : IViewRenderService
{
private readonly IRazorViewEngine _razorViewEngine;
private readonly ITempDataProvider _tempDataProvider;
private readonly IServiceProvider _serviceProvider;
public RenderViewToString(IRazorViewEngine razorViewEngine,
ITempDataProvider tempDataProvider,
IServiceProvider serviceProvider)
{
_razorViewEngine = razorViewEngine;
_tempDataProvider = tempDataProvider;
_serviceProvider = serviceProvider;
}
public 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()
);
viewResult.View.RenderAsync(viewContext);
return sw.ToString();
}
}
}
}
查看(项目。Web/Views/Account/Email/EmailBody.cshtml):
@model PotLearn.DataLayer.Entities.User.User
<p>@Model.UserName hello!</p>
谢谢
您收到此错误是因为您使用的是 custom/dummy ActionContext
与实际执行的方法无关,并结合了视图引擎 FindView
方法。
FindView
方法需要来自执行上下文的信息。
来自 documentation
Finds the view with the given viewName using view locations and information from the context.
由于您传递的是绝对路径,因此您可以通过调用视图引擎 GetView
方法来解决问题,该方法不依赖于执行上下文。
var viewResult = _razorViewEngine.GetView(null, pathToView, false);
查看下面的完整代码。
您的代码还有第二个问题 - 虽然与查找视图无关;
未等待以下呼叫。
viewResult.View.RenderAsync(viewContext);
要解决,您需要 await
那个,这需要您的方法签名更改为 return Task<string>
.
public interface IViewRenderService
{
Task<string> RenderToStringAsync(string pathToView, object model);
}
渲染视图的调用看起来像
string body = await _viewRender.RenderToStringAsync("~/Views/Account/Email/EmailBody.cshtml", user);
渲染方法的完整代码
public async Task<string> RenderToStringAsync(string pathToView, 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.GetView(null, pathToView, false);
if (viewResult.View == null)
{
throw new ArgumentNullException($"{pathToView} 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();
}
}
我正在使用 .net6,我想将视图呈现为字符串以发送电子邮件,但我收到错误消息:
视图寻址正确,但无法渲染。
控制器(项目。Web/Controllers/AccountController.cs):
string body = _viewRender.RenderToStringAsync("~/Views/Account/Email/EmailBody.cshtml", user);
SendEmail.Send(register.Email, "Activation email", body);
将视图呈现为字符串 class(Project.Core/Convertors/RenderViewToString.cs):
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 PotLearn.Core.Convertors
{
public interface IViewRenderService
{
string RenderToStringAsync(string viewName, object model);
}
public class RenderViewToString : IViewRenderService
{
private readonly IRazorViewEngine _razorViewEngine;
private readonly ITempDataProvider _tempDataProvider;
private readonly IServiceProvider _serviceProvider;
public RenderViewToString(IRazorViewEngine razorViewEngine,
ITempDataProvider tempDataProvider,
IServiceProvider serviceProvider)
{
_razorViewEngine = razorViewEngine;
_tempDataProvider = tempDataProvider;
_serviceProvider = serviceProvider;
}
public 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()
);
viewResult.View.RenderAsync(viewContext);
return sw.ToString();
}
}
}
}
查看(项目。Web/Views/Account/Email/EmailBody.cshtml):
@model PotLearn.DataLayer.Entities.User.User
<p>@Model.UserName hello!</p>
谢谢
您收到此错误是因为您使用的是 custom/dummy ActionContext
与实际执行的方法无关,并结合了视图引擎 FindView
方法。
FindView
方法需要来自执行上下文的信息。
来自 documentation
Finds the view with the given viewName using view locations and information from the context.
由于您传递的是绝对路径,因此您可以通过调用视图引擎 GetView
方法来解决问题,该方法不依赖于执行上下文。
var viewResult = _razorViewEngine.GetView(null, pathToView, false);
查看下面的完整代码。
您的代码还有第二个问题 - 虽然与查找视图无关;
未等待以下呼叫。
viewResult.View.RenderAsync(viewContext);
要解决,您需要 await
那个,这需要您的方法签名更改为 return Task<string>
.
public interface IViewRenderService
{
Task<string> RenderToStringAsync(string pathToView, object model);
}
渲染视图的调用看起来像
string body = await _viewRender.RenderToStringAsync("~/Views/Account/Email/EmailBody.cshtml", user);
渲染方法的完整代码
public async Task<string> RenderToStringAsync(string pathToView, 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.GetView(null, pathToView, false);
if (viewResult.View == null)
{
throw new ArgumentNullException($"{pathToView} 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();
}
}