Blog ativo novamente

Olá pessoal,depois de algum tempo parado estou novamente reativando o blog.

Em breve mais novidades!

Anúncios

ASP.NET MVC – Design de controllers – Parte 1

Numa aplicação Asp.net MVC ,controllers existem para responder qualquer requisição que um usuario faça através da interface de usuario.Qualquer interação entre a aplicação e o usuario é geralmente descrita como use-case.Como arquiteto,você começa a partir do user-case pra ter uma idéia clara das funções que devem estar disponiveis para o usuario na aplicação.

Sua próxima tarefa é simplesmente mapear funções para a classe controller.

Não existem razões técnicas que o impeçam de ter uma única classe controller que englobe toda a aplicação;e da mesma forma não existem razão técnicas que o impeçam,de ter uma classe controller para cada possível requisição.

Você está agora no momento de particionar o conjunto de funções num número balanceado de classes controller.Como você faz isso,depende das funções e mais o mais importante,da visão da aplicação que se origina do user-case.Como via de regra,você deve se preocupar em ter uma classe controller para cada entidade significante na solução da sua aplicação.

Num site comercial,é comum você encontrar use-cases que precisem de operações CRUD (Create,Read,Update,Delete) em clientes,pedidos,detalhes do pedido, e faturas.Você pode então iniciar com um OrderController para permitir que usuarios criem um novo pedido,assim como atualizar ou deletar pedidos.Fazendo isso,você deve estar focado nas necessidades da camada de apresentação,e colocar de lado,como irrelavente no momento,as necessidades da entidade modelo da camada de negócios.

Se você lida com pedidos,você provavelmente também lida com detalhes do pedido e produtos.Porém,apesar de Pedidos,Detalhes do pedido,e produtos serem bons candidatos a se tornarem membros do modelo de entidades (ou domain model,se você aplicar a metodologia domain-driven),somente Pedidos faz sentido como inspirador da criação de uma classe controller.A partir da perspectiva da interface de usuario,na verdade,um usuario irá enviar comandos somente para criar,atualizar ou deletar pedidos.Nesse caso,é OK ter um OrderController,mas não é OK ter um OrderDetailsController.Uma regra simples é a seguinte.

Ter um contoller para cada entidade de negócio que é diretamente exposta na camada de apresentação.

Esse poder ser apenas o primeiro passo,no entanto.

Suponha que um dos use-cases determine que você deva fazer com que os usuarios possam visualizar faturas.Um InvoiceController seria então util para servir as necessidade do usuario.Num site comercial,no entanto,provavelmente você vai disponibilizar uma seção de back-office para controle administrativo,como processamento de pedidos e faturas.Nesse caso,pode ser util tem uma classe controller distinta para suportar operações de back-office para pedidos e faturas.Outra regra simples é a seguinte:

Tenha uma classe controller para cada entidade da camada de negócio que é exposta diretamente na camada de apresentação e pra cada contexto operacional.

No fim das contas,o mapeamento de funções para controllers,e o subsequente mapeamento de métodos para controllers,certamente não é uma ciência exata.Porém,com a correta e sistemática aplicação dos principios da chave de design,você pode obter um design que seja aceitavel para todas as partes interessadas no projeto.O principio é o Single Responsibility Principle – SRP (Principio da Responsabilidade única).As duas regras simples citadas anteriormente fazem parte do SRP.

Mapeando comportamento de métodos

No todo, a parte mais complicada do processo de design é mapear as funções para os controllers.Depois de você ter estabelicido uma lista aceitavel de controllers,deve ficar claro quais métodos pertecem a quais controllers.Métodos de um controller são conhecidos como Actions – e o nome não poderia ser mais apropriado.Num controller,você tem um método para cada ação do usuario, o que acaba caindo na (única) responsabilidade do controller.

