Рендеринг объектов C# в Html

у нас есть куча объектов домена, которые должны быть отображены в формате html, который показывает их детали во всплывающем окне.

Я был бы рад сделать что-то вроде этого:

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

но моя главная проблема заключается в том, как это делать Сзади. У меня есть 3 разных ответа:

1. Рендеринг По Коду:

Я могу просто написать свой код для рендеринга Html внутри метода ToHtml (C#) - проблема в том, что это слишком статический. если вы хотите немного переместить заголовок в середину, вы должны изменить код. кроме того, очень трудно прочитать отступ Html В C#.

2. Использование XSL:

xsl-файлы могут легко управлять HTML-шаблоном и с помощью XSLT я могу преобразовать XML-файл в нужное место документов. парсер уже написан кем-то другим (просто нужно изучать синтаксис) ** для этого нам нужно, чтобы каждый объект можно сериализовать в Xml. и если объект изменен - > Xml будет изменен -> xslt также необходимо изменить ** это также даст мне возможность легко отступить html, например: добавление возможностей css иили изменить дизайн html

3. использование другого движка шаблонов:

напишите мой собственный C# -> html template Engine, чтобы он прочитал шаблон из файла (*.template) и вставит нужное свойство в нужное место шаблона, используя отражение. ** в это решение у нас есть много проблем, которые мы можем придумать, например: как должен быть синтаксис? это нормально? %Name% %описание% и как мы можем обрабатывать массивы? ** может быть, мы можем использовать существующий движок (Brail или T4-Templating)?

что вы предпочитаете? вы знаете хороший двигатель? пока я предпочитаю второе решение, но оно будет очень медленным.

спасибо

7 ответов


Я не могу согласиться с Джоном Feminella. Интеграция HTML-рендеринга непосредственно в объекты домена-это ужасное загрязнение вашего домена совершенно произвольной и внешней заботой. Как сказал Джон, сделав это, вы сделаете свои сущности очень хрупкими и нарушите оба критических правила: разделение забот и Единую ответственность.

из вариантов, которые вы дали, #3 ближе всего к соответствующему способу сделать это. Вам не нужно писать свой собственный шаблон двигатель. В сети есть много бесплатных и готовых шаблонных движков, которые сделают работу более чем адекватно (NVelocity, StringTemplate, Brail и т. д. так далее.)

продолжайте рендеринг, где он принадлежит...в вашей презентации / представлении, и не загрязняйте свой домен проблемами более высокого уровня.


когда-то мне нужно было отобразить коллекцию любого типа в таблицу Html. Я создал метод расширения на IEnumerable, который имел перегрузки для 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) сделает ваши изменения очень хрупкими. Вместо этого напишите фрагмент представления для каждого способа, в котором вы хотите отобразить определенную сущность домена. Затем просто потяните соответствующие представления, чтобы создать свою последнюю страницу.


Я искренне предпочитаю метод A. HTML уже является стандартом, поэтому вы не должны слишком сильно избивать себя промежуточными форматами, такими как XML (через XSL - Метод 2) или пользовательский формат (метод 3).

Если запись в / для ASP.NET MVC вы можете, однако, построить .ASCX (пользовательский элемент управления), который будет принимать объект вашего типа и отображать соответствующий HTML. И вы не получите неприятный отступ C# и никакой подсветки или автозаполнения.

вы также можете написать несколько пользовательских представлений для размещения различных сценариев для одного типа объекта.


после немного исследований я сделал свою собственную функцию для преобразования любого объекта toHtmlString.

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 на основе вашего


лично я бы объединил метод два и три: просто создайте общий XML-документ, используя отражение, скажем:

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

и используйте таблицу стилей XSTL для создания фактического HTML из этого.


почему вы не хотите создать пользовательский элемент управления .ascx-файл, который принимает объект объектов домена в качестве аргумента, а затем вы можете сделать gui любым способом. Таким образом, вы можете динамически добавлять элементы управления на страницу и просто устанавливать свойство для их заполнения.

Edit 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>

конечно, используйте свой пользовательский элемент управления вместо встроенного управления, но это была быстрая и простая демонстрация.