- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
此处考虑 CMS 用例。想象一下这样的 View :
// /Home/Index.cshtml
@model object
@{
var str = "My <b>CMS</b> content with razor code: @Html.ActionLink(\"Click\", \"Home\")"
}
@Html.MyCustomRazorStringRenderer(Model)
预期输出:
My <b>CMS</b> content with razor code: <a href="/Home/Click">Click</a>
MyCustomRazorStringRenderer 是什么样子的?它必须以某种方式做某事。喜欢创建/使用 ViewContext 并呈现它(如此处:Render a view as a string),但我无法完全理解它。
最佳答案
您必须创建一个包含 extension method 的静态类.该方法必须返回 MvcHtmlString 的一个实例包含安全呈现的 HTML 输出。话虽如此,正确地访问 renderedOutput
意味着“劫持”Razor 渲染器,这很棘手。
您真正在做的是在其预期环境之外使用 Razor 引擎,此处对其进行了描述:http://vibrantcode.com/blog/2010/7/22/using-the-razor-parser-outside-of-aspnet.html
这里也有很多不错的信息,我从中得到了很多灵感来写下面的代码:http://www.codemag.com/article/1103081
这些类是这方面的起点:RazorEngineHost , RazorTemplateEngine , CSharpCodeProvider , HtmlHelper .
工作代码
我实际上得到了一个几乎可以工作的版本,但意识到这是一件非常徒劳的事情。 Razor 引擎通过生成代码来工作,然后必须使用 CSharpCodeProvider
对其进行编译。这需要时间。很多时间!
唯一可行且有效的方法是将模板字符串保存在某处,预编译它们,并在调用时调用这些编译后的模板。这使得它基本上对您所追求的毫无用处,因为这正是带有 Razor 的 ASP.NET MVC 所擅长的——将 View 保存在一个好的位置,预编译它们,并在引用时调用它们。 更新:好吧,也许大量的缓存可能会有所帮助,但我实际上仍然不推荐这种解决方案。
生成代码时,Razor 发出对 this.Write
和 this.WriteLiteral
的调用。因为 this
是一个继承自您自己编写的基类的对象,所以由您提供 Write
和 WriteLiteral
的实现。
如果您在模板字符串中使用任何其他 HtmlHelper
扩展,则需要为所有这些扩展包含程序集引用和命名空间导入。下面的代码添加了最常见的代码。由于匿名类型的性质,它们不能用于模型类。
MyRazorExtensions 类
public static class MyRazorExtensions
{
public static MvcHtmlString RazorEncode(this HtmlHelper helper, string template)
{
return RazorEncode(helper, template, (object)null);
}
public static MvcHtmlString RazorEncode<TModel>(this HtmlHelper helper, string template, TModel model)
{
string output = Render(helper, template, model);
return new MvcHtmlString(output);
}
private static string Render<TModel>(HtmlHelper helper, string template, TModel model)
{
// 1. Create a host for the razor engine
// TModel CANNOT be an anonymous class!
var host = new RazorEngineHost(RazorCodeLanguage.GetLanguageByExtension("cshtml");
host.DefaultNamespace = typeof(MyTemplateBase<TModel>).Namespace;
host.DefaultBaseClass = nameof(MyTemplateBase<TModel>) + "<" + typeof(TModel).FullName + ">";
host.NamespaceImports.Add("System.Web.Mvc.Html");
// 2. Create an instance of the razor engine
var engine = new RazorTemplateEngine(host);
// 3. Parse the template into a CodeCompileUnit
using (var reader = new StringReader(template))
{
razorResult = engine.GenerateCode(reader);
}
if (razorResult.ParserErrors.Count > 0)
{
throw new InvalidOperationException($"{razorResult.ParserErrors.Count} errors when parsing template string!");
}
// 4. Compile the produced code into an assembly
var codeProvider = new CSharpCodeProvider();
var compilerParameters = new CompilerParameters { GenerateInMemory = true };
compilerParameters.ReferencedAssemblies.Add(typeof(MyTemplateBase<TModel>).Assembly.Location);
compilerParameters.ReferencedAssemblies.Add(typeof(TModel).Assembly.Location);
compilerParameters.ReferencedAssemblies.Add(typeof(HtmlHelper).Assembly.Location);
var compilerResult = codeProvider.CompileAssemblyFromDom(compilerParameters, razorResult.GeneratedCode);
if (compilerResult.Errors.HasErrors)
{
throw new InvalidOperationException($"{compilerResult.Errors.Count} errors when compiling template string!");
}
// 5. Create an instance of the compiled class and run it
var templateType = compilerResult.CompiledAssembly.GetType($"{host.DefaultNamespace}.{host.DefaultClassName}");
var templateImplementation = Activator.CreateInstance(templateType) as MyTemplateBase<TModel>;
templateImplementation.Model = model;
templateImplementation.Html = helper;
templateImplementation.Execute();
// 6. Return the html output
return templateImplementation.Output.ToString();
}
}
MyTemplateBase<> 类
public abstract class MyTemplateBase<TModel>
{
public TModel Model { get; set; }
public HtmlHelper Html { get; set; }
public void WriteLiteral(object output)
{
Output.Append(output.ToString());
}
public void Write(object output)
{
Output.Append(Html.Encode(output.ToString()));
}
public void Write(MvcHtmlString output)
{
Output.Append(output.ToString());
}
public abstract void Execute();
public StringBuilder Output { get; private set; } = new StringBuilder();
}
test.cshtml
@using WebApplication1.Models
<h2>Test</h2>
@Html.RazorEncode("<p>Paragraph output</p>")
@Html.RazorEncode("<p>Using a @Model</p>", "string model" )
@Html.RazorEncode("@for (int i = 0; i < 100; ++i) { <p>@i</p> }")
@Html.RazorEncode("@Html.ActionLink(Model.Text, Model.Action)", new TestModel { Text = "Foo", Action = "Bar" })
更新
“实时”执行此操作 - 如果您不大量使用缓存,让 Razor 为每个页面加载编译和运行显然太慢,但如果您分解我的代码片段并让您的 CMS 自动请求重新编译每当页面内容发生变化时,您都可以在这里做一些非常有趣的事情。
关于c# - 在 View 中渲染包含 Razor 代码的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35913730/
我的公司正在尝试制定一些关于使用哪种技术来构建应用程序的指南。在做我的研究时,我感到很困惑。 似乎有 3 种 ASP.NET 技术。 MVC Razor Razor 页 MVC 对我来说相当清楚,因为
我正在尝试使用 Razor(来自预览版)将 MVC 项目升级到 Beta,现在我遇到了 Razor 没有进入它用来访问的登录 View 的奇怪现象(当有人要求执行需要授权的操作时)。 我的网络配置有
我想在 Razor 页面中包含一个类型化的模型子页面。我知道 SS 与 MVC Razor 不同。这样做的方式可能有些不同。 到目前为止,这就是我想出来的(看起来很丑,知道......): /
我在 Views 的同一个子文件夹中有两个 cshtml 文件。其中一个模板旨在包含另一个模板。我试图做到这一点,如下所示: 主模板: @Html.Partial("~/View
尝试通过部分将模型对象呈现为 JSON 结构,如下所示: @if( Model.IsEmpty ) { @( Model.UseNull ? "null" : "" ) } else {
现在我有下一个并且它有效 @foreach (TestLogs.Repository.DatabaseModel.Platforms CurrentPlatform in Model.Appl
我想知道如何在 Razor Pages 2.1 中创建和分配角色。应用。 我已经找到了如何为 MVC 应用程序( How to create roles in asp.net core and ass
我正在使用 Razor Engine from CodePlex在控制台应用程序中。当我在 VS 2010 IDE 中以 Debug模式运行时,一切正常。从 shell 来看,即使是上述 CodePl
我正在学习 ServiceStack razor 并希望更好地使用它(一般是 ServiceStack),但我无法让智能感知在模型上工作(通过继承指令) 这是我到目前为止的尝试:http://www.
如何在 Razor 辅助方法中包含不间断空格 ( )?这是有问题的助手: @helper RenderClipResult(Clip clip, IList searchTerms) {
关闭。这个问题需要更多focused .它目前不接受答案。 想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post . 6年前关闭。 Improve this questi
我有一些 Razor 页面,其中包含大量条件逻辑、循环、部分 View 等。保持输出标记在语义上正确很容易,但使用正确的缩进和换行符对其进行格式化则更困难。我怎样才能在运行时自动执行此操作?有模块或
我有: @: 但它呈现为 ...lesson_icon/d40d2ff2-d06b-4fd8-80a0-0ed31bbc04eb%20.png 如何去掉.png前面的%20? 最佳答案 文件扩展名前
我有 6 个相同内容类型“新闻”的项目,在每个项目中我都有一个字段 newsIntro。我想将特定页面中的字段放在另一个页面上,因此我需要定位特定字段,因此它可能是节点 1702 上的 newsInt
是否有任何支持自动完成的 Razor 模板 (.cshtml) 的轻量级编辑器? 或任何支持 Razor 自动完成的 Notepad++、Sublime Text 2 等插件? 最佳答案 自上次测试版
有没有办法在 Razor View 引擎中创建类似的函数? @{ View.Title = "Clients"; private string GetRowClassName(RowS
我有一个名为 item 的对象,item 有一个属性 itemId。我正在尝试建立一个包含 itemId 后跟 .html 的网址...所以它看起来像“myNiftyItem-123456.html”
我想知道如何在 Razor Pages (Page.cshtml) 中获取路由值。 前任。https://localhost:44320/AdminPanel/Admins如果我使用 MVC,我会将这
如何在 F# 项目中使用 ServiceStack.Razor? 我添加了对 ServiceStack.Razor 的引用(这似乎在 Windows 上没有问题,但出于某种原因在 Mac 上的 Mon
通过Ctrl+E、D格式化这部分代码: if (row % 3 == 0) { @: } 给我: if (row % 3 == 0) { @:
我是一名优秀的程序员,十分优秀!