Como você codifica um método de um controller?O template de um método pode ser resumido no seguinte:

  • Recuperar dados de entrada – Um método pode obter argumentos de entrada de várias fontes:route values e coleções expostas pelo objeto Request.O ASP.NET MVC não impõe uma assinatura particular para métodos de um controller.Para testes,é preferivel que qualquer parametro de entrada seja recebido através da assinatura do método.Evite,se você puder métodos que recuperem parametros programaticamente através do objeto Request.Pré-condições também ajudam a garantir que não hajam valores incorretos passados nas camadas do sistema.
  • Realizar a tarefa – Nesse momento,o método realiza o seu trabalho baseado nos argumenos de entrada e nos resultados esperados.Na maioria das vezes,o método precisa interagir com a camada intermediária e qualquer dessas interações é feita através de serviços dedicados.Validações de valores calculados ocorrem também nesse estágio.
  • Preencher o View-Model – No fim da tarefa,qualquer valor que deva ser incorporado na resposta é adicinado ao view-model.O view-model pode ser um dicionario plano de key/value,ou um objeto strong-typed especifico daquela view.
  • Preparar o objeto result – Um controller não é responsável por produzir a resposta em si.Ele é responsavel,por disparar o processo que irá usar um objeto View distinto para renderizar o resultado para a saída.O método identifica o tipo da resposta (file,plain data,HTML,JavaScript,ou JSON) e prepara um objeto ActionResult de acordo.

Parece fácil de maneira geral?Bom,outro aspecto complicado é como você elabora o código que executa a tarefa.Mas isso fica para a próxima parte de design de controllers.

Até lá!

ASP.NET MVC Controllers

Entendendo Controllers

Controllers são responsáveis por respostas a requisições feitas em um website ASP.NET MVC.Cada requisição de um navegador é mapeada para um controller em particular.Por exemplo,imagine que você entre com a seguinte URL no seu navegador:

http://localhost:4656/Product/Index/3

Nesse caso,um controller chamado ProductController é chamado.Esse controller é responsável por gerar a resposta para a requisição do navegador.Por exemplo,o controller poderia retornar uma View em particular para o navegador ou poderia redirecionar o usuario para outro controller.

Veja abaixo o ProductController:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax; 

namespace MvcApplication1.Controllers
{
public class ProductController : Controller
{
//
// GET: /Products/

public ActionResult Index()
{
// Add action logic here
return View();
}

}
}

Como você pode ver acima,um controller é somente uma classe.Um controller é uma classe que deriva da classe base System.Web.Mvc.Controller.Como todo controller herda dessa classe base,um controller herda muitos métodos úteis gratuitamente.

Entendendo Actions

Uma Action é um método em um controller que é chamado quando você entra com uma URL particular no navegador.Por exemplo,a seguinte URL:

http://localhost:4656/Product/Index/3

Nesse caso,o método Index é chamado na classe ProductController.O método Index é exemplo de uma action.

Uma action deve ser um método público de um controller.Métodos C#,por padrão são privates.Perceba que qualquer método público em um controller é considerado uma action automaticamente (por isso você deve ser cuidadoso,pois esse método pode ser invocado por qualquer um no universo simplesmente digitando a URL correspondente no navegador).

Existem alguns outros requerimentos para uma action.Um método usado como action não pode ser sobreescrito.Também não pode ser static.Fora isso,você pode usar qualquer outro método como action.

Entendendo Action Results

Uma action retorna algo chamado action result.Uma action result é o que um controller retorna em resposta a uma requisição de um navegador.

O ASP.NET MVC framework contém vários tipos de action results:

  1. ViewResult – Representa HTML e markup
  2. EmptyResult – Representa resultado vazio
  3. RedirectResult – Representa redirecionamento para uma nova URL
  4. JsonResult – Representa um resultado JSON que pode ser utilizado numa aplicação AJAX
  5. JavaScriptResult – Representa um script JavaScript
  6. ContentResult – Representa um resultado em texto
  7. FileContentResult – Representa um arquivo que pode ser baixado (com conteúdo binário)
  8. FilePathResult – Representa um arquivo que pode ser baixado (com um path)
  9. FileStreamResult – Representa um arquivo que pode ser baixado (com um stream)

