O Rob Conery, da Microsoft, e que tem atuado no ASP.Net MVC e advogado seu uso desde sempre, lançou essa, agora a pouco:

"WebForms is a lie. It’s abstraction wrapped in deception covered in lie sauce presented on a plate full of diversion and sleight of hand. Nothing you do with Webforms has anything to do with the web – you let it do the work for you.
(…) You’re working in a lie. The web is *not* stateful and works with this stuff called HTML sent across wires using another thing called HTTP (…)"

E segue explicando porque você deve usar ASP.Net MVC. (E queimar seus livros de WebForms – não brincadeira, ele não disse isso.)

O mais interessante é dizer que o Webforms é uma mentira, e fechar dizendo que quem trabalha com WF trabalha com uma mentira. Obviamente eu não concordo, mas que vai dar o que falar vai. Afinal, o cara trabalha na Microsoft… quero só ver.

O .Net Architects já debateu muito sobre ASP.Net MVC e Webforms, prós, contras, etc. Eu também já postei, uns 6 meses atrás, quando você deve usar WF ou MVC. Todo mundo já falou alguma coisa sobre isso. Mas parece que o assunto continua quente…


Postado na(s) categoria(s) Polêmicas , ASP.Net MVC , ASP.Net pelo giovanni bassi em 23 de abril de 2009 às 02:35 | Tags:

Acabei de ver no blog do Cezar Guimarães que o time do ASP.Net publicou o roadmap do ASP.Net AJAX. Li e achei muito interessante. Dêem uma olhada, está no Codeplex.

Algumas novidades: integração no MVC, interoperabilidade, melhoria no Intelisense e comentários, melhorias nas ferramentas e novas funcionalidades, animação, mobile, etc.

Já dá para ver que os componentes do ASP.Net Ajax, que já são bons, vão ficar ainda melhores. E o melhor, como são feitos pela Microsoft, vêm com uma ótima qualidade e vão ser padrão de mercado, o que é sempre muito bom.


Postado na(s) categoria(s) ASP.Net , AJAX pelo Giovanni Bassi em 17 de julho de 2008 às 17:15 | Tags: ,

Peguei uma aplicação esses dias que não tinha nada de tratamento de erros. Nada. Quando uma exceção era lançada, bum, ia parar direto naquela linda tela amarela do ASP.Net. No máximo tinha uma TC (Try Catch Finally) que fazia o seguinte:

    1 Dim componente As New AlgumComponente()

    2 Try

    3     componente.AlgumaFuncao()

    4 Catch ex As Exception

    5     Throw ex

    6 End Try

 

Esse tipo de código é perigosíssimo porque esconde o erro, que depois virará um pesadelo para encontrar. Mas depois eu entro neste assunto. A questão era: eu precisava sugerir uma solução de tratamento de erro em poucos minutos (a aplicação ia subir para homologação no mesmo dia).

Analisei algumas opções:

  1. Base de dados - Não dá tempo de criar os schema e os scripts, está fora.
  2. XML no file system – Estava fora das políticas escrever arquivos em disco, a não ser que fosse muito necessário. Fora.
  3. E-mail – não tinha endereço disponível, e não dava tempo para criar. Fora o trabalho de monitorar desse jeito. Fora.
  4. Algum legado de log ou log de erros. Não havia. Fora.
  5. Memória. Opa… memória!

Sim, guardar na memória resolveu o problema. É óbvio que é uma solução para quem está com pouco tempo, mas ia resolver. Depois implementaria algo mais sofisticado. A idéia era: quando acontecer uma exceção, pega o objeto de exceção e guarda ele em uma lista de acesso global. Perfeito. Criei algo assim:

    1 Public Class MeuLogger

    2 

    3     Public Shared ReadOnly Property Errors() As List(Of Exception)

    4         Get

    5             Dim Exceptions As List(Of Exception) = TryCast(System.Web.HttpContext.Current.Application("apperrors"), List(Of Exception))

    6             If Exceptions Is Nothing Then

    7                 Exceptions = New List(Of Exception)

    8                 System.Web.HttpContext.Current.Application("apperrors") = Exceptions

    9             End If

   10             If Exceptions.Count > 50 Then

   11                 Exceptions.RemoveRange(0, Exceptions.Count - 50)

   12             End If

   13             Return Exceptions

   14         End Get

   15     End Property

   16 

   17 End Class

 

