【问题标题】:Replace items in html template by C# object property values用 C# 对象属性值替换 html 模板中的项目
【发布时间】:2011-03-06 18:03:18
【问题描述】:

1:我有一个带有一些占位符标记的 .html 文件。

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body>
   First Name : <FIRSTNAME/>   <br />
   Last Name:  <LASTNAME/>
</body>
</html>

2:我有一个类来保存从 db 返回的数据

public class Person
{
    public Person()
    {
    }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

3:PersonInfo.aspx 我用实际值替换占位符写出这个 .html。

public partial class PersonInfo : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Person per= new Person();
        per.FirstName = "Hello";
        per.LastName = "World";

        string temp = File.ReadAllText(Server.MapPath("~/template.htm"));
        temp = temp.Replace("<FIRSTNAME/>", per.FirstName);
        temp = temp.Replace("<LASTNAME/>", per.LastName);
        Response.Write(temp);
    }
}

4:PersonInfo.aspx 实际上是空的,因为我是从代码隐藏中注入 html。

当调用 PersonInfo.aspx 时,将显示占位符中具有适当值的 html 模板标记。还有机会我想在 html 电子邮件中发送最终标记(尽管这不是问题的一部分,因为我知道如何发送电子邮件)。

这是在我的 html 模板中填充值的最佳方式还是其他更好的选择?

注意:这是一个非常简单的示例。我的课程非常复杂,涉及对象作为属性,而且我的 html 模板有 40-50 个占位符。

所以我第 3 步中的代码需要 40-50 条替换语句。

如有任何疑问,请随时提出,并非常感谢任何意见。

【问题讨论】:

  • 您能否再解释一下您要寻找的最终结果是什么?这是某人正在浏览器中查看的动态网页,还是您正在尝试生成电子邮件内容?
  • 您使用的是有效的 XML 吗?
  • @Daniel,它既可以显示在页面上供用户打印,也可以通过单击按钮发送电子邮件。
  • 您是否完全使用网络表单?使用 ASP.NET MVC 和 Razor 视图引擎可以很容易地做到这一点,而且我 98% 确信有一种方法可以渲染它以获取最终的 HTML 内容以发送电子邮件。
  • @Daniel:是的,必须使用网络表单。

标签: c# asp.net html templates


【解决方案1】:

如果您的页面是有效的 XML(我猜它是基于示例),那么您可以将其解析为 XElement 并按节点名称进行后代搜索。您可能可以编写一个更高效的版本,但一个示例是:

.NET 3.5

    public void Page_Load(object sender, EventArgs e)
    {
        Person person = new Person { FirstName = "Hello", LastName = "World" };
        var dictionary = typeof(Person).GetProperties(BindingFlags.Public | BindingFlags.Instance)
            .ToDictionary(p => p.Name.ToUpperInvariant(), p => (p.GetValue(person, null) ?? string.Empty).ToString());
        var xe = XElement.Parse(File.ReadAllText(HttpContext.Current.Server.MapPath("~/template.htm")));
        foreach (var key in dictionary.Keys)
        {
            foreach (var match in xe.Descendants(key))
            {
                match.ReplaceAll(dictionary[key]);
            }
        }
    }

.NET 2.0 友好:

        var person = new Person();
        person.FirstName = "Hello"; 
        person.LastName = "World";
        var dictionary = new Dictionary<string, string>();
        foreach(var propertyInfo in typeof(Person).GetProperties(BindingFlags.Public|BindingFlags.Instance))
        {
            var elementName = propertyInfo.Name.ToUpperInvariant();
            var value = (propertyInfo.GetValue(person, null) ?? string.Empty).ToString();
            dictionary.Add(elementName,value);
        }
        var xml = new XmlDocument();
        xml.LoadXml(File.ReadAllText(HttpContext.Current.Server.MapPath("~/template.htm")));
        foreach(var key in dictionary.Keys)
        {
            var matches = xml.GetElementsByTagName(key);
            for(int i = 0; i<matches.Count;i++)
            {
                var match = matches[i];
                var textNode = xml.CreateTextNode(dictionary[key]);
                match.ParentNode.ReplaceChild(textNode, match);
            }
        }