Todos esses Action Results herdam da classe base ActionResult.

Na maioria dos casos,uma action retorna um ViewResult.Por exemplo,o método Index abaixo retorna um ViewResult:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax; 

namespace MvcApplication1.Controllers
{
public class BookController : Controller
{

public ActionResult Index()
{
// Add action logic here
return View();
}

}
}

Quando uma action retorna um ViewResult um HTML é gerado para o navegador.O método Index acima retorna uma view chamada Index para o navegador.

Note que a action Index não retorna um ViewResult().Ao invés disso,o método View() da classe controller é chamado.Normalmente,você não retorna um action result diretamente.Ao invés disso,você chama um dos seguinte métodos,da classe controller:

  1. View – Retorna um action result ViewResult
  2. Redirect – Retorna um action result RedirectResult
  3. RedirectToAction – Retorna um action result RedirectToRouteResult
  4. RedirectToRoute – Retorna um action result RedirectToRouteResult
  5. Json – Retorna um action result JsonResult
  6. JavaScriptResult – Retorna um JavaScriptResult
  7. Content – Retorna um action result ContentResult
  8. File – Retorna um FileContentResult,FilePathResult,ou FileStreamResult dependendo dos parâmetros passados para o método

Então,se você quer retornar uma View para o navegador,você chama o método View().Se você quer redirecionar o usuario de uma action para outra,você chama o método RedirectToAction().Por exemplo,a action Details abaixo,ou mostra uma View ou redireciona o usuario para a action Index dependendo se o parâmetro ID tiver algum valor:

using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
public class CustomerController : Controller
{
public ActionResult Details(int? id)
{
if (!id.HasValue)
return RedirectToAction(“Index”);

return View();
}

public ActionResult Index()
{
return View();
}

}
}

A ContentResult action é especial.Você pode usa-lo pra retornar um action result em formato de texto plano.Por exemplo,o método Index abaixo retorna o resultado como texto plano e não como HTML:

using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
public class StatusController : Controller
{

public ActionResult Index()
{
return Content(“Hello World!”);
}

}
}

Quando o método Index é chamado uma View não é retornada.Ao invés disso,em seu lugar o texto plano “Hello World!” é retornado para o browser.

Se uma action retornar um valor que não seja um action result – por exemplo,uma Data ou um inteiro – então o resultado é colocado num ContentResult automaticamente.Por exemplo,quando o método Index abaixo é chamado, a data é colocada como ContentResult automaticamente:

using System;
using System.Web.Mvc; 

namespace MvcApplication1.Controllers
{
public class WorkController : Controller
{

public DateTime Index()
{
return DateTime.Now;
}

}
}

O ASP.NET MVC converte o objeto DateTime pra uma string e coloca o resultado num ContentResult automaticamente.O navegador recebe a data como texto plano.

É isso aí pessoal até apróxima!
Qualquer dúvida deixem comentários que responderei assim que possível.

ASP.NET MVC Entendendo Action Filters

Entendendo Action Filters

Um Action Filter é um atributo que você pode aplicar a uma Action de um controller,ou a um controller diretamente – o que modifica a maneira como essa action é executada.O framework MVC ja inclui muitos Action Filters

  • OutputCache – Esse action filter coloca o resultado de uma action em cache por um tempo determinado
  • Handle Error – Esse action filter manipula erros disparados durante a execução da action de um controller
  • Authorize – Esse action filter permite a você restringir acesso a um usuario ou role em particular

Você pode também criar seu próprio action filter.Por exemplo,você pode querer criar seu próprio action filter para implementar um sistema de autenticação personalizado.Ou,você pode querer criar um action filter que modifique a viewdata retornado por uma action de um controller.

Usando um action filter

Um action filter é um atributo.Você pode aplicar a maioria dos action filters para uma action ou diretamente para um controller inteiro.Por exemplo,o DataController abaixo contém uma action chamada Index que retorna a data atual.Essa action está decorada com o action filter OutputCache .Esse action filter faz com que o valor retornado pela action seja colocado em cache por 10 segundos.

