3. Controladores, Ações, Encaminhamento
Consideremos a arquitetura de uma aplicação ASP.NET MVC:
![]() |
Neste capítulo, analisamos o processo que leva a solicitação [1] ao controlador e à ação [2a] que irão processá-la, um mecanismo a que se chama encaminhamento. Apresentamos ainda as diferentes respostas [3] que uma ação pode enviar ao navegador. Estas podem ser outras coisas além de uma vista V [4b].
3.1. A estrutura de um projeto ASP.NET MVC
Vamos criar um primeiro projeto ASP.NET MVC com o Visual Studio Express 2012. Vamos adicioná-lo [1] à solução utilizada no capítulo anterior:
![]() |
![]() |
- em [2], o nome do novo projeto;
- em [3, 4], escolhemos um projeto base ASP.NET MVC. Este modelo fornece-nos uma aplicação Web vazia, mas com todos os recursos (DLL, bibliotecas JavaScript, ...) necessários para trabalhar.
O projeto resultante é apresentado em [5]. Faremos deste o projeto inicial da solução, com o [6]:
![]() |
Em [5], destacam-se os seguintes pontos:
- a arquitetura do projeto reflete o seu modelo MVC:
- os controladores C serão colocados na pasta [Controllers],
- os modelos de dados M serão colocados na pasta [Models],
- as vistas V serão colocadas na pasta [Views],
![]() |
- em [1], o ficheiro [Site.css] será o ficheiro CSS por predefinição da aplicação;
- em [2], estão à nossa disposição várias bibliotecas JavaScript;
- em [3], encontram-se três vistas específicas: _ViewStart, _Layout e Error.
O ficheiro [_ViewStart] é o seguinte:
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
- linha 1: o caractere @ indica uma sequência de C# na vista. De facto, é possível incluir código C# numa vista;
- linha 2: define uma variável Layout que define a vista pai de todas as vistas. Corresponde à página mestre do framework ASP.NET clássico.
O ficheiro [_Layout] é o seguinte:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
<body>
@RenderBody()
@Scripts.Render("~/bundles/jquery")
@RenderSection("scripts", required: false)
</body>
</html>
Quando uma vista da pasta [Views] for renderizada, o seu corpo será renderizado pela linha 11 acima. Isto significa que a vista não precisa de incluir as tags <html>, <head> e <body>. Estas são fornecidas pelo ficheiro acima. Por enquanto, este ficheiro é bastante hermético. Vamos simplificá-lo:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Tutoriel ASP.NET MVC</title>
</head>
<body>
<h2>Tutoriel ASP.NET MVC</h2>
@RenderBody()
</body>
</html>
- linha 6: o título comum a todas as visualizações;
- linha 9: o cabeçalho comum a todas as visualizações;
- linha 10: o conteúdo específico da vista apresentada.
![]() |
- [Web.config] é o ficheiro de configuração da aplicação Web. É complexo. Será necessário alterá-lo quando se utilizar o framework [Spring.net] numa arquitetura multicamadas.
- [Global.asax] contém o código executado no arranque da aplicação. Em geral, este código utiliza os diferentes ficheiros de configuração da aplicação, incluindo o [Web.config].
3.2. O encaminhamento por predefinição do URL
O código de [Global.asax] é, de momento, o seguinte:
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
namespace Exemple_01
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
...
}
}
}
- linha 6, o namespace da classe. Provém diretamente do nome do projeto e está presente nas propriedades do projeto:

![]() |
Definimos [1] como o espaço de nomes predefinido. Este será então utilizado por predefinição para todas as classes que forem criadas no projeto.
Voltemos ao código de [Global.asax]:
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
namespace Exemple_01
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
...
}
}
}
- linha 9: a classe [MvcApplication] deriva da classe [HttpApplication]. O nome [MvcApplication] pode ser alterado;
- linha 11: o método [Application_Start] é o método executado no arranque da aplicação Web. É executado apenas uma vez. É aqui que se inicializa a aplicação.
O código de [Application_Start] é atualmente o seguinte:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
Por enquanto, não é necessário compreender todo este código. As linhas 5 a 8 definem as rotas aceites pela aplicação Web. Voltemos à arquitetura de uma aplicação ASP.NET MVC:
![]() |
Já explicámos que o [Front Controller] deve encaminhar um URL para a ação responsável pelo seu processamento. Uma rota serve para estabelecer a ligação entre um modelo de URL e uma ação. Estas rotas são definidas na pasta [App_Start] do projeto pelas classes [WebApiConfig, FilterConfig, RouteConfig, BundleConfig]:
![]() |
Por enquanto, apenas a classe [RouteConfig] nos interessa:
using System.Web.Mvc;
using System.Web.Routing;
namespace Exemple_01
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}
As linhas 12 a 16 definem o formato dos URL aceites pela aplicação. A isto chama-se uma rota. Podem existir várias rotas possíveis (= vários modelos possíveis de URL). Distinguem-se entre si pelo nome (linha 13). O formato dos URL da rota é definido na linha 14. Aqui, o URL terá três componentes:
- {controller}: o nome de uma classe derivada de [Controller]. Será procurada na pasta [Controllers] do projeto. Por convenção, se o URL for /X/Y/Z, o controlador responsável por processar este URL será a classe XController. O sufixo Controller é adicionado ao nome do controlador presente no URL;
- {action}: o nome de um método no controlador acima referido. É este método que irá receber os parâmetros que acompanham o URL e que os irá processar. Este método pode devolver vários resultados:
- void: a ação irá construir ela própria a resposta para o navegador do cliente
- String: a ação devolve ao cliente uma cadeia de caracteres;
- ViewResult: devolve uma vista ao cliente;
- PartialViewResult: devolve uma vista parcial;
- EmptyResult: é enviada uma resposta vazia ao cliente;
- RedirectResult: solicita ao cliente que se redirecione para um URL
- RedirectToRouteResult: o mesmo, mas a URL é construída a partir de rotas da aplicação;
- JsonResult: envia uma resposta JSON
- JavaScriptResult: devolve um código JavaScript ao cliente;
- ContentResult: devolve um fluxo HTML ao cliente sem passar por uma vista;
- FileContentResult: devolve um ficheiro ao cliente;
- FileStreamResult: o mesmo, mas por outro meio;
- FilePathResult: ...
- {id}: um parâmetro que será transmitido à ação. Para tal, a ação deverá ter um parâmetro denominado id.
A linha 15 define valores por predefinição quando o URL não tem o formato esperado /{controller}/{action}/{id}. Indica também que o parâmetro {id} no URL é opcional. Segue-se uma lista de URL incompletas e a URL preenchida com os valores por predefinição:
URL original | URL preenchido |
/ | /Home/Índice |
/Do | /Fazer/Índice |
/Do/Something | /Fazer/Algo |
/Fazer/Algo/4 | /Fazer/Algo/4 |
/Fazer/Algo/x/y/z | URL não encaminhada |
3.3. Criação de um controlador e de uma primeira ação
Vamos criar um primeiro controlador:
![]() |
![]() |
- em [1], atribua o nome do controlador com o seu sufixo [Controller];
- em [2], crie um controlador MVC vazio;
- em [3], foi criado.
O código de [FirstController] é o seguinte:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Exemple_01.Controllers
{
public class FirstController : Controller
{
//
// GET: /First/
public ActionResult Index()
{
return View();
}
}
}
- linha 7: foi gerado um namespace por predefinição;
- linha 9: a classe [FirstController] deriva da classe [System.Web.Mvc.Controller];
- linhas 14-17: foi gerada por predefinição uma ação [Index]. É pública. Isto é importante, caso contrário não será encontrada. Retorna um tipo [ActionResult], que é uma classe abstrata da qual derivam a maioria dos resultados que uma ação normalmente retorna. Trata-se de um tipo «genérico» que pode ser especificado, substituindo-o pelo nome real do tipo devolvido;
- linha 16: o método não faz nada. Limita-se a devolver uma vista, ou seja, um tipo [ViewResult]. O nome da vista não é especificado. Neste caso, o framework procura na pasta [Views / First] uma vista com o nome da ação, ou seja, neste caso: [Index.cshtml].
Vamos criar a vista [Index.cshtml]:
![]() |
- em [1], clica-se com o botão direito do rato no código da ação e seleciona-se a opção [Ajouter une vue];
- em [2], o assistente sugere uma vista com o nome da ação. É isso que queremos aqui;
- em [3], por predefinição, é sugerida a utilização da página-mestre [_Layout.cshtml];
- em [4], uma vez validada, o assistente cria a vista numa subpasta da pasta [Views] com o nome do controlador (First).
O código gerado para a vista [Index] é o seguinte:
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
- linhas 1-3: código C# que define uma variável;
- linha 5: uma baliza HTML.
Substitui-se todo o código anterior por este:
<strong>Vue [Index]...</strong>
Resumindo:
- temos um controlador C chamado [First];
- temos uma ação chamada [Index] que solicita a exibição de uma vista chamada [Index];
- temos a vista V [Index].
Podemos chamar a ação [Index] de duas formas:
- /First/Index;
- /First, uma vez que [Index] é também a ação por predefinição nas rotas.
Vamos executar a aplicação (CTRL-F5). Obtemos a seguinte página:
1

Em [1], a ação solicitada foi http://localhost:49302. Não existe qualquer caminho. Sabemos que o nosso router espera ações da forma /{controller}/{action}/{id}. Como estes elementos estão ausentes, são utilizados os valores por predefinição. A URL passa a ser http://localhost:49302/Home/Index. O controlador [Home] não existe. Por isso, a URL é rejeitada.
Vamos agora tentar o URL http://localhost:49302/First/Index, digitando-o diretamente no navegador:
![]() |
A página acima foi gerada pela ação [Index] do controlador [First]. A página gerada por esta ação é a vista [Index], cujo código era o seguinte:
<strong>Vue [Index]...</strong>
Esta ação gera a parte [1]. A parte [2], por sua vez, provém da página mestre [_Layout] que definimos anteriormente:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Tutoriel ASP.NET MVC</title>
</head>
<body>
<h2>Tutoriel ASP.NET MVC</h2>
@RenderBody()
</body>
</html>
A linha 9 gerou a parte [2] da página. A vista [Index], por sua vez, só aparece na linha 10.
Se visualizarmos o código-fonte da página recebida, verificamos que a página [Index] está, de facto, incluída (linha 10 abaixo) na página [Layout]:
Vamos agora experimentar o URL e o [/First]:
![]() |
O URL [/First] estava incompleto. Foi preenchido com os valores por predefinição do percurso e passou a ser [/First/Index]. Obtém-se, assim, o mesmo resultado que anteriormente.
3.4. Ação com um resultado do tipo [ContentResult] - 1
Vamos criar uma nova ação no controlador [First]:
using System.Text;
using System.Web.Mvc;
namespace Exemple_01.Controllers
{
public class FirstController : Controller
{
// Índice
public ViewResult Index()
{
return View();
}
// Ação01
public ContentResult Action01()
{
return Content("<h1>Action [Action01]</h1>", "text/plain", Encoding.UTF8);
}
}
}
A nova ação está definida nas linhas 14-18. Limita-se a devolver uma cadeia de caracteres utilizando o método [Content] (linha 16) da classe [Controller] (linha 6). Os parâmetros do método são:
- a cadeia de caracteres da resposta;
- um indicador da natureza do texto enviado: «text/plain», «text/html», «text/xml», ... Este indicador é designado por tipo MIME (http://fr.wikipedia.org/wiki/Type_MIME);
- o terceiro parâmetro permite especificar o tipo de codificação utilizado para o texto.
Em vez de utilizar o tipo abstrato [ActionResult], os nossos métodos especificam o tipo real resultante (linhas 9 e 14).
Vamos solicitar o URL [/First/Action01]. Obtemos a seguinte página:
![]() |
Vejamos o código-fonte da página recebida:
O navegador recebeu apenas o texto enviado pela ação e nada mais. Este modo é interessante quando se pretende solicitar ao servidor Web dados puros, sem a estrutura HTML à sua volta. Note-se, acima, que o navegador não interpretou a baliza <h1>. Para compreender porquê, vamos analisar, no Chrome, as trocas de dados:
O navegador enviou os seguintes cabeçalhos:
O servidor respondeu com os seguintes cabeçalhos:
- linha 3: define a natureza do documento. Encontramos aqui os atributos definidos no método [Action01]. Foi porque lhe foi indicado que o documento era do tipo «text/plain» e não «text/html» que o navegador não interpretou a baliza <h1> que se encontrava no documento recebido.
3.5. Ação com um resultado do tipo [ContentResult] - 2
Consideremos a seguinte terceira ação:
using System.Text;
using System.Web.Mvc;
namespace Exemple_01.Controllers
{
public class FirstController : Controller
{
...
// Ação02
public ContentResult Action02()
{
string data = "<action><name>Action02</name><description>renvoie un texte XML</description></action>";
return Content(data, "text/xml", Encoding.UTF8);
}
}
}
- linha 12: define-se um texto XML;
- linha 13: envia-se esse texto para o navegador, especificando que se trata de XML com o tipo MIME «text/xml».
No navegador, obtém-se a seguinte página:
![]() |
Vejamos no Chrome a resposta HTTP do servidor:
- linha 3: define a natureza do documento. Encontramos aqui os atributos definidos no método [Action02];
- linha 12: o tamanho, em bytes, do documento enviado pelo servidor.
O documento enviado pelo servidor é este (cópia do Chrome):
![]() |
3.6. Ação com um resultado do tipo [JsonResult]
Vamos adicionar a seguinte ação ao controlador [First]:
// Ação03
public JsonResult Action03()
{
dynamic personne = new ExpandoObject();
personne.nom = "someone";
personne.age = 20;
return Json(personne,JsonRequestBehavior.AllowGet);
}
- linha 4: uma variável do tipo dynamic. Durante a execução, é possível adicionar livremente propriedades a essa variável. A propriedade é criada ao mesmo tempo que é inicializada;
- linhas 5-6: inicializam-se duas propriedades nom e age;
- linha 7: devolve a representação JSON (Javascript Object Notation) do objeto. O JSON permite serializar um objeto numa cadeia de caracteres e, inversamente, deserializar uma cadeia num objeto. É uma alternativa à serialização/deserialização XML;
- linha 2: a ação devolve um tipo [JsonResult]. Este tipo só pode ser devolvido para um pedido POST. Se se pretender devolvê-lo para um método GET, é necessário atribuir ao segundo parâmetro do construtor da classe Json (linha 7) o valor JsonRequestBehavior.AllowGet.
Quando se solicita o URL [/First/Action03], o navegador apresenta o seguinte:
![]() |
A resposta HTTP do servidor é a seguinte:
- linha 3: indica que o documento enviado é o JSON;
- linha 10: o documento enviado tem 58 bytes. É o seguinte:
O elemento dinâmico [personne] é visto pelo JSON como uma matriz de dicionários, em que cada dicionário:
- corresponde a um campo da variável [personne];
- tem duas chaves: «Key» e «Value». A chave «Key» tem como valor associado o nome do campo e a chave «Value» tem como valor o valor do campo.
3.7. Ação com um resultado do tipo [string]
Adicionemos a seguinte ação ao controlador [First]:
// Ação04
public string Action04()
{
return "<h3>Contrôleur=First, Action=Action04</h3>";
}
Quando solicitamos o URL [/First/Action04] com o Chrome, obtemos a seguinte resposta:
![]() |
Vemos que a tag <h3> foi interpretada. Vejamos a resposta HTTP do servidor:
e o documento seguinte:
Na linha 3, verifica-se que o servidor indicou que enviou texto no formato HTML. É por isso que o navegador interpretou a baliza <h3>. Quando se pretende enviar texto simples, é, portanto, preferível devolver um [ContentResult] em vez de um [string]. O [ContentResult] permite-nos, de facto, especificar um tipo MIME «text/plain» para indicar que estamos a enviar texto não formatado, pelo que não está sujeito a interpretação por parte do navegador.
3.8. Ação com um resultado do tipo [EmptyResult]
Consideremos a seguinte nova ação:
// Ação05
public EmptyResult Action05()
{
return new EmptyResult();
}
A ação limita-se a devolver um tipo [EmptyResult]. Neste caso, o servidor envia uma resposta vazia ao cliente, tal como mostra a sua resposta HTTP:
- linha 9: o servidor indica ao seu cliente que lhe está a enviar um documento vazio.
3.9. Ação com um resultado do tipo [RedirectResult] - 1
Consideremos a seguinte nova ação:
// Ação06
public RedirectResult Action06()
{
return new RedirectResult("/First/Action05");
}
A ação devolve um tipo [RedirectResult]. Este tipo permite enviar ao cliente uma ordem de redirecionamento para o parâmetro URL do construtor (linha 4). O cliente irá então emitir um novo pedido GET para [/First/Action05]. O cliente efetua, assim, dois pedidos no total.
O navegador apresenta o resultado da segunda solicitação:
![]() |
Analisemos a resposta HTTP do servidor no Chrome:
![]() |
Como se pode ver acima, estas são as duas solicitações do navegador. Vamos analisar a primeira solicitação, [Action06]. A resposta do servidor, HTTP, é a seguinte:
- linha 1: o servidor respondeu com um código 302 Found. Até agora, era 200 OK, o que significa que o documento solicitado foi encontrado. O código 302 indica que é solicitada uma redireção. O endereço de redirecionamento é indicado na linha 4. Encontramos aqui o endereço de redirecionamento que tínhamos especificado no código da ação;
- linha 11: o servidor indica que, com a sua resposta HTTP, está a enviar um documento do tipo text/html (linha 3) com 132 octetos (linha 11). Quando se examina no Chrome a resposta à solicitação [Action06], esta está vazia, como seria de esperar. Provavelmente há uma explicação, mas desconheço-a.
Devido ao redirecionamento, o navegador efetua uma nova solicitação GET para o URL indicado na linha 4 acima, como se pode ver no Chrome, na linha 1 abaixo:
3.10. Ação com um resultado do tipo [RedirectResult] - 2
Ou seja, a seguinte nova ação:
// Ação07
public RedirectResult Action07()
{
return new RedirectResult("/First/Action05",true);
}
Na linha 4, foi adicionado um segundo parâmetro ao construtor do tipo [RedirectResult]. Trata-se de um valor booleano cujo valor por predefinição é false. Quando se define este parâmetro como true, altera-se a resposta HTTP enviada ao cliente. Passa a ser:
Assim, o código de resposta enviado ao cliente é agora 301 Moved Permanently. O redirecionamento ocorre como anteriormente, mas indica-se que este redirecionamento é permanente. Isto permite que os motores de busca substituam, nos seus resultados, o antigo URL pelo novo.
3.11. Ação com um resultado do tipo [RedirectToRouteResult]
Consideremos a seguinte nova ação:
// Ação08
public RedirectToRouteResult Action08()
{
return new RedirectToRouteResult("Default",new RouteValueDictionary(new {controller="First",action="Action05"}));
}
- linha 2: a ação devolve um tipo [RedirectToRouteResult]. Este tipo permite redirecionar um cliente para um URL especificado não por uma cadeia de caracteres, como anteriormente, mas por uma rota.
As rotas são definidas em [App_Start/RouteConfig]. Atualmente, existe apenas uma:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
- na linha 4, solicita-se ao cliente que se redirecione para a rota denominada [Default] com a variável controller=First e a variável action=Action05. O sistema de encaminhamento irá então gerar a rota de redirecionamento URL a partir de /First/Action05. É isso que mostra a resposta HTTP do servidor:
- linha 1: o redirecionamento;
- linha 4: o endereço de redirecionamento gerado pelo sistema de encaminhamento do URL.
3.12. Ação com um resultado do tipo [void]
Ou seja, a seguinte nova ação:
// Ação09
public void Action09()
{
string nom = Request.QueryString["nom"] ?? "inconnu";
Response.AddHeader("Content-Type", "text/plain");
Response.Write(string.Format("<h3>Action09</h3>nom={0}", nom));
}
- linha 2: a ação não devolve qualquer resultado. Ela própria escreve no fluxo da resposta enviada ao cliente;
- linha 4: recupera-se um eventual parâmetro denominado [nom] na solicitação. Este parâmetro está acessível através da propriedade [Request] do controlador [Controller], do qual o controlador [First] herda. O parâmetro [nom], passado na forma [/First/Action09?nom=quelquechose], está disponível em Request.QueryString["nom"]. A sintaxe da linha 4 é equivalente a:
- linha 5: a resposta enviada ao cliente está acessível através da propriedade [Response] do controlador [Controller], do qual herda o controlador [First];
- linha 5: define-se o cabeçalho HTTP [Content-Type], que indica a natureza do documento que o servidor se prepara para enviar ao cliente. Aqui, «text/plain» indica que o documento é texto simples que não deve ser interpretado pelo navegador;
- linha 6: insere-se no fluxo da resposta uma cadeia de caracteres. Nela foram incluídas balizas HTML que não devem ser interpretadas pelo navegador, uma vez que este terá recebido anteriormente o cabeçalho HTTP [Content-Type : text/plain"]. É isso que queremos verificar.
Vamos compilar o projeto e solicitar o URL [/First/Action09?nom=someone ][1] e, em seguida, oURL [/First/Action09 ] [2]:
![]() |
Vamos agora ver no Chrome a resposta HTTP do servidor:
- linha 3: encontramos o cabeçalho HTTP que nós próprios definimos no código da ação.
3.13. Um segundo controlador
Vamos criar um segundo controlador no projeto. Seguiremos o método descrito no parágrafo 3.1, página 40. Vamos chamá-lo de [Second].
![]() |
O código gerado é o seguinte:
namespace Exemple_01.Controllers
{
public class SecondController : Controller
{
//
// GET: /Segundo/
public ActionResult Index()
{
return View();
}
}
}
Vamos alterá-lo da seguinte forma:
using System.Text;
using System.Web.Mvc;
namespace Exemple_01.Controllers
{
public class SecondController : Controller
{
// /Segundo/Ação01
public ContentResult Action01()
{
return Content("Contrôleur=Second, Action=Action01", "text/plain", Encoding.UTF8);
}
}
}
Em seguida, solicitemos o URL [/Second/Action01] num navegador. Obtemos a seguinte resposta:
![]() |
Este URL foi solicitado com um comando HTTP GET, tal como mostram os registos HTTP da solicitação no Chrome:
O URL também pode ser solicitado com os comandos HTTP e POST. Para demonstrar isso, vamos utilizar novamente a aplicação [Advanced Rest Client]:
![]() |
- em [1], iniciamos a aplicação (no separador [Applications] de um novo separador do Chrome);
- em [2], selecionamos a opção [Request];
- em [3], especifica-se a URL solicitada;
- em [4], indica-se que o URL deve ser solicitado com um POST;
Ativam-se os registos do Chrome através de (CTRL-I) para obter a resposta HTTP do servidor. Ao executar o [Send], a solicitação anterior, as trocas de dados HTTP são as seguintes:
O navegador envia a seguinte solicitação:
- linha 1: o URL é efetivamente solicitado com um POST;
- linha 4: o tamanho em bytes dos elementos enviados. Aqui não há nenhum.
A resposta HTTP do servidor é a seguinte:
- linha 3: o servidor envia um documento de texto sem formatação (plain);
- linha 12: com 148 caracteres.
O documento enviado é o seguinte:
![]() |
Obtém-se o mesmo documento que com o GET.
3.14. Ação filtrada por um atributo
Vamos criar a seguinte nova ação:
// /Segundo/Ação02
[HttpPost]
public ContentResult Action02()
{
return Content("Contrôleur=Second, Action=Action02", "text/plain", Encoding.UTF8);
}
A ação [Action02] é análoga à ação [Action01], mas indica-se que só é acessível através de um comando HTTP POST (linha 2). Podem ser utilizados outros atributos:
HttpGet | serve apenas para o comando GET |
HttpHead | serve apenas para o comando HEAD |
HttpOptions | serve apenas para o comando OPTIONS |
HttpPut | serve apenas para o comando PUT |
HttpDelete | serve apenas para o comando DELETE |
Vamos solicitar o URL [/Second/Action02] diretamente no navegador. Este é então solicitado por um GET. O navegador apresenta então a seguinte resposta:
![]() |
A resposta HTTP do servidor foi a seguinte:
- linha 1: o código HTTP 404 Not Found indica que o servidor não encontrou o documento solicitado. Neste caso, a ação [Action02] não conseguiu atender ao pedido GET, uma vez que apenas atende aos comandos POST;
- linha 3: o tamanho do documento devolvido. Trata-se da página que foi apresentada pelo navegador:
![]() |
3.15. Recuperar os elementos de um percurso
Nas duas ações descritas anteriormente, escrevíamos algo do género:
public ContentResult Action02()
{
return Content("Contrôleur=Second, Action=Action02", "text/plain", Encoding.UTF8);
}
Os nomes do controlador e da ação estavam fixos no código. Se alterarmos esses nomes, o código deixa de estar correto. Podemos aceder ao controlador e à ação da seguinte forma:
// /Segundo/Ação03
public ContentResult Action03()
{
string texte = string.Format("Contrôleur={0}, Action={1}", RouteData.Values["controller"], RouteData.Values["action"]);
return Content(texte, "text/plain", Encoding.UTF8);
}
A rota definida em [App_Start/RouteConfig] é a seguinte:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Na linha 3, os três elementos da rota podem ser obtidos através de RouteData.Values["élément"], com o elemento em [controller, action, id].
Vamos solicitar o URL e o [http://localhost:49302/Second/Action03]:
![]() |
Conseguimos recuperar tanto o nome do controlador como o nome da ação.




