【讨论】:

  • XSLT 也像 Avitus 所说的那样工作,但这有点取决于您是否了解它,并且可能比复制和粘贴需要更多时间
  • 我实际上想过使用 GetProperties 使用 Reflection 并获取 PropertyInfo.Name 并能够检索到。您是否使用 Lambda 表达式(即 3.0+)进行编码,因为我使用的是 .NET 2.0。虽然最终,我可能会转向 4.0,但现在 2.0 是我的框架。我将阅读有关 XElement 的更多信息并了解它的适用性。感谢您的代码-sn-p。
  • XElement 是 linq 的一部分,因此在 .NET 2.0 中也不可用。您可能需要考虑切换到 .NET 3.5 SP1,因为它使用与 .NET 2.0 相同版本的 CLR,并且易于升级,但提供了很多功能
  • 感谢 smartcaveman。我一定会试一试的。我在使用这种方法时可能会看到的一个潜在问题是我的属性应该与我的占位符命名完全相同,或者相反。由于此模板是现有模板,因此我必须检查是否可以在不影响正在使用它的其他部分的情况下对其进行修改。
【解决方案2】:

我会更改您的页面以使用 xslt。这是从数据库中替换事物的一种非常简单的方法。然后,您要做的唯一工作就是使用数据库中的数据制作 XML 文档。

【讨论】:

  • 我之前想过如果我能走那条路,那么我也将开始研究 XSLT/XML 表面。但在那种情况下,数据应该是 XML 格式的吧?因为我的数据不仅来自一个类或查询,而且我需要进行多次数据库调用来填充模板中的不同占位符。感谢您投入 2 美分。
  • 这将是我最终会采用的方式,但现在我将坚持使用现有模板。
【解决方案3】:

我会使用 SqlDataSource 和 Repeater 控件。它们使从数据库中提取数据变得非常容易,然后将其显示在页面上。您无需执行任何代码隐藏,因为一切都将由 .NET 为您处理。

您的数据源如下所示:

<asp:sqlDataSource ID="mySqlDataSource" SelectCommand="SELECT firstName, lastName FROM tablename" />

然后你需要一个可以使用返回的数据并将其显示在页面上的控件:

<asp:Repeater runat="server">
    <HeaderTemplate>
        <table>
    </HeaderTemplate>
    <ItemTemplate>
        <tr>
            <td>First Name: <%#Container.DataItem("firstName")%>"</td>
        </tr>
        <tr>
            <td>Last Name: <%#Container.DataItem("lastName")%></td>
        </tr>
    </ItemTemplate>
    <FooterTemplate>
        </table>
    </FooterTemplate>
</asp:Repeater>

编辑:

由于您不想使用数据源和数据绑定控件,我建议您使用XmlTextWriter 类。有一个very good tutorial here。与从单独的 HTML 文件中读取模板相比,这将使您更加灵活。

【讨论】:

  • @FreeAslnBeer:从没想过,但我必须看看它在我的情况下是否可行。感谢您的意见。
  • 我考虑了一下,似乎这不是一个选项,因为首先我不需要重复的东西,我也可以在 .aspx 标记中做同样的事情。而且我的数据不仅与一个数据源相关联,而且会有多个来源。
  • @gbs:我仍然认为我的解决方案是完全有效的。如果您能详细解释一下您的数据,那么我可以根据您的情况调整我的回复。
  • 我并不是说它不会起作用,它会起作用。在这种情况下,我认为没有必要使用Repeater 或任何DataBound 控件,因为这样我就可以简单地在.aspx 中完成这项工作。我没有使用 SqlDataSources 并且有单独的层来完成所有数据库工作。我有四个不同的存储过程,从不同的地方传递不同的参数,并用适当的值替换占位符。我想我可能还需要一些计算。所以我确定我不会得到 DataBoundControl 路由。
【解决方案4】:

由于您要生成电子邮件,请考虑使用MailDefinition.CreateMailMessage。您必须将占位符和替换值复制到 Dictionary 对象。

【讨论】:

    猜你喜欢
    • 2023-01-27
    • 2013-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-27
    • 2020-03-27
    • 1970-01-01
    • 2022-08-18
    相关资源
    最近更新 更多