2015-11-14 14 views
1

任何人都有使用复杂模型和RazorEngine的经验吗?RazorEngine - 如何使用复杂的模型视图?

使用RazorEngine版本3.7.3来生成HTML,但遇到了我们所拥有的复杂模型视图的问题。看起来我们应该能够使用这些模板来让RazorEngine发现下面的SubSample,但是还没有找到正确的方式来告诉RazorEngine关于相关的cshtml文件。

在下面的示例中,我们正在寻找使用SubSample.cshtml文件的SubSample类的共享模板。从结果中可以看出,显示的是类名称空间(ReportSample.SubSample),而不是HTML数据行。

我们已经尝试过实现一个ITemplateManager,但是Resolve()永远不会被一个要求SubSample的键调用。还尝试过服务上的AddTemplate(),但仍然没有快乐。

下面是一个简化的示例模型来说明问题:

namespace ReportSample 
{ 
    public class SubSample 
    { 
     public string Name { get; set; } 
     public string Value { get; set; } 
    } 

    public class SampleModel 
    { 
     public SubSample SubSample { get; set; } 
    } 
} 

SampleModel.cshtml

@using ReportSample 
@*@model ReportSample.SampleModel*@ 
<table style="width: 7.5in" align="center"> 
    <tr> 
     <td align="center"> 
      <h1> 
       Sample Report 
      </h1> 
     </td> 
    </tr> 
    <tr> 
     <td> 
      <table style="width: 100%"> 
       <tr> 
        <td colspan="2"> 
         <b>Name:</b> @Model.SubSample.Name 
        </td> 
        <td colspan="2"> 
         <b>Value:</b> @Model.SubSample.Value 
        </td> 
       </tr> 
      </table> 
     </td> 
    </tr> 
    <tr> 
     <td align="center"> 
      <h1> 
       Sub-sample Data 
      </h1> 
     </td> 
     <td> 
      <table style="width: 100%"> 
       @Model.SubSample 
      </table> 
     </td> 
    </tr> 
</table> 

SubSample.cshtml

@model ReportSample.SubSample 
@using FSWebportal.Infrastructure.Mvc; 
<tr class="observation-row"> 
    <td class="observation-label"> 
     @model.Name 
    </td> 
    <td class="observation-view"> 
     @model.Value 
    </td> 
</tr> 

基本RazorEngine电话:

private void html_Click(object sender, EventArgs e) 
{ 
    var gen = new RazorEngineGenerator(); 
    var cshtmlTemplate = File.ReadAllText("Sample.cshtml"); 

    var sample = new SampleModel() { SubSample = new SubSample() { Name = "name", Value = "value" } }; 

    var html = gen.GenerateHtml(sample, cshtmlTemplate); 
} 

public string GenerateHtml<T>(T model, string cshtmlTemplate) 
{ 
    var config = new TemplateServiceConfiguration(); 
    using (var service = RazorEngineService.Create(config)) 
    { 
     return service.RunCompile(cshtmlTemplate, "", typeof(T), model); 
    } 
} 

样本HTML输出:

样本报告

名称:名称 值:

子采样数据

ReportSample.SubSample

回答

0

对不起,但我不认为我完全理解你的问题,但我有一个小想法,你正在尝试做什么......

我想你想要的是搜索部分模板(使用@包括)!

using RazorEngine; 
using RazorEngine.Templating; 
using System; 

namespace TestRunnerHelper 
{ 
    public class SubModel 
    { 
     public string SubModelProperty { get; set; } 
    } 

    public class MyModel 
    { 
     public string ModelProperty { get; set; } 
     public SubModel SubModel { get; set; } 
    } 

    class Program 
    { 

     static void Main(string[] args) 
     { 
      var service = Engine.Razor; 
      // In this example I'm using the default configuration, but you should choose a different template manager: http://antaris.github.io/RazorEngine/TemplateManager.html 
      service.AddTemplate("part", @"my template"); 
      // If you leave the second and third parameters out the current model will be used. 
      // If you leave the third we assume the template can be used for multiple types and use "dynamic". 
      // If the second parameter is null (which is default) the third parameter is ignored. 
      // To workaround in the case you want to specify type "dynamic" without specifying a model use Include("p", new object(), null) 
      service.AddTemplate("template", @"<h1>@Include(""part"", @Model.SubModel, typeof(TestRunnerHelper.SubModel))</h1>"); 
      service.Compile("template", typeof(MyModel)); 
      service.Compile("part", typeof(SubModel)); 
      var result = service.Run("template", typeof(MyModel), new MyModel { ModelProperty = "model", SubModel = new SubModel { SubModelProperty = "submodel"} }); 
      Console.WriteLine("Result is: {0}", result); 
     } 
    } 
} 

我加入文档此位置:https://antaris.github.io/RazorEngine/LayoutAndPartial.html

但是我觉得做@Model.SubSample工作是可能的,你可以更改子样本属性为TemplateWriter类型或使子样本类实现IEncodedString 。但我认为你应该首先考虑部分模板!

+0

我看到了你的代码,并根据代码写了一个工作单元测试。一个建议:使用“@ Model.SubModelProperty”副本“我的模板”作为“部分”,使其清晰可以引用SubModel。 – Brett

+0

我们试图避免使用'@include'语法。我们有很多chtml文件已被MVC代码使用,所以使用'@include'意味着必须预先解析代码才能添加'@include'。我们希望得到引擎来发现适当的模板,类似于MVC如何发现共享模板。 – Brett

+0

RazorEngine目前不支持“神奇”发现引擎。正如问题中所提到的,您只能通过修改模型而不是模板来实现解决方法(更改属性的类型或使它们(此处为SubModel类)实现IEncodedString)。 – matthid