using System;
using System.Web.Mvc; 

namespace MvcApplication1.Controllers
{
public class DataController : Controller
{
[OutputCache(Duration=10)]
public string Index()
{
return DateTime.Now.ToString(“T”);

}
}
}

Se você chamar repetidamente a action Index digitando a URL /Data/Index na barra de endereços do seu navegador e pressionando o botão de refresh varias vezes,você verá o mesmo horário durante 10 segundos.A saída da action Index é colocada em cache durante 10 segundos (figura 1):

No exemplo acima,um unico action filter – o OutputCache – é aplicado ao método Index.Se você precisar,você pode aplicar vários action filters diferentes a mesma action.Por exemplo,você pode querer aplicar os action filters OutputCache e HandleError para a mesma action.

No exemplo acima,o action filter está sendo aplicado diretamente na action Index,mas você também poderia ter aplicado diretamente ao controller.Nesse caso,todas as actions deste controller teriam suas saídas colocadas em cache durante 10 segundos.

Os diferentes tipos de filters

O ASP.NET MVC suporta quatro diferentes tipos de filters:

  1. Authorization filters – Implementa o atributo IAuthorizationFilter
  2. Action filters – Implementa o atributo IActionFilter
  3. Result filters – Implementa o atributo IResultFilter
  4. Exception filters – Implementa o atributo IExceptionFilter

Os filters são executados na ordem listada acima.Por exemplo,authorization filters são sempre executados antes de action filters e exception filters são sempre executados após qualquer outro tipo de filter.

Authorization Filters são usados para implementar autenticação e autorização para actions de um controller.Por exemplo,o Authorize filter é um exemplo do Authorization Filter.

Action Filters contém lógica que é executada antes e depois que a action de um controller é executada.Você pode usar um action filter,por exemplo,para modificar a ViewData que uma action retorna.

Result Filters contém lógica que é executada antes e depois da execução de um View Result.Por exemplo,você pode querer modificar um ViewResult um pouco antes da view ser renderizada para o navegador.

Exception Filters são os últimos tipo de filter que são executados.Você pode usar exception filters para tratar erros disparados pela suas actions ou pelo resultado das suas actions.Você também pode usa-lo para criar um log de erros.

Cada tipo diferente de filter é executado numa ordem em particular.Se você quiser modificar a ordem de execução de cada filter do mesmo tipo você pode setar a propriedade ORDER do filter.

A classe base para todos os filters é System.Web.Mvc.FilterAttribute.Se você quiser implementar um tipo particular de filter,então você precisa criar uma classe que herde dessa classe base e implemente uma ou mais das seguintes intefaces:IAuthorizationFilter,IActionFilter,IResultFilter ou IExceptionFilter.

<h3>A classe base ActionFilterAttribute</h3>

Pra facilitar a sua vida quando você quiser implementar um filter próprio,o ASP.NET MVC inclui uma classe base <em>ActionFilterAttribute</em>.Essa classe implementa as interfaces <em>IResultFilter</em> e <em>IActionFilter</em> herda da classe filter.

A terminologia aqui não é perfeitamente consistente.Tecnicamente,uma classe que herda da classe <em>ActionFilterAttribute</em> é tanto um Action Filter quanto um Result Filter.O termo Action Filter é usado para se referir a qualquer tipo de filter no ASP.NET MVC.

A classe <em>ActionFilterAttribute</em> possui os seguintes métodos que você pode sobrescrever:

  • OnActionExecuting – Esse método é chamado antes de uma action ser executada
  • OnActionExecuted – Esse método é chamado depois de uma action ser executada
  • OnResultExecuting – Esse método é chamado antes de uma action result ser executada
  • OnResultExecuting – Esse método é chamado depois de uma action result ser executada

Vamos ver como implementar esses métodos.

Criando um Action Filter de Log

