quinta-feira, 17 de maio de 2007

Referência circular usando Master Page e User Control

Olá.

Depois que a Microsoft nos disponibilizou as master pages nossa vida melhorou bastante. Mesmo com alguns contratempos a simples possibilidade de realizarmos herança visual em nossas páginas já é recompensador e, como todo bom recurso, tenho usado e abusado do mesmo.

Dentre os “abusos” posso citar a confecção de master pages de outras master pages (tenho casos de quatro níveis de herança) e controles que estão tanto na master page quanto na página que a implementa.

Este último “abuso” me causou bastante dor de cabeça.
Ainda não sei exatamente onde estava o problema, pois necessito estudar a fundo o modelo de compilação do ASP.NET 2.0.

Lembremos que houve uma mudança no sistema de compilação do ASP.NET.
Nas versões anteriores ao Visual Studio 2005 nossos sites eram projetos do tipo Web Project e agora temos o conceito de Web Site. Por haver material farto na internet sobre este assunto, vou diretamente ao meu problema, mas antes, segue link para quem quiser se aprofundar:

Compilando aplicações ASP.NET 2.0 - Mudanças no Modelo de Código e Compilação

Nota importante: para quem sente saudades ou necessita trabalhar como antigamente, o Service Pack 1 do Visual Studio 2005 adiciona um novo, porém velho conhecido, tipo de projeto: o Web Project. Mas ao trabalhar com este tipo de projeto você perderá uma série de vantagens dos Web Sites, como por exemplo, mudar algo no codebehind ou outra classe e não precisar recompilar.

Quando necessitei usar um mesmo controle de usuário (user control) na master page e na página (content place holder) recebi erros de referência circular.

Depois de algum tempo pesquisando postei minha dúvida no fórum da MSDN e obtive uma resposta quase que imediatamente. A sugestão era, ao invés de registrar o controle em cada página (na master page e na página), eu o registrasse no web.config, desta forma:

<configuration>
<system.web>
<pages>
<controls>
<add tagPrefix="IW" tagName="ctrPesquisas" src="~/Controles/ctrPesquisas.ascx"/>
</controls>
</pages>
</system.web>
</configuration>


Tal solução funcionou perfeitamente para o meu problema.

De maneira básica, os problemas de referência circular não necessariamente ocorrem diretamente entre páginas, controles e master pages.
Segundo o modelo de compilação padrão as classes em uma mesma pasta são compiladas em uma mesma DLL.
Vejam o exemplo visual abaixo:

No caso apresentado a ClasseA possui uma referência à ClasseC e a ClasseD possui uma referência para a ClasseB. Note que não há qualquer referência circular direta entre as classes, porém há uma referência circular entre as dll’s geradas porque a DLL1 referencia a DLL2 e a DLL2 referencia a DLL1.

Conhecendo este comportamento podemos adotar estratégias para evitar tais referências, como, por exemplo, movendo alguma das classes para outra pasta provocando assim a criação de uma terceira DLL e evitando a referência circular.

De maneira mais radical, poderemos utilizar a diretiva batch da tag compilation do web.config que força a criação de uma DLL para cada classe, página, controle e demais componentes.

<configuration>
<system.web>
<compilation batch="false">
</compilation>
</system.web>
</configuration>

Abraços e até o próximo post.

2 comentários:

Anônimo disse...

Boa tarde, estou com um problema que acredito ser parecido com o que você teve. Eu tenho uma master page que esta num projeto web site. Gostaria de usar essa mesma master page num outro projeto web site, mas sem precisar copiar essa master page para o outro projeto. Eu tentei compilar a master page e adicionar a DLL gerada como referência no outro projeto, mas não deu certo. Você saberia me dizer como posso fazer isso? A idéia, pra ficar mais claro é a seguinte: eu estou tentando montar um portal de aplicações, onde eu tenho uma aplicação principal, e nela eu uso uma master page. Todos os outros projetos, serão incorporados no mesmo web site, mas serão projetos diferentes em soluções diferentes, e meu problema em "herdar" a master page esta ai, pois os projetos são separados, apesar de estarem no mesmo diretório virtual.
Espero que tenha sido claro.

Obrigado.

João Paulo Barbosa Fernandes disse...

Olá Juliano,

Desculpa a demora na resposa (e que demora). Mesmo crendo que você tenha solucionado seu problema, vou responder ao post pois pode ser de valia a alguém. Encontrei no site OdeToCode.com um artigo exelente sobre master pages, e ao final dele há uma consideração sobre exatamente este seu problema. Está bem no final e é entitulado "Sharing Master Pages". Abraços, JP.

http://www.odetocode.com/articles/450.aspx