2015-11-14 75 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