2015-09-05 37 views
14

Mi sembra che ci siano importanti modifiche in TagBuilder a partire da beta7 senza menzione nel repository annunci.TagBuilder InnerHtml in ASP.NET 5 MVC 6

In particolare .ToString non esegue più il tagbuilder, ma restituisce solo il nome del tipo. in precedenza abbiamo potuto fare cose come questa all'interno delle nostre estensioni HtmlHelper per costruire gli elementi HTML nidificati:

var li = new TagBuilder("li"); 
li.AddCssClass("inactive"); 
var span = new TagBuilder("span"); 
span.SetInnerText(somestring); 
li.InnerHtml = span.ToString(); 

.innerHTML ora non accetta più stringa perché è ormai IHtmlContent

ma dato .ToString() doesn' t rendono il tag questo non funziona neanche:

li.InnerHtml = new HtmlString(span.ToString()) 

si limita rende come "Microsoft.AspNet.Mvc.Rendering.TagBuilder", il nome del tipo.

Non vedo alcun nuovo metodo su TagBuilder per fornire la funzionalità necessaria. Cosa mi manca? Come posso creare un html nidificato complesso con TagBuilder ora?

+0

'TagBuilder' implementa' IHtmlContent', quindi è possibile assegnare direttamente TagBuilder a 'li.InnerHtml'? – fiat

risposta

13

Poiché TagBuilder ora implementa IHtmlContent, dovrebbe essere possibile utilizzarlo direttamente, senza eseguire .ToString().

var li = new TagBuilder("li"); 
li.AddCssClass("inactive"); 
var span = new TagBuilder("span"); 
span.SetInnerText(somestring); 
li.InnerHtml = span; 

Il vero problema con l'attuale implementazione in Beta 7 è che non esiste un modo semplice per aggiungere due contenuti tag bambino Builder per un genitore uno. È possibile seguire la discussione su GitHub.

L'attuale proposta è di rendere InnerHtml non assegnabile, ma supportare invece Append. Questo obiettivo è implementato in Beta 8.

La soluzione in Beta 7 è chiamare parent.WriteTo con un StringWriter per convertirlo in un string.

+2

Avrei detto che il vero problema era la grande quantità di codice MVC3 + che utilizzava 'TagBuilder.ToString()' nei metodi personalizzati 'HtmlHelper' e ora è completamente danneggiato. È così radicale voler ottenere una stringa HTML da una classe che, ehm, costruisca stringhe HTML? – Sam

+3

MVC 6 è una bestia completamente diversa da MVC 5 e precedenti. La retrocompatibilità non è mai stata una priorità. La differenza è paragonabile a quella tra WebForms e MVC (vasta esagerazione - lo so). Non vedrai molti progetti migrati. MVC 6 è più mirato verso nuovi progetti e rework completi. –

+2

Apprezzo questo, ma sospetto che molte di queste persone https://github.com/search?l=csharp&q=TagBuilder+HtmlHelper&type=Code&utf8=✓ stiano per ottenere uno shock violento quando migrano il loro codice componente riusabile e silenziosamente fallisce su di loro. Questa implementazione 'ToString()' viola il Principio della Minima Sorpresa e rende la migrazione molto più difficile, senza una buona ragione (diversa da "Pensiamo che le persone non dovrebbero farlo"). – Sam

2

Beta 8 ha risolto questo problema aggiungendo un metodo Append() per contrassegnare gli helper.

Per beta 7 la soluzione sarebbe utilizzare la classe BufferedHtmlContent(), ma dal momento che non è accessibile, è necessario eseguire un lavoro aggiuntivo.

private class MyBufferedHtmlContent : IHtmlContent 
{ 
    internal List<IHtmlContent> Entries { get; } = new List<IHtmlContent>(); 

    public MyBufferedHtmlContent Append(IHtmlContent htmlContent) 
    { 
     Entries.Add(htmlContent); 
     return this; 
    } 

    public void WriteTo(TextWriter writer, IHtmlEncoder encoder) 
    { 
     foreach (var entry in Entries) 
     { 
      entry.WriteTo(writer, encoder); 
     } 
    } 
} 

Usage:

TagBuilder firstChild = new TagBuilder("input"); 
firstChild.MergeAttribute("type", "hidden"); 
firstChild.MergeAttribute("name", "Ids"); 
firstChild.TagRenderMode = TagRenderMode.SelfClosing; 

TagBuilder secondChild = new TagBuilder("input"); 
secondChild.MergeAttribute("type", "hidden"); 
secondChild.MergeAttribute("name", "Ids"); 
secondChild.TagRenderMode = TagRenderMode.SelfClosing; 

var innerHtml = new MyBufferedHtmlContent(); 
innerHtml.Append(firstChild); 
innerHtml.Append(secondChild); 
TagBuilder parent = new TagBuilder("div"); 
parent.InnerHtml = innerHtml; 
+0

http://imgur.com/L0neS57 ... InnerHtml non ha setter ... – Jack

+0

Controlla la tua versione beta. Questo è per la beta 7. –

12

Utilizzando MVC 6, al momento della scrittura, Tagbuiler.InnerHtml ha infatti alcun setter più. Ha alcuni metodi invece di aggiungere l'elemento. Per esempio si potrebbe scrivere:

var container = new TagBuilder("div"); 
var input = new TagBuilder("input"); 

container.InnerHtml.AppendHtml(input); 
2

@Memet Olsen

Tutti i miei TagHelpers personalizzati ruppe con un aggiornamento a 4.6.1 (1.0.0-RC2). InnerHtml.Append() non accetterà più un TagBuilder.

Invece, il metodo AppendHtml() è consentito:

var container = new TagBuilder("div"); 
var input = new TagBuilder("input"); 

container.InnerHtml.AppendHtml(input); 

secondo bug-fix [here]

1

Sulla @ risposta di Mihai per mostrare il codice vero e proprio per l'approccio StringWriter:

// Create tag builder 
var builder = new TagBuilder("img"); 
//... 
// Render tag approach also changed in .NetCore 
builder.TagRenderMode = TagRenderMode.SelfClosing; 

//Create the StringWriter and make TagBuilder "WriteTo" it 
var stringWriter = new System.IO.StringWriter(); 
builder.WriteTo(stringWriter, HtmlEncoder.Default); 
var tagBuilderIsFinallyAStringNow = stringWriter.ToString(); 
0

Avendo perso span.SetInnerText(somestring); è ora possibile fare

span.InnerHtml.SetContent(somestring);

utilizzando Microsoft.AspNetCore.Html.HtmlContentBuilderExtensions.

Questo viene da una prospettiva di 4.7 con AspNetCore 2.0.1.

Problemi correlati