将C#对象渲染为Html

时间:2009-05-25 21:57:44

标签: c# html rendering template-engine

我们有一堆域实体应该呈现为html格式,在弹出窗口中显示它们的详细信息。

我很乐意做这样的事情:

Product product = new Product(...);
product.ToHtml();  // or: HtmlRenderer.Render(Product);

但我的主要问题是如何从后面做这些事情。 我有3个不同的答案:

1。按代码渲染:

我可以简单地编写用于在ToHtml方法(C#)中呈现Html的代码 - 问题在于它静态。如果你想将标题移动到中间,你应该改变代码。 而且,在C#中读取Html缩进非常困难。

2。使用XSL:

XSL文件可以轻松管理Html模板并使用XSLT我可以将XML文件转换到文档的正确位置。 解析器已经由别人编写(只需要学习语法) **为此,我们需要每个对象都可以序列化为Xml。如果对象发生了变化 - > Xml将被更改 - > xslt也需要改变 **这也可以让我选择简单地缩进html例如:添加css功能和\或更改html设计

第3。使用其他模板引擎:

写我自己的C# - > Html模板引擎,因此它将从文件(* .template)中读取模板,并使用反射将正确的属性插入模板的正确位置。 **在这个解决方案中,我们可以考虑许多问题,例如:语法应该如何? 这件事好吗? %名称%%说明% 以及我们如何处理数组? **也许我们可以使用现有的引擎(Brail或T4-Templating)?

你更喜欢什么? 你知道一个好引擎吗? 现在我更喜欢第二种解决方案,但它会很慢。

感谢

7 个答案:

答案 0 :(得分:5)

我曾经需要将任何类型的集合呈现给Html表。我在IEnumerable< T>上创建了一个扩展方法。有css等过载。你可以在这里看到我的博客文章:

http://crazorsharp.blogspot.com/2009/03/cool-ienumberable-extension-method_25.html

它使用反射来获取对象的所有属性,并呈现一个漂亮的小表。看看这对你有用。

[System.Runtime.CompilerServices.Extension()]
public string ToHtmlTable<T>(IEnumerable<T> list, string propertiesToIncludeAsColumns = "")
{
    return ToHtmlTable(list, string.Empty, string.Empty, string.Empty, string.Empty, propertiesToIncludeAsColumns);
}

[System.Runtime.CompilerServices.Extension()]
public string ToHtmlTable<T>(IEnumerable<T> list, string tableSyle, string headerStyle, string rowStyle, string alternateRowStyle, string propertiesToIncludeAsColumns = "")
{
    dynamic result = new StringBuilder();
    if (String.IsNullOrEmpty(tableSyle)) {
        result.Append("<table id=\"" + typeof(T).Name + "Table\">");
    } else {
        result.Append((Convert.ToString("<table id=\"" + typeof(T).Name + "Table\" class=\"") + tableSyle) + "\">");
    }

    dynamic propertyArray = typeof(T).GetProperties();

    foreach (object prop in propertyArray) {
       if (string.IsNullOrEmpty(propertiesToIncludeAsColumns) || propertiesToIncludeAsColumns.Contains(prop.Name + ",")) {
        if (String.IsNullOrEmpty(headerStyle)) {
            result.AppendFormat("<th>{0}</th>", prop.Name);
        } else {
            result.AppendFormat("<th class=\"{0}\">{1}</th>", headerStyle, prop.Name);
        }
      }
    }

    for (int i = 0; i <= list.Count() - 1; i++) {
        if (!String.IsNullOrEmpty(rowStyle) && !String.IsNullOrEmpty(alternateRowStyle)) {
            result.AppendFormat("<tr class=\"{0}\">", i % 2 == 0 ? rowStyle : alternateRowStyle);

        } else {
            result.AppendFormat("<tr>");
        }
        foreach (object prop in propertyArray) {
            if (string.IsNullOrEmpty(propertiesToIncludeAsColumns) || propertiesToIncludeAsColumns.Contains(prop.Name + ",")) {
                object value = prop.GetValue(list.ElementAt(i), null);
                result.AppendFormat("<td>{0}</td>", value ?? String.Empty);
            }
        }
        result.AppendLine("</tr>");
    }

    result.Append("</table>");

    return result.ToString();
}

答案 1 :(得分:3)

这是您视图的工作,而不是您的控制器或模型。正如您所怀疑的那样,使用方法(1)会使您的更改变得非常脆弱。相反,为您想要呈现特定域实体的每种方式编写视图片段。然后只需拉入相应的视图即可构建最终页面。

答案 2 :(得分:3)

我对John Feminella表示赞同。将Html渲染直接集成到您的域实体中是对您的域的可怕污染,具有完全随意和外部的关注。就像约翰所说,通过这样做,你将使你的实体变得非常脆弱,并打破这两个关键规则:分离关注和单一责任。

根据您提供的选择,#3最接近合适的方式。您无需编写自己的模板引擎。网上有大量免费和现成的模板引擎,可以完成更多的工作(NVelocity,StringTemplate,Brail等等)

在您的演示文稿/视图中继续渲染它所属的位置,并且不要在更高级别的问题上污染您的域名。

答案 3 :(得分:2)

我真的更喜欢方法A. HTML已经是一个标准,所以你不应该用XML等中间格式(通过XSL - 方法2)或自定义格式(方法3)打败自己。

如果在/为ASP.NET MVC编写,你可以构建一个.ASCX(用户控件)来接受你的类型的对象并呈现适当的HTML。而且你没有得到令人讨厌的C#缩进,没有突出显示也没有自动完成。

您还可以编写多个用户视图以适应一种对象类型的不同方案。

答案 4 :(得分:1)

经过一番研究后,我创建了自己的函数将Any Object转换为HTMLString。

VB .Net代码:

 Public Function ToHtmlString(ByVal fObj As Object) As String
    Dim pType = fObj.GetType()
    Dim props As IList(Of PropertyInfo) = pType.GetProperties()
    Dim value As Object = Nothing
    Dim htmlString As String = "<html><body><form>"

    For Each p In props
        value = p.GetValue(fObj, Nothing)
        If value <> Nothing Then
            htmlString += String.Format("<input type=""hidden"" name=""{0}"" id=""{0}"" value=""{1}""/>", p.Name, value)
        End If
    Next

    htmlString += "</form></body></html>"
    Return htmlString.ToString()

它将从特定对象获取属性名称和值。你可以根据你的

来操纵HTML

答案 5 :(得分:0)

您是否有理由不想创建自定义控件.ascx文件,该文件将域实体对象作为参数,然后您可以以任何方式创建gui。这样,您可以动态地将控件添加到页面,只需设置一个属性来填充它们。

编辑1: 只需将控件呈现给HTMLTextWriter,而不是将其放在页面上。

        StringBuilder outString = new StringBuilder();
        StringWriter outWriter = new StringWriter(outString);
        HtmlTextWriter htmlText = new HtmlTextWriter(outWriter);
        System.Web.UI.WebControls.Label lbl1 = new System.Web.UI.WebControls.Label();
        lbl1.Text = "This is just a test!";
        lbl1.ToolTip = "Really";
        lbl1.RenderControl(htmlText);
        ViewData["Output"] = outString.ToString();

输出

<span title="Really">This is just a test!</span>

当然使用自定义控件而不是内置控件,但这是一个快速简单的演示。

答案 6 :(得分:0)

就个人而言,我将第二种方法和第三种方法结合起来:只需使用反射创建一个通用的XML文档,比如说:

<object type="xxxx">
    <property name="ttt" value="vvv"/>
    ...
</object>

并使用XSTL样式表从中创建实际的HTML。