C# 在ASP.NET核心中将Razor视图呈现为字符串
我在MVC 6项目中使用以下方法解析模板:C# 在ASP.NET核心中将Razor视图呈现为字符串,c#,razor,asp.net-core,asp.net-core-mvc,C#,Razor,Asp.net Core,Asp.net Core Mvc,我在MVC 6项目中使用以下方法解析模板: Engine.Razor.RunCompile(File.ReadAllText(fullTemplateFilePath), templateName, null, model); 它适用于beta 6。升级到beta 7后无法工作,错误为: MissingMethodException:找不到方法:“Void Microsoft.AspNet.Razor.CodeGenerators.GeneratedClassContext.set_Resol
Engine.Razor.RunCompile(File.ReadAllText(fullTemplateFilePath), templateName, null, model);
它适用于beta 6。升级到beta 7后无法工作,错误为:
MissingMethodException:找不到方法:“Void Microsoft.AspNet.Razor.CodeGenerators.GeneratedClassContext.set_ResolveUrlMethodName(System.String)”。
在RazorEngine.Compilation.CompilerServiceBase.CreateHost中(类型templateType、类型modelType、字符串className)
这是global.json:
{
"projects": [ "src", "test" ],
"sdk": {
"version": "1.0.0-beta7",
"runtime": "clr",
"architecture": "x64"
}
}
这是project.json:
...
"dependencies": {
"EntityFramework.SqlServer": "7.0.0-beta7",
"EntityFramework.Commands": "7.0.0-beta7",
"Microsoft.AspNet.Mvc": "6.0.0-beta7",
"Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-beta7",
"Microsoft.AspNet.Authentication.Cookies": "1.0.0-beta7",
"Microsoft.AspNet.Authentication.Facebook": "1.0.0-beta7",
"Microsoft.AspNet.Authentication.Google": "1.0.0-beta7",
"Microsoft.AspNet.Authentication.MicrosoftAccount": "1.0.0-beta7",
"Microsoft.AspNet.Authentication.Twitter": "1.0.0-beta7",
"Microsoft.AspNet.Diagnostics": "1.0.0-beta7",
"Microsoft.AspNet.Diagnostics.Entity": "7.0.0-beta7",
"Microsoft.AspNet.Identity.EntityFramework": "3.0.0-beta7",
"Microsoft.AspNet.Server.IIS": "1.0.0-beta7",
"Microsoft.AspNet.Server.WebListener": "1.0.0-beta7",
"Microsoft.AspNet.StaticFiles": "1.0.0-beta7",
"Microsoft.AspNet.Tooling.Razor": "1.0.0-beta7",
"Microsoft.Framework.Configuration.Abstractions": "1.0.0-beta7",
"Microsoft.Framework.Configuration.Json": "1.0.0-beta7",
"Microsoft.Framework.Configuration.UserSecrets": "1.0.0-beta7",
"Microsoft.Framework.Logging": "1.0.0-beta7",
"Microsoft.Framework.Logging.Console": "1.0.0-beta7",
"Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0-beta7",
"RazorEngine": "4.2.2-beta1"
},
...
"frameworks": {
"dnx451": { }
},
...
我的模板是:
@模型动态
@{
布局=空;
}
登记处
你好,@Model
已删除ResolveUrlMethodName
。因此,在CreateHost
中,您试图设置一个不存在的属性:)
我们决定将~/
处理从core Razor移动到TagHelper
中,并在Microsoft.AspNet.Mvc.Razor
程序集中实现。以下是删除该方法的位的示例
希望这会有所帮助。过去,我在类库中使用了
RazorEngine
,因为我的目标是从类库中呈现模板
据我所知,您似乎在一个MVC 6.0项目中,所以为什么不使用RenderPartialViewToString()
方法,而不必添加对RazorEngine
的依赖性呢
记住,我只是出于好奇才这么问的
例如,在VS2015中,我创建了一个新的ASP.NET Web应用程序,并从ASP.NET 5预览模板中选择了Web应用程序模板
在ViewModels
文件夹中,我创建了一个PersonViewModel
:
公共类PersonViewModel
{
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共字符串全名
{
得到
{
返回string.Format(“{0}{1}”,this.FirstName,this.LastName);
}
}
}
然后,我创建了一个新的BaseController
,并添加了一个RenderPartialViewToString()
方法:
public string RenderPartialViewToString(字符串视图名,对象模型)
{
if(string.IsNullOrEmpty(viewName))
viewName=ActionContext.ActionDescriptor.Name;
ViewData.Model=Model;
使用(StringWriter sw=new StringWriter())
{
var engine=Resolver.GetService(typeof(ICompositeViewEngine))作为ICompositeViewEngine;
ViewEngineResult viewResult=engine.FindPartialView(ActionContext,viewName);
ViewContext ViewContext=新的ViewContext(ActionContext、viewResult.View、ViewData、TempData、sw、新的HTMLHelpOptions());
var t=viewResult.View.RenderAsync(viewContext);
t、 等待();
返回sw.GetStringBuilder().ToString();
}
}
大卫的成功归功于他
在Views-->Shared
文件夹中,我创建了一个新的Templates文件夹,在其中我向我的PersonViewModel
添加了一个简单的RegistrationTemplate.cshtml
View强类型的,如下所示:
@model MyWebProject.ViewModels.PersonViewModel
登记处
您好,@Model.FullName
最后一步是使我的控制器
继承自我的基本控制器
公共类MyController:BaseController
并创建如下内容:
public IActionResult Index()
{
var模型=新PersonViewModel();
model.FirstName=“Frank”;
model.LastName=“安德伍德”;
var emailbody=base.RenderPartialViewToString(“模板/注册模板”,模型);
返回视图();
}
当然,上面的示例是无用的,因为我对变量emailbody
不做任何处理,但其目的是展示如何使用它
此时,我可以(例如)调用EmailService
并传递emailbody
:
\u emailService.SendEmailAsync(“test@test.com“,”注册“,电子邮件正文);
我不确定这是否适合您当前的任务。2016年7月更新
在以下版本1.0.0
,RC2
谁的目标是aspnetcore RC2,此片段可能会帮助您:
- 创建一个单独的服务,这样,如果您不在控制器上下文中(例如,从命令行或队列运行程序等),您就可以使用它
- 在
类中的IoC容器中注册此服务启动
//使用模型
字符串html=view.Render(“电子邮件/测试”,新产品(“苹果”);
//使用字典
var viewData=新字典();
viewData[“名称”]=“123456”;
字符串html=view.Render(“电子邮件/测试”,viewData);
笔记
Razor中的链接呈现为相对URL,因此这在外部视图(如电子邮件等)上不起作用
现在,我正在控制器上生成链接,并通过ViewModel将其传递给视图
信用
源代码是从中提取的(感谢@pholly):)今天我已经完成了我的库,它可以解决您的问题。您可以在ASP.NET之外使用它,因为它对它没有依赖关系 例如:
string content = "Hello @Model.Name. Welcome to @Model.Title repository";
var model = new
{
Name = "John Doe",
Title = "RazorLight"
};
var engine = new RazorLightEngine();
string result = engine.ParseString(content, model);
//Output: Hello John Doe, Welcome to RazorLight repository
更多信息:为了改进@vlince答案(这对我来说不是现成的),以下是我所做的: 1-创建其他控制器将继承的基本控制器
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ViewEngines;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Mvc.Rendering;
using System.IO;
namespace YourNameSpace
{
public class BaseController : Controller
{
protected ICompositeViewEngine viewEngine;
public BaseController(ICompositeViewEngine viewEngine)
{
this.viewEngine = viewEngine;
}
protected string RenderViewAsString(object model, string viewName = null)
{
viewName = viewName ?? ControllerContext.ActionDescriptor.ActionName;
ViewData.Model = model;
using (StringWriter sw = new StringWriter())
{
IView view = viewEngine.FindView(ControllerContext, viewName, true).View;
ViewContext viewContext = new ViewContext(ControllerContext, view, ViewData, TempData, sw, new HtmlHelperOptions());
view.RenderAsync(viewContext).Wait();
return sw.GetStringBuilder().ToString();
}
}
}
}
2-继承基本控制器并调用方法
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ViewEngines;
namespace YourNameSpace
{
public class YourController : BaseController
{
public YourController(ICompositeViewEngine viewEngine) : base(viewEngine) { }
public string Index(int? id)
{
var model = new MyModel { Name = "My Name" };
return RenderViewAsString(model);
}
}
}
我找到了这个讨论它的帖子: 线程中的某个人在此处创建了一个示例服务: 经过反复试验之后,我能够精简服务,这样它只需要一个有效的
HttpContext
和一个ViewEngine
,并且我添加了一个不需要模型的重载。视图是相对于应用程序根目录的(它们不必位于Views
文件夹中)
您需要注册s
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ViewEngines;
namespace YourNameSpace
{
public class YourController : BaseController
{
public YourController(ICompositeViewEngine viewEngine) : base(viewEngine) { }
public string Index(int? id)
{
var model = new MyModel { Name = "My Name" };
return RenderViewAsString(model);
}
}
}
public static class PartialViewToString
{
public static async Task<string> ToString(this PartialViewResult partialView, ActionContext actionContext)
{
using(var writer = new StringWriter())
{
var services = actionContext.HttpContext.RequestServices;
var executor = services.GetRequiredService<PartialViewResultExecutor>();
var view = executor.FindView(actionContext, partialView).View;
var viewContext = new ViewContext(actionContext, view, partialView.ViewData, partialView.TempData, writer, new HtmlHelperOptions());
await view.RenderAsync(viewContext);
return writer.ToString();
}
}
}
public async Task<IActionResult> Index()
{
return await PartialView().ToString(ControllerContext)
}
public static async Task<string> ViewToString(this PartialViewResult partialView, Controller controller)
{
using (var writer = new StringWriter())
{
var services = controller.ControllerContext.HttpContext.RequestServices;
var viewEngine = services.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine;
var viewName = partialView.ViewName ?? controller.ControllerContext.ActionDescriptor.ActionName;
var view = viewEngine.FindView(controller.ControllerContext, viewName, false).View;
var viewContext = new ViewContext(controller.ControllerContext, view, partialView.ViewData, partialView.TempData, writer, new HtmlHelperOptions());
await view.RenderAsync(viewContext);
return writer.ToString();
}
}