2009-05-25 12 views
7

Tenemos un montón de entidades de dominio que deben representarse en un formato html, que muestra sus detalles en una ventana emergente.Rendering C# Objects to Html

estaría contento de hacer algo como esto:

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

pero mi principal problema es cómo hacer estas cosas por detrás. tengo 3 respuestas diferentes:

1. Render Por Código:

que simplemente hay que escribir el código para renderizar el código HTML dentro del Método ToHTML (C#) - el problema es que es demasiado estática. si desea mover un poco el encabezado hacia el centro, debe cambiar el código. además, es muy difícil leer sangría Html en C#.

2. El uso de XSL:

XSL archivos pueden administrar fácilmente la plantilla HTML y mediante XSLT puedo transformar archivo XML en el lugar adecuado de los documentos. el analizador ya escrito por otra persona (solo necesita aprender la sintaxis) ** para esto necesitaremos que cada objeto se pueda serializar a Xml. y si el objeto cambió -> se cambiará el Xml -> el xslt también se debe cambiar ** esto también me dará la opción de aplicar sangría al html fácilmente, por ejemplo: agregar capacidades css y \ o cambiar el diseño html

3. utilizar otro motor de plantilla:

Escribir mi propia C# -> HTML plantilla de motor por lo que leerá la plantilla de archivo (* .template) e insertará la propiedad adecuada en el lugar correcto de la plantilla usando la reflexión. ** en esta solución tenemos muchos problemas que podemos pensar, por ejemplo: ¿cómo debería ser la sintaxis? ¿esto está bien? % Nombre%% Descripción% y cómo podemos gestionar las matrices? ** tal vez podamos usar un motor existente (Brail o T4-Templating)?

¿Qué prefieres? ¿conoces un buen motor? por el momento prefiero la segunda solución, pero va a ser muy lenta.

gracias

Respuesta

3

No puedo estar más de acuerdo con John Feminella. Integrar la representación Html directamente en las entidades de su dominio es una contaminación horrible de su dominio con una preocupación completamente arbitraria y externa. Como dijo John, hará que sus entidades sean muy frágiles al hacer eso, y romperá ambas reglas críticas: separación de preocupaciones y responsabilidad única.

De las elecciones que haya realizado, el # 3 es el más cercano a una forma adecuada de hacerlo. No necesita escribir su propio motor de plantillas. Hay muchos motores de plantillas libres y listos para usar en la red que harán el trabajo de forma más que adecuada (NVelocity, StringTemplate, Brail, etc.)

Mantenga la representación donde corresponde ... en su presentación/vista y no contamine su dominio con preocupaciones de mayor nivel.

3

Este es el trabajo de su punto de vista, no sus controladores y modelos. Como sospecha, el uso del método (1) hará que sus cambios sean muy frágiles. En su lugar, escriba un fragmento de vista para cada forma en que desea representar una entidad de dominio particular. Luego, simplemente ingrese las vistas apropiadas para construir su página final.

2

Sinceramente prefiero el método A. El HTML ya es un estándar, por lo que no debe darse demasiada importancia con los formatos intermedios como XML (a través de XSL - método 2) o un formato personalizado (método 3).

Si escribe en/para ASP.NET MVC, puede construir un .ASCX (control de usuario) que acepte un objeto de su tipo y represente el HTML apropiado. Y no obtienes la desagradable mella C# y no resaltas ni autocompletas.

También puede escribir varias vistas de usuario para acomodar diferentes escenarios para un tipo de objeto.

+0

No estoy trabajando en un equipo web, estoy renderizando objects-as-html y enviándoselo a cualquier otra persona, quien puede usar esto en wpf \ palm \ web-site u otra tecnología, así que supongo que ascx no es bueno para mí. – rabashani

+0

En ese caso, puede serializarlo en formato JSON y enviarlo para que lo usen otros usuarios. – shahkalpesh

+0

todavía no es lo suficientemente bueno. Quiero que todos obtengan la misma interfaz de usuario. no manejan la lógica de renderizado por sí mismos. – rabashani

0

Existe un motivo por el que no desea crear un archivo .ascx de control personalizado que tome objetos de entidades de dominio como argumento y luego puede hacer la interfaz gráfica de usuario de la manera que desee. De esta forma, puede agregar dinámicamente los controles a la página y simplemente establecer una propiedad para rellenarlos.

Editar 1: Simplemente represente el control en HTMLTextWriter en lugar de colocarlo en la página.

 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(); 

salida

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

supuesto utilizar el control personalizado en lugar de un construido en control, pero esto fue una demostración rápida y fácil.

+0

. No estoy trabajando en un equipo web, estoy renderizando objects-as-html y enviándolos a cualquier otra persona que puede usar esto en wpf \ palm \ web-site u otra tecnología, por lo que supongo que ascx no es bueno para mí – rabashani

+0

Pero aún puede entregar su control a un escritor de texto html y pasar ese valor. De esta forma, puede diseñar y mantener un archivo ascx para mayor comodidad y simplicidad en comparación con el de escribir su propio motor de plantilla o xsl. – benjamin

+0

agregó un código a mi respuesta para mostrar cómo ascx podría funcionar bien. – benjamin

5

Una vez tuve la necesidad de presentar una colección de cualquier tipo en una tabla Html. Creé un método de extensión en IEnumerable <T> que tenía sobrecargas para css y similares. Se puede ver mi blog sobre él aquí:

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

Se utiliza la reflexión para obtener todas las propiedades del objeto, y hace una pequeña mesa. Ve si eso funcionaría para ti.

[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(); 
} 
0

Personalmente, me combino método de dos y tres: Hay que crear un documento XML utilizando la reflexión genérica, por ejemplo:

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

y utilizar una hoja de estilo XSTL para crear el HTML real de esta.

1

Después de investigar un poco hice mi propia función para convertir Any Object toHtmlString.

VB .Net Código:

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() 

obtendrá el nombre de la propiedad y el valor de un objeto en particular. puede manipular html según su