2009-05-25 17 views
7

Abbiamo un gruppo di entità di dominio che dovrebbero essere renderizzate in un formato html, che mostra i loro dettagli in una finestra pop-up.Rendering di oggetti C# in HTML

Sarei felice di fare qualcosa di simile:

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

ma il mio problema principale è come fare questa roba da dietro. Ho 3 diverse risposte:

1. Render Per Codice:

posso semplicemente scrivere il mio codice per il rendering HTML all'interno del metodo ToHTML (C#) - il problema è che si tratta di troppo statico. se vuoi spostare un po 'l'intestazione verso il centro, devi cambiare il codice. inoltre, è molto difficile leggere il rientro Html in C#.

2. Utilizzando XSL:

XSL file possono facilmente gestire il template HTML e utilizzando XSLT posso trasformare file XML al posto giusto dei documenti. il parser già scritto da qualcun altro (solo bisogno di imparare la sintassi) ** per questo avremo bisogno che ogni oggetto possa serializzare su Xml. e se l'oggetto è cambiato -> l'Xml sarà cambiato -> anche il xslt deve essere cambiato ** questo mi darà anche la possibilità di indentare facilmente il codice HTML per esempio: aggiungere funzionalità css e \ o cambiare il design html

3. utilizzando altri template engine:

scrivere il mio C# -> Html modello del motore in modo che leggerà il modello da file (* .template) e inserirà il diritto di proprietà nel posto giusto di il modello usando la riflessione. ** in questa soluzione abbiamo molti problemi a cui possiamo pensare, ad esempio: come dovrebbe essere la sintassi? questa cosa è ok? % Nome%% Descrizione% e come possiamo gestire gli array? ** forse possiamo usare un motore esistente (Brail o T4-Templating)?

Cosa preferisci? conosci un buon motore? per ora preferisco la seconda soluzione, ma sarà molto lento.

grazie

risposta

3

Non posso essere più d'accordo con John Feminella. Integrare il rendering Html direttamente nelle entità del tuo dominio è un orrendo inquinamento del tuo dominio con una preoccupazione completamente arbitraria ed esterna. Come ha detto John, renderai le tue entità molto fragili facendo così, e infrangi entrambe le regole fondamentali: Separazione delle preoccupazioni e Responsabilità singola.

Dalle scelte che hai dato, # 3 è il più vicino a un modo appropriato per farlo. Non è necessario scrivere il proprio motore di template. Esistono numerosi motori di template gratuiti e pronti per l'uso in rete che svolgeranno il lavoro più che adeguatamente (NVelocity, StringTemplate, Brail, ecc. Ecc.)

Continua rendering in cui appartiene ... nella presentazione/visualizzazione e non inquinare il tuo dominio con problemi di livello superiore.

3

questo è il lavoro della vostra vista, non i controller o modelli. Come sospetti, l'uso del metodo (1) renderà le tue modifiche molto fragili. Invece, scrivi un frammento di visualizzazione per ogni modo in cui desideri rendere una particolare entità di dominio. Quindi basta inserire le viste appropriate per costruire la pagina finale.

2

Preferisco sinceramente il metodo A. L'HTML è già uno standard quindi non dovresti batterti troppo con formati intermedi come XML (tramite XSL - metodo 2) o un formato personalizzato (metodo 3).

Se si scrive in/per ASP.NET MVC, è comunque possibile creare un .ASCX (controllo utente) che accetta un oggetto di tipo e rende l'HTML appropriato. E non ottieni il brutto rientro in C# e nessuna evidenziazione o completamento automatico.

È anche possibile scrivere più viste Utente per gestire diversi scenari per un tipo di oggetto.

+0

Non lavoro in un team Web, sto rendendo object-as-html e li mando a chiunque altro - chi può usarlo in wpf \ palm \ web-site o altra tecnologia, quindi suppongo che ascx non sia buono per me. – rabashani

+0

In tal caso, è possibile serializzarlo in formato JSON e inviarlo per consentire ad altri utenti di utilizzarlo. – shahkalpesh

+0

ancora non abbastanza buono voglio che tutti ottengano la stessa interfaccia utente. non gestisce autonomamente la logica di rendering. – rabashani

0

C'è un motivo per cui non si desidera creare un file .ascx di controllo personalizzato che consideri l'oggetto di dominio oggetto come argomento e che quindi si possa creare la GUI in qualsiasi modo si desideri. In questo modo è possibile aggiungere in modo dinamico i controlli alla pagina e impostare semplicemente una proprietà per popolarli.

Modifica 1: È sufficiente eseguire il rendering su un HTMLTextWriter anziché posizionarlo sulla pagina.

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

uscita

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

Naturalmente utilizzare il controllo personalizzato al posto di una costruito nel controllo, ma questa è stata una dimostrazione semplice e veloce.

+0

Non lavoro in un team web, sto rendendo object-as-html e li mando a chiunque altro - chi può usare questo in wpf \ palm \ web-site o altra tecnologia, quindi suppongo che ascx non mi fa bene – rabashani

+0

Ma puoi ancora rendere il tuo controllo a un writer di testo html e passare quel valore. In questo modo puoi ancora progettare e mantenere un ascx per comodità e semplicità rispetto a quello di scrivere il tuo motore xsl o template. – benjamin

+0

aggiunto codice alla mia risposta per mostrare come ascx potrebbe funzionare bene. – benjamin

5

Una volta avevo bisogno di eseguire il rendering di una raccolta di qualsiasi tipo su una tabella Html. Ho creato un metodo di estensione su IEnumerable <T> che ha sovraccarico per css e simili. Si può vedere il mio blog post su di esso qui:

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

Si utilizza la riflessione per ottenere tutte le proprietà dell'oggetto, e rende un bel tavolo. Guarda se questo potrebbe funzionare per te.

[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, mi piacerebbe combinare metodo in due e tre: Basta creare un documento XML generico utilizzando la riflessione, dire:

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

e utilizzare un foglio di stile XSTL per creare il codice HTML vero e proprio da questo.

1

Dopo un po 'di ricerca ho creato la mia funzione per convertire Any Object inHtmlString.

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

otterrà il nome della proprietà e il valore da un particolare oggetto. puoi manipolare il codice HTML in base al tuo