Boa tarde moçada! Tudo na Paz?!

Já há algum tempo queria mostrar para vocês como utilizar um httpModule para criar um filtro de http que encapsula as variáveis de querystring e de quebra tornar suas URL´s mais amigáveis, pois estou usando isso num software aqui da empresa e tem sido ótimo trabalhar desta forma.

Bom, numa visão geral, a solução resume-se no seguinte: você tem uma navegação em seu sistema web cheia de default.aspx, pagina.aspx além de parâmetros de querystring outrapagina.aspx?parametro=26&estranho=32&feio=S e por aí vai. Agora imagine isso em uma aplicação web mobile com aqueles browsers minúsculos e uma digitação super difícil naqueles tecladinhos. Fica inviável, né?

Tentando melhorar este cenário, pesquisei sobre o assunto e encontrei a solução que menos interferiu na maneira como eu já programava e me deu os benefícios esperados. A solução foi criar um httpModule e um httpHandler para mapear minhas URL´s da forma que quizer e fazê-las chegar na página que eu escolher. Incrível? Nada disso… é algo super simples de se fazer, mas chega de falar de teoria e vamos ver na prática como funciona.

A primeira coisa que precisa ser feita é definir no global.asax todos os seus roteamentos. Podemos fazer isso adicionando uma função estática que recebe uma RouteCollection e adiciona uma a uma nossas rotas.

  
  public static void RegisterRoutes(RouteCollection routes)
  {
      routes.Add(new Route("blog/home/", new RouteHandler<Page>("~/Default.aspx")));
      routes.Add(new Route("blog/{postname}/{postid}/", new RouteHandler<Page>("~/Read.aspx")));
      routes.Add(new Route("blog/profile/{userid}/", new RouteHandler<Page>("~/UserProfile.aspx")));
  }

Depois de criar a função basta chamá-la dentro do seu Application_Start, passando o objeto estático que fica dentro de System.Web.Routing. Aliás, adicione esta referência ao seu projeto e ao seu global.asax.

protected void Application_Start(object sender, EventArgs e)
{
     RegisterRoutes(RouteTable.Routes);
}

Depois precisamos criar um Handler, que nada mais é do que o “tradutor” das nossas URL´s, ou seja, é ele que irá saber que a URL http://www.sistema.com/blog/criando-um-routing/12/ na verdade deverá ser processado pela página http://www.sistema.com/Read.aspx, e que parte desta URL são na verdade parâmetros, como por exemplo:

  • http://www.sistema.com/blog/criando-um-routing/12/
  • http://www.sistema.com/blog/{postname}/{postid}/

Repare, que a estrutura da URL é a mesma. Desta forma as partes entre {} serão entendidas como parâmetros de mesmo nome da parte da URL indenficada no roteamento. Então concluímo que:

postname = "criando-um-routing" e postid = 12

Veja como ficou o meu handler.

public class RouteHandler<T> : IRouteHandler where T : IHttpHandler, new()
{
     public string VirtualPath { get; set; }

     public RouteHandler(string virtualPath)
     {
           VirtualPath = virtualPath;
     }

     public IHttpHandler GetHttpHandler(RequestContext requestContext)
     {            

                foreach (var value in requestContext.RouteData.Values)
                {
                    requestContext.HttpContext.Items[value.Key] = value.Value;
                }

                return (VirtualPath != null)
                           ? (IHttpHandler) BuildManager.CreateInstanceFromVirtualPath(VirtualPath, typeof (T))
                           : new T();

     }

}

Tudo que está classe faz é procurar na tabela de roteamentos, a rota que foi solicitada procurando pelas partes “variáveis”, introduzindo estes valores variáveis na coleção de Items do HttpContext com o nome do parâmetro e o valor recebido na URL. E pronto! Nossa solução está pronta.

Agora só precisamos adicionar a referência da dll de roteamento em nosso web.config na seção httpModules, como mostrado abaixo.

<httpModules>
     <add name="UrlRoutingModule"
              type="System.Web.Routing.UrlRoutingModule, System.Web.Routing,
              Version=3.5.0.0, Culture=neutral,
              PublicKeyToken=31BF3856AD364E35" />
</httpModules>

Feito tudo isso, podemos enfim começar a programar nossas páginas. Digamos que estamos na página Read.aspx e precisamos pegar os dois parâmetros (postname e postid) que vieram na URL.

protected void Page_Load(object sender, EventArgs e)
{
    if (HttpContext.Current.Items["postname"] != null)
        Response.Write("name: " + HttpContext.Current.Items["postname"]);

    if (HttpContext.Current.Items["postid"] != null)
        Response.Write("id: " + HttpContext.Current.Items["postid"]);
}

Então mãos a obra e sucesso!