2013-12-09 34 views
5

Si è verificato un problema interessante nei WebForms ASP.Net durante la migrazione di un progetto da 3,5 a 4,5.Edizione Dynamic UpdatePanels e UserControls

Il sito in questione è estremamente dinamico: la pagina viene creata in base alla configurazione in modalità CMS.

Tuttavia in 4.5 abbiamo un problema: quando più contenuti vengono aggiunti nella pagina tramite un clic del pulsante, non viene visualizzato tutto il markup per il contenuto. (Alla prova il problema è riprodotto anche in .net 4.0).

Per dimostrare qui è un esempio molto spogliato che utilizza solo il modello di progetto WebForms predefinito (in VB in questo caso).

Nel Default.aspx aggiungere il seguente markup:

<asp:UpdatePanel ID="udpTrigger" runat="server" UpdateMode="Always"> 
    <ContentTemplate> 
     <asp:button id="btnGo" runat="server" Text ="Go" /> 
    </ContentTemplate> 
</asp:UpdatePanel> 
<asp:Panel ID="pnlContainer" runat="server"> 
</asp:Panel> 

Nel Default.aspx.vb aggiungere il seguente codice:

Dim _udp As UpdatePanel 

Private Sub Page_Init(sender As Object, e As EventArgs) Handles Me.Init  
    _udp = New UpdatePanel() 
    _udp.ID = "udpTarget" 
    _udp.UpdateMode = UpdatePanelUpdateMode.Conditional 

    pnlContainer.Controls.Add(_udp)   
End Sub 

Private Sub btnGo_Click(sender As Object, e As EventArgs) Handles btnGo.Click  
    Dim ctrl = LoadControl("Control.ascx")   

    Dim pnlWrapper = New Panel With {.ID = "pnlWrapper"} 
    pnlWrapper.Controls.Add(ctrl) 

    _udp.ContentTemplateContainer.Controls.Add(pnlWrapper)   
    _udp.Update()    
End Sub 

Nota: C'è un pannello involucro qui tra il controllo utente e il pannello di aggiornamento. Questo serve a dimostrare quale markup manca sull'output.

Creare un Control.ascx e aggiungere il seguente:

<asp:Panel ID="pnlControl" runat="server"></asp:Panel> 

Una volta che si clicca il controllo btnGo, il pannello involucro e control.ascx dovrebbero essere aggiunti alla pagina.

In Net 3.5 che è esattamente ciò che accade:

<div id="pnlContainer">      
    <div id="udpTarget"> 
     <div id="pnlWrapper"> 
      <div id="ctl05_pnlControl"> 
      </div> 
     </div> 
    </div> 
</div> 

In .Net 4.5, non appare il pannello di avvolgimento

- solo il controllo utente:

<div id="MainContent_pnlContainer">   
    <div id="MainContent_udpTarget"> 
     <div id="MainContent_ctl02_pnlControl"> 
     </div> 
    </div> 
</div> 

Il problema doesn' Si verifica se il pannello di aggiornamento è nel markup della pagina Web, tuttavia non è possibile in questo caso.

Commutazione quale sovraccarico LoadControl viene utilizzato (su LoadControl(type,params) produce il pannello wrapper, ma nessun markup - sembra esserci un problema separato con questo).

Controllo del corpo della risposta in fiddler2 dimostra che il pannello involucro viene omesso lato server (cioè non stiamo perdendo nel settore della trasformazione lato client Ajax)

Quindi non v'è alcuna soluzione, o addirittura una sorta di correggere la patch per questo comportamento - sembra essere una rottura in .Net 4 dato che andava bene in 3.5.

Anche ora ho postato questo sul mio blog here per raccogliere tutti i tentativi che faccio per ottenere una soluzione o una soluzione alternativa.

Aggiornamento

A seguito di un puntatore da @ jadarnel27 che i passaggi riportati di seguito non riprodurre il problema su VS2010, ho provato i passi su un paio di macchine da lavoro.

  • Prima di tutto un'altra macchina VS2013: Ha ricreato il problema.
  • successivo, la mia vecchia macchina dev, in esecuzione VS2012 Express per Web: non ha ripreso il problema

in modo che appaia in questa fase, come il problema è limitato a VS2013. Avanti per provare alcune diverse impostazioni in VS2013.

Ora inviato a Microsoft Connect here.

+0

Se si ispeziona l'albero dei controlli (guardando dalla pagina verso il basso fino al controllo, usando le proprietà Controlli) si trova il pannello nell'albero o non è lì? Questo per discernere se il problema è sul lato server o negli script ajax. Dovresti controllare questo nell'evento pre-rendering. – JotaBe

+0

@JotaBe: il markup inviato non contiene il wrapper - controllato in fiddler, guardando il contenuto della risposta. –

+0

@ jadarnel27. Interessante. Ce l'abbiamo su tutte le macchine qui. Effettuerà il test sulla mia configurazione di casa. –

risposta

1

Soluzione alternativa

Ho una soluzione per questo ora. Sto utilizzando un controllo UserControlLoader server per avvolgere il controllo utente, e rendere separatamente ridefinendo RenderContents

Il codice per UserControlLoader è:

''' <summary> 
''' UserControl Loader - loads a user control 
''' Works around a problem with ASP.Net Webforms in 4.0/4.5 
''' </summary> 
<ToolboxData("<{0}:UserControlLoader runat=server></{0}:UserControlLoader>")> _ 
Public Class UserControlLoader 
    Inherits WebControl 

    Public ReadOnly Property Control As Control 
     Get 
      Return _control 
     End Get 
    End Property 
    Private _control As Control 

    Public Sub LoadControl(page As Page, virtualPath As String) 
     _control = page.LoadControl(virtualPath) 
     Me.Controls.Add(_control) 
    End Sub 

    Public Overrides Sub RenderBeginTag(writer As HtmlTextWriter) 
     'Don't render anything 
    End Sub 

    Public Overrides Sub RenderEndTag(writer As HtmlTextWriter) 
     'Don't render anything 
    End Sub 

    ''' <summary> 
    ''' Overrides RenderContent to write the content to a separate writer, 
    ''' then adds the rendered markup into the main HtmlTextWriter instance. 
    ''' </summary> 
    Protected Overrides Sub RenderContents(ByVal writer As HtmlTextWriter) 

     If _control Is Nothing Then Return 

     Using sw = New StringWriter() 
      Using hw = New HtmlTextWriter(sw) 

       MyBase.RenderContents(hw) 

       writer.Write(sw.ToString) 

      End Using 
     End Using 

    End Sub 

End Class 

Usage:

Per attuare questo nel tempo libero passaggi elencati, il gestore btnGo evento diventa:

Private Sub btnGo_Click(sender As Object, e As EventArgs) Handles btnGo.Click 

    Dim loader = new UserControlLoader() 
    loader.LoadControl(Page,"Control.ascx")  

    Dim pnlWrapper = New Panel With {.ID = "pnlWrapper"} 
    pnlWrapper.Controls.Add(loader) 

    _udp.ContentTemplateContainer.Controls.Add(pnlWrapper)   
    _udp.Update() 

End Sub 
0

Nel mio caso, ho ha avuto lo stesso problema con VS2013 Professional senza aggiornamenti applicati. Supponevo che fosse un bug correlato con il server delle app incorporato incluso nell'installazione (IIS Express). Aggiornamento dell'IDE con l'ultimo pacchetto di aggiornamento (VS2013 Update 5), il problema è scomparso!