Não lembro se o código era exatamente esse, mas era mais ou menos esse. Nada mais é que uma List(Of Exception) guardada em uma variável de aplicação. Sempre que alguém solicitava a lista eu verificava se ela tinha mais que 50 itens, e se tinha eu removia os primeiros. Cinquenta exceções não é quase nada, a memória não vai sobrecarregar. Depois é só exibir. Vejam os códigos. No caso de erro:

    1 Try

    2     componente.AlgumaFuncao()

    3 Catch ex As Exception

    4     MeuLogger.Errors.Add(ex)

    5     Return

    6 End Try

 

E na hora de exibir criei outra página, joguei um gridview de nome gvErrors sem mudar nada, e fiz o binding, simples assim:

    1 Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    2     LoadErrors()

    3 End Sub

    4 

    5 Private Sub LoadErrors()

    6     Dim errors As List(Of Exception) = MeuLogger.Errors

    7     gvErrors.DataSource = errors

    8     gvErrors.DataBind()

    9 End Sub

 

Para ver o erro era só chamar esta página. Pronto, resolveu. Faça você um teste, vai funcionar. Na chamada de componente.AlgumaFuncao(), lance uma exceção. E faça um “for” umas 70 vezes. Tudo certo até aqui.

Pois bem, mas o título do post não é “como criar um gerenciador de erros em 5 minutos”, mas “Como fazer databind com tipos herdados”. E por quê? Porque se as exceções registrada na lista de erros forem subtipos diferentes de Exception, você vai ter problemas. O gridview, quando começa a fazer o binding de uma List(Of T) na chamada de DataBind(), verifica o tipo da lista logo no primeiro item, e com esse tipo ele tentará montar as colunas dinamicamente. Ele não utiliza o “T” do generics, ele olha o tipo no primeiro objeto da lista. Só que o segundo objeto pode ser de um tipo diferente, mesmo que ambos herdem de Exception. Resultado: o gridview vai procurar por uma propriedade que não existe e… tela amarela de novo. Por exemplo: Se a primeira exceção a ser listada for uma ArgumentException, ela vai ter a propriedade ParamName e a coluna ParamName vai ser adicionada ao gridview. Se alguma outra exceção não for uma ArgumentException, ela não vai ter esta propriedade e teremos o problema.

Vejam o erro abaixo. Notem que temos lançada uma System.Reflection.TargetException, com a mensagem “Object does not match target type”, bem na linha do databind.

image 

O problema não acontece com colunas estáticas, mas, de qualquer forma, há momentos em que queremos um gridview dinâmico mesmo. Para isso fui pesquisar. Das várias soluções que encontrei, a mais fácil e rápida de ser implementada foi criar um wrapper que envolve a classe de lista. Ficou assim:

   22 Private Class ListaDeErrosTipada

   23     Inherits List(Of Exception)

   24     Implements System.ComponentModel.ITypedList

   25 

   26     Sub New(ByVal innerList As IList(Of Exception))

   27         MyBase.New(innerList)

   28     End Sub

   29 

   30 

   31     Public Function GetItemProperties(ByVal listAccessors() As PropertyDescriptor) As PropertyDescriptorCollection Implements ITypedList.GetItemProperties

   32         Return System.ComponentModel.TypeDescriptor.GetProperties(GetType(Exception))

   33     End Function

   34 

   35     Public Function GetListName(ByVal listAccessors() As PropertyDescriptor) As String Implements ITypedList.GetListName

   36         Return "ExceptionList"

   37     End Function

   38 End Class