Pra ilustrar como criar nosso próprio action filter,nós iremos criar um filter que registre os estágios de processo de uma action para a janela Output do Visual Studio.Segue abaixo:

using System;
using System.Diagnostics;
using System.Web.Mvc;
using System.Web.Routing; 

namespace MvcApplication1.ActionFilters
{
public class LogActionFilter : ActionFilterAttribute

{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
Log(“OnActionExecuting”, filterContext.RouteData);
}

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
Log(“OnActionExecuted”, filterContext.RouteData);
}

public override void OnResultExecuting(ResultExecutingContext filterContext)
{
Log(“OnResultExecuting”, filterContext.RouteData);
}

public override void OnResultExecuted(ResultExecutedContext filterContext)
{
Log(“OnResultExecuted”, filterContext.RouteData);
}

private void Log(string methodName, RouteData routeData)
{
var controllerName = routeData.Values[“controller”];
var actionName = routeData.Values[“action”];
var message = String.Format(“{0} controller:{1} action:{2}”, methodName, controllerName, actionName);
Debug.WriteLine(message, “Action Filter Log”);
}

}
}

Os métodos OnActionExecuting, OnActionExecuted,OnResultExecuting e OnResultExecuted chamam o método Log.O nome do método e a RouteData são passados para o método Log.O método Log escreve uma mensagem na janela output do Visual Studio conforme abaixo:

O HomeController abaixo ilustra como podemos aplicar o Log Action Filter para um controle inteiro.Quando qualquer das actions deste controle for chamada,(Index ou About) os estagios do processo de execução serão mostrados na janela Output do Visual Studio.

using System.Web.Mvc;
using MvcApplication1.ActionFilters; 

namespace MvcApplication1.Controllers
{
[LogActionFilter]
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}

public ActionResult About()
{

return View();
}
}
}

É isso aí!Até a próxima pessoal!

Como tratar exceptions

Há duas maneiras de tratar uma exception e dar um re-throw na mesma ,abaixo seguem dois trechos de código:

Código 1:

1: try
2: {
3:
4: }
5: catch(Exception ex)
6: {
7:         throw ex;
8: }

Código 2:

1: try
2: {
3:
4: }
5: catch(Exception ex)
6: {
7:           throw;
8: }

Quando você usa o código 1,você vair dar um Throw no mesmo objeto Exception e como resultado o stack trace original será perdido.O código 2,mantém o stack trace original e isso é muito útil para debugar.

Um dos guias sobre tratamentos de exceptions diz:


Não de um re-throw jogando o mesmo objeto de exception.Isso faz com que o stack trace original da exception seja perdido;use somente “throw”,para dar um re-throw na exception.

A melhor maneira de ver a diferença,é nesse código de exemplo:

1: class Program
2: {
3: static void Main(string[] args)
4: {
5: try
6: {
7:            Method1();
8: }
9: catch (Exception ex)
10: {
11:           throw;
12: }
13: }
14:
15: public static void Method1()
16: {
17:            Method2();
18: }
19:
20: public static void Method2()
21: {
22:            throw new Exception();
23: }
24: }

O seguintestack trace será gerado com o exemplo acima:

at ConsoleApplication2.Program.Method2()
at ConsoleApplication2.Program.Method1()
at ConsoleApplication2.Program.Main(String[] args)
at System.AppDomain.ExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()

Quando você dá um throw em ex;ao invés de throw você recebe:

at ConsoleApplication2.Program.Main(String[] args)
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()

Como você pode ver o stack trace não possui a chamada dos métodos 1 e 2,então quando você usa throw ex,você pede informações essenciais do debug.

Conhecendo paths ASP.NET

Conhecendo paths ASP.NET

O ASP.NET contém muitas propriedades para recuperar informação sobre paths da requisição atual,controle e aplicação.
Há muita informação sobre paths no objeto Request,alguns desses são pra sobrepor e outros vão a níveis mais baixos do path,por isso pode ser confuso achar apenas o caminho certo que você está procurando.

