Testando WebParts com o ASP.NET AJAX 1.0
Ontem fiquei fazendo alguns testes com webparts e Ajax e resolvi criar este resumo e compartilhar com vocês :
Posso usar webparts com ajax ?
Minha resposta SIM.
Para usar webparts com ajax não preciso fazer nada ?
Minha resposta e não, você precisa fazer sim! Infelizmente nem todas as funcionalidades de webparts foram implementadas , tanto é que ela não faz parte da versão RTM e sim da versão “Future” . Veja as limitações (sem fazer nada) em
http://forums.asp.net/thread/1545256.aspx
ou em
http://blogs.msdn.com/mharder/archive/2007/01/23/webparts-and-asp-net-ajax-1-0.aspx
Então só posso Ajax com a versão “FUTURE” ?
Minha resposta e não, PODE IR ALEM, VOCE PODE USAR WEBPARTS COM A VERSÃO ASP.NET AJAX 1.0!!!!!!!!!!!!!!!!!.
E posso usar Ajax com Webparts em produção?
Minha resposta e não, mas por quê? Por que embora as funcionalidades de Drag and Drop passem a funcionar com as soluções que demonstro mais abaixo, ainda precisa ser amadurecida e melhorada, inclusive se pensando em cross-browser.
O Objetivo aqui é compartilhar o conhecimento e mostrar que é possível fazer funcionar webparts com Ajax , quem acompanhou a evolução lembra que durante os ctps a compatibilidade entres os browses veio depois , como em qualquer amadurecimento de código.
Mas como é possível? Já li que isso é mito uma lenda não é fato....
Minha resposta é que leia ate o final e depois tire a conclusão do que é lenda e que fato e pode ser feito, e conclua você mesmo, afinal não estou aqui para ficar demostrando o que não funciona e sim para compartilhar conhecimento e aprender junto com a comunidade , ou seja com vocês.
Mas esta solução é sua?
Não. Estava trabalhando em uma solução para este cenário, porem meu trabalho foi abreviado por encontrar uma solução bem mais adiantada e seguindo o mesmo raciocínio que o meu.
Mas afinal qual é a Mágica?
Bem antes de mostrar como é a mágica, vamos entender o que não funciona:
Uma das principais funcionalidades de usar webparts é você poder mover as webparts entre as webzones. Uma das coisas desagradáveis era que quando fazia isso para cada webparts que você movia era executado um postback e página era toda carregada.
Com a chegada do AJAX isso pareceu ter sido resolvido de uma forma muito elegante não ocorrendo mais o postback, tornando a usabilidade bastante atraente. Infelizmente esta funcionalidade com o Ajax foi retirada nas versões betas e também na versão RTM 1.0, sendo deixada para ser implementada em versões futuras. Quando colocamos as webparts e o wepartmananger dentro do updatepanel o drag and drop não funciona corretamente.
Mas porque não funciona?
É aqui que começa a mágica. Se observar o comportamento quando esta dentro do updatepanel ira perceber que funciona na primeira vez e depois quando é feito o “Partial render” pelo scriptmananger não é possível mais executar o drag and drop. Este efeito indesejado esta centrado em um único componente:
O webpartmananger.
O webpartmananger que é responsável por gerar e registrar os scripts com as funcionalidades. Este script é que são os responsáveis pela funcionalidade Drag and drop, os Verbos dos menus e outras funcionalidades das webparzones.
Desta forma então será o webpartmananger que teremos que modificar para que o webparts funcione corretamente.
Mas porque precisamos modificar ele (webpartmananger) ?
Porque quando colocamos ele dentro do updatepanel durante o primeiro render ele carrega os script e executa as funcionalidades, mas depois do primeiro “Partial render” o Webpartmananger não consegue mas registrar os scripts e “se perde” criando exatamente o comportamento já descrito de apenas executar somente 1 vez, isso se explica porque o responsável por isso é o scriptmananger quando trabalhamos com AJAX. Simples não é..... São estes conceitos que ajudam a você a resolver cenários onde existe pouca documentação e recursos existentes.
Vocês já leram também pelo meu blog que os validators também tem problemas quando usando dentro do updatepanel (principalmente dentro de templates de grids que estão dentro dos updatepanels) . A solução para os validtors foi mapear as classes responsáveis pelos controles para outra classe que resolver o problema.
A solução para webparts é feita da mesma forma! Justamente por este caminho que estava trabalhando quando me deparei com outra solução feita por outro desenvolvedor segundo exatamente esta linha!
Mas o que deve ser feito?
Primeiro criar uma classe que herde do WebpartMananger e sobre-escrever o RenderClientScript (para se ter o controle do se se escreve na pagina). Com isso registramos os scripts pelo System.Web.UI.ScriptManager e não mais pelo System.Web.UI.ClientScriptManager.
Esta simples mudança faz com que os script registrados sejam executados a cada refresh do updatepanel que é controlado pelo scriptmananger.
Estava bem próximo disso quando encontrei esta solução que estou descrevendo.
Para completar a solução será necessário mapear as classes do System.Web.UI.WebControls.WebParts.WebPartManager para a classe que esta sendo criada da mesma forma que foi feita a solução para os validators.
<configuration>
<system.web>
<pages>
<tagMapping>
<add
tagType="System.Web.UI.WebControls.WebParts.WebPartManager"
mappedTagType="Sample.Web.UI.WebParts.WebPartManager, Sample.Web.UI.WebParts"
/>
</tagMapping>
</pages>
</system.web>
</configuration>
E o código ? Vamos a explicação de algumas partes dele :
Como já falamos a classe herda de System.Web.UI.WebControls.WebParts.WebPartManager e o trecho abaixo mostra como esta sendo registrado o script necessário junto ao ScriptManager e depois durante a statup para garatir o resfresh do updatepanel.
Public Class WebPartManager
Inherits System.Web.UI.WebControls.WebParts.WebPartManager
Protected Overrides Sub RegisterClientScript()
If Me.CheckRenderClientScript Then
System.Web.UI.ScriptManager.RegisterClientScriptResource(Me,
GetType(System.Web.UI.WebControls.WebParts.WebPartManager),
"WebParts.js")
System.Web.UI.ScriptManager.RegisterStartupScript(Me,
Me.GetType, Me.ID & "_Script", Me.Script, True)
End If
End Sub
Abaixo parte de o script necessário ser executado durante o startup.
Private ReadOnly Property Script() As String
Get
Dim colorConverter As New System.Web.UI.WebControls.WebColorConverter
Dim _clientScript As String = String.Format("__wpm = new
WebPartManager();{0}" & _
"__wpm.overlayContainerElement =
document.getElementById('{2}___Drag');{0}" & _
"__wpm.personalizationScopeShared = {1};{0}" & _
"var zoneElement;{0}var zoneObject;{0}",
ControlChars.CrLf, Me.Personalization.CanEnterSharedScope.ToString.ToLower, Me.ClientID)
For Each z As WebPartZone In Me.Zones……
Return _clientScript
End Get
End Property
Você deve estar se perguntando como é possível saber que código escrever para se chegar a este resultado ... Aqui Tb não existe nenhuma lenda nem nenhum “super guru” ..rs.rs, quem acompanha meu blog em http://linhadecodigo.com.br/cs2/blogs/fcerqueira deve se lembra de uma dica que dei da nova versão do :
“Refletor 5.0 - Uma ferramenta indispensável” (http://linhadecodigo.com.br/cs2/blogs/fcerqueira/comments/588.aspx)
No blog disse
“Embora muitos achem que a intenção é descompilar e ver o código fonte, estas ferramentas tem uma tarefa mais nobre : Faciliar o entendimento do .NET framework. Ajudar a melhorar a performance e reduzir os cast Uma grande fonte de aprendizado”
E ai esta a outra parte da mágica, aprender mais sobre o funcionamento vendo como é realizado as rotinas.
Uma pergunta final que pode ser feita : Esta solução é crossbrowser ?
Infelizmente não é, por enquanto esta solução esta compatível apenas com o Internet Explorer , porem mostra que com um pouco de conhecimento pode-se se chegar a uma solução. O legal de compartilhar conhecimento é poder mostrar os avanços, os caminhos . Compartilhando estes caminhos e códigos outros desenvolvedores aprendem melhor o funcionamento e pode evoluir a solução até chegar a uma maturidade de código que permita o uso em usa plenitude
Onde posso pegar todo o código fonte ?
Esta em um thread no fórum www.asp.net : http://forums.asp.net/thread/1621227.aspx
Quem inica a thead e o propio autor da classe, a ele que devemos dar o grande parabens . De minha parte estou apenas ajudando a divulgar e compartilhar com vocês.
A todos um grande abraço