Veja que a classe herda de “List(Of Exception)”, recebe uma outra lista de exceções no construtor, e repassa esta lista ao construtor da classe base, para que ela já seja adicionada à coleção. Onde está o segredo? Na interface ITypedList, implementada pela lista customizada. Ela informa o tipo que a lista está utilizando. O método GetItemProperties é quem dá a brecha, com a ajuda do método estático GetProperties da classe TypeDescriptor. O outro método não faz diferença neste contexto.

Como fica então o código de databind? Fica assim:

    5 Private Sub LoadErrors()

    6     Dim errors As List(Of Exception) = MeuLogger.Errors

    7     gvErrors.DataSource = New ListaDeErrosTipada(errors)

    8     gvErrors.DataBind()

    9 End Sub

Somente a linha 7 foi alterada, onde pegamos a coleção e a repassamos para a classe de lista de erros tipada.

Com isso meu “log de erros em 5 minutos” ficou pronto.

Happy coding!


Postado na(s) categoria(s) ASP.Net pelo Giovanni Bassi em 25 de junho de 2008 às 21:24 | Tags: , ,

Precisei esses dias encontrar o caminho relativo de um recurso em uma página web. Pensei "o .Net framework já faz isso". Me lembrei do controle Image, que permite utilizar o til (~) para indicar a raiz e portanto o caminho relativo. Com ele, uma imagem na pasta "img" chamada imagem.gif ficaria com a string de caminho "~/img/imagem.gif", seria resolvida para "img/imagem.gif" no caso de uma página chamando da raiz e "../img/imagem.gif" caso a página de chamada morasse em um diretório descendente.

Fui ao Reflector. Descobri que o atributo/propriedade ImageUrl que indica o caminho relativo da imagem é realmente "traduzido" para caminho relativo. O método responsável pela tradução é o ResolveClientUrl, da classe System.Web.UI.Control.

Para utilizar o método, basta colocar o caminho a ser descoberto. Em uma página ASPX, por exemplo, onde você quer descobrir o caminho relativo de um arquivo flash, a tag param ficaria assim:

        <param name="movie" value="<% =Me.ResolveClientUrl("~/flash/banner.swf") %>" />

Isso é útil especialmente para o flash, porque não há um controle nativo no flash, e se você usar uma master page vai ter problemas caso ela seja utilizada por alguma página aspx em um sub diretório. Imagens são mais fáceis, traduzem sozinhas.

 

Simples e prático, mas não achei muita documentação por aí... Analisei também a implementação interna e percebi que a Microsoft utiliza por debaixo dos panos a classe System.Web.Util.UrlPath, mas ela é marcada como "Friend"-VB/"internal"-C#. Essa classe tem muitos métodos interessantes, mas estão todos escondidos de nós, que não estamos codificando o .Net Framework. Porque será?

Enfim, problema resolvido e em pouco tempo. Nada como um framework bem desenvolvido.


Postado na(s) categoria(s) ASP.Net pelo Giovanni Bassi em 27 de maio de 2008 às 09:00 | Tags:

Quem é Giovanni Bassi

Giovanni Bassi Sou uma pessoa apaixonada por tecnologia e especificamente por .Net. Sou consultor independente especialista em .Net, focado em arquitetura e melhores práticas. Tenho dezenas de artigos publicados na .Net Magazine, revista da qual sou editor técnico. Ministro palestras e cursos de vez em quando, e quando dá tempo eu respiro um pouco. Mais detalhes nesta página.

Busca

Selos

Eu vou ao TechEd Brasil 2010, e você?

MVP

MCPD

MCSD

.Net Magazine

Abaixo ao if!

Calendário

«  setembro 2010  »
seteququsedo
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910
Ver detalhamento de posts no calendário

Blogs interessantes

    OPMLDownload OPML file

    Postagens recentes

    Comentários recentes

    Disclaimer / Aviso
    As opiniões colocadas neste blog são minhas e pessoais e não expressam necessariamente as opiniões de meus empregadores, pareceiros e amigos. Da mesma forma, os comentários feitos por leitores do blog não expressam a minha opinião.

    © Copyright 2010 .Net Unplugged
    Log in