Eu achei uma boa idéia listar as opções de path junto com sua descrição e um exemplo.

Aqui está uma lista de propriedades relacionada com o objeto Request e o objeto Page.Tomamos como exemplo o caminho http://www.webabstract.com/webclass/learn/paths.aspx, onde webclass é o nome do virtual.

Propriedade do Request Descrição e valor
ApplicationPath Retorna a raiz-relativa lógica da pasta virtual da aplicação
/webclass/
PhysicalApplicationPath Retorna o caminho local (FileSystem) da pasta virtual da aplicação
c:\inetpub\wwwroot\webclass
PhysicalPath Retorna o caminho local do script
atual
ou do path atual
c:\inetpub\wwwroot\webclass\learn\paths.aspx
Path

FilePath

CurrentExecutionFilePath

Todos esses retornam o caminho lógico completo da raiz-relativa incluindo paths e nome de scripts.CurrentExecutionFilePath <br />retorna o caminho da requisição atual,depois de um Transfer enquanto FilePath sempre retorna o caminho original da requisição
/webclass/learn/paths.aspx
AppRelativeCurrentExecutionFilePath Retorna o caminho virtual da raiz-relativa do script ou caminho da requisição atual.<br />Se estiver num Transfer o caminho da transferencia é que é retornado
~/learn/paths.aspx
PathInfo Retorna qualquer extra path depois do nome do script.Se não houver extra path retorna o caminho da raiz-relativa.
/webclass/learn/paths.aspx/ExtraPathInfo
RawUrl Retorna a URL completa da raiz-relativa incluindo QueryString e Extra Path

/webclass/learn/paths.aspx?nome=DotNet
Url Retorna a URL completa incluindo QueryString e ExtraPath.Note que retorna uma instancia do objeto Uri ao invés de string.

http://www.webabstract.com/webclass/learn/paths.aspx?nome=DotNet

UrlReferrer Retorna a URL completa da página que enviou a requisição.Também retorna uma instância do objeto Uri e retorna NULL se a página foi acessada diretamente sendo digitada na barra de endereço.

http://www.webabstract.com/webclass/learn/default.aspx?Info

Como você pode ver,há muita informação disponível pra cada um dos 3 formatos de path comuns:

  • Caminho Físico (Physical Path):
    é um caminho do tipo do OS que aponta para um caminho ou arquivo no disco.
  • Caminho lógico (Logical Path):
    é um caminho Web que é relativo a raiz do servidor.
  • ~/(raiz-relativa) Path:
    é um caminho especifico do ASP.NET que inclue ~/ pra indicar a raiz virtual do caminho Web.O ASP.NET pode converter caminhos virtuais tanto em caminhos lógicos usando Control.ResolveUrl() ou caminhos fisicos usando Server.MapPath().Caminhos de raiz-relativa são uteis para especificar URL móveis que não dependem da estrutura de diretórios relativa e muito util para uso em controles ou componentes.

Você deve conseguir pegar qualquer formato de path ou script necessário do ASP.NET usando esses mecanismos

Internet Explorer 9 adiciona integração inovadora com o desktop

Eu usei o Internet Explorer 9 por alguns dias e achei bom.O  navegador tem uma interface limpa,agora mais parecido com  o que vimos nos navegadores Firefox e Chrome.

Como você provavelmente já deve ter ouvido falar ele está bastante rápido.Parece que a microsoft está finalmente preocupada em criar um bom navegador.

Eles também adicionaram algumas coisas inovadoras no browser,que permitem forte integração com o Windows 7.Leia esse artigo no MSDN pra ver como você pode utilizar essa nova funcionalidade.

Alguns sites já estão utilizando isso.Abaixo está um Jump List disponibilizado pelo site Amazon.com.

E isso é só o começo,há thumbnails toolbars,icons overlay,notificações e muito mais!

Como Desktop e Web continuam interagindo fortemente,esta ferramenta nova cai como uma mão na roda!