Ou seja, se eu tenho a seguinte url: http://host/home/Index?p1=10&p2=no (e supondo a tabela de rotas por padrão), se invocará a ação Index de HomeController com dois parâmetros p1 (com valor 10) e p2 com valor "não". Assim no controlador poderíamos ter definida a ação da seguinte forma:
public ActionResult Index(int p1, string p2)
{
// Codigo...
}
Os nomes dos parâmetros devem coincidir com os nomes dos parâmetros da querystring. Bem, observem que dado que declaramos o parâmetro p1 como int só podemos passar valores inteiros, enquanto que no parâmetro p2, podemos passar qualquer cadeia. Se passamos uma cadeia no parâmetro p1, p.ex. a url http://host/home/index?p1=texto&p2=outrotexto o erro que recebemos é o seguinte:

O que ocorreu é que ASP.NET MVC tentou converter o valor de p1 ("texto") a um inteiro. Como não pode fazê-lo, internamente atribui null ao valor do parâmetro p1, porém depois quando deve invocar o método Index e passar-lhe um int percebe que int não aceita valores null. Daí o erro que recebemos.
Como poderíamos evitar isto? Bom, uma maneira fácil e simples é usar int? (ou seja Nullable
public ActionResult Index(int? p1, string p2)
Agora se invocamos a url e o valor de p1 não é numérico, nos chegará null, enquanto que se o valor
de p1 é numérico receberemos seu valor.
A regra é realmente muito simples: Se você quiser que um parâmetro de querystring seja opcional
deve usar um tipo por referência (ou seja uma classe como string ou Nullable
Pressiona <a href="/Home/View?pid=10">aquí</a> para ver os detalhes
Este código tem dois erros fundamentais.
Pressione <a href="@Url.Action("View","Home")?pid=10">aquí</a> para ver os
detalhes
Se executamos isso e olhamos o código HTML veremos que é exatamente o que havíamos teclado
antes (porque usamos a tabela de rotas standard). Porém, se acrescento uma entrada à tabela de
rotas, deixando-a assim:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
Agora a URL que é gerada usando Url.Action é a seguinte:
Pressione <a href="/VerProducto?pid=10">aquí</a> para ver os detalhes
Portanto, sempre que vocês necessitem obter uma URL a partir de uma visão , usem Url.Action
lembrem que o formato real das URLs depende da tabela de rotas. Assumir que sempre estarão na
forma /controlador/ação é uma má prática (e como disse antes, um erro comum no começo).
Os parâmetros de rota são os que colocamos na URL separados pela barra, ou seja: http://host/
controlador/ação/10. Neste caso 10 é o valor de um parâmetro de rota. De qual? Pois o nome deve
estar explicitado na tabela de rotas. Vamos supor que usamos a tabela de rotas standard. Neste caso
o nome de tal parâmetro é id. Agora eu pergunto a vocês o que aconteceria se usássemos a URL
http://host/controlador/ação/10?id=20 ?
Observem que a questão não é sem importância: estamos passando a nosso controlador:
Pois o que receberemos em nossa ação será o valor do parâmetro de rota (ou seja, 10 em lugar de
20):
Isso se deve ao que comentávamos antes: ASP.NET MVC mistura todos os parâmetros que lhe
chegam antes de juntá-los com os controladores e o faz de acordo com uma certa prioridade. E
os parâmetros de rota (cujo nome se define na tabela de rotas) têm mais prioridade. Isso deveria
tê-lo em conta quando gero URLs, ou seja, neste caso deveria gerar URLs usando a convenção /
controlador/ação/valor_id antes que /controlador/ação?id=valor_id
No final isso implica que não deveríamos nunca gerar as URLs com parâmetros querystring
acrescentados manualmente. Para nossa sorte o helper Url.Action que vimos antes vem de novo em
nossa ajuda. Em uma de suas sobrecargas Url.Action aceita um objeto anônimo cujas propriedades
são os valores a serem mandados ao controlador. Url.Action é o suficientemente inteligente para
usar valores de rota se estão definidos e querystring no caso de que não!
Desse modo se temos a tabela de rotas standard e temos as seguintes chamadas a Url.Action:
Url 1: @Url.Action("Index", "Home", new { id = 20 })
A resposta gerada por essa visão é a seguinte:
Url 1: /Home/Index/20
Não é uma maravilha? Url.Action sabe que id é um parâmetro de rota e o coloca como tal. E sabe
que outro_id não é e o coloca usando query_string. Neste caso temos a ação definida no controlador
:
public ActionResult Index(string id, string outro_id)
Observem como a partir do controlador recebemos de igual maneira parâmetros de rota e
parâmetros que venham por querystring :)
No artigo seguinte do tutorial vamos ver como mandar dados de formulários para as visões, ou seja
como usar POST.
{
// Codigo
}
Gerar URLs com querystrings a partir das visões
Um dos erros mais frequentes em ASP.NET MVC é ter código nas visões que seja parecido a este:
Para solucionar o primeiro ponto, o que devemos fazer é usar o Helper Url. Os Helpers são classes
que nos proporcionam mecanismos de ajuda (de série vêm alguns que iremos vendo e podem
ser criados deles próprios), para nos ajudar com tarefas repetitivas. Para gerar uma URL que
respeite a tabela de rotas devemos usar o método Url.Action. Sua assinatura básica é Url.Action
("ação", "controlador"). Assim podemos reescrever o código anterior da forma:
routes.MapRoute(
"Ver",
"VerProduto",
new {controller = "Home", action = "View"});
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter
defaults
);
Parâmetros querystring e route values
Vamos ver agora o que significa o segundo dos erros que cometíamos (passar os valores sempre
em querystring ignorando os valores de rota). Para evitar entrar demasiado em tecnicismos
direi que ASP.NET MVC mistura todos os parâmetros que chegam a ele antes de passá-los aos
controladores. A um controlador podem chegar parâmetros por três formas básicas (tudo bem, isso
não é totalmente certo, há mais formas mas vamos ignorá-las de momento): como parâmetros de
rota, como querystring e como POST (desses falaremos em um artigo posterior).
Ambos parâmetros (de rota e querystring) se mapeiam a parâmetros da ação do controlador. Sendo
assim, que valor receberemos no parâmetro id de nossa ação? Ou então ASP.NET MVC gerará um
erro?

Url 2: @Url.Action("Index", "Home", new { id = 20, outro_id=30})
Url 3: @Url.Action("Index", "Home", new {outro_id=30})
Url 2: /Home/Index/20?outro_id=30
Url 3: /?outro_id=30
{
return View();
}