No ASP.NET MVC, você pode retornar um ActionResult de redirecionamento facilmente:
return RedirectToAction("Index");
or
return RedirectToRoute(new { controller = "home", version = Math.Random() * 10 });
Isso realmente fornecerá um redirecionamento HTTP, o que normalmente é bom. No entanto, ao usar o Google Analytics, isso causa grandes problemas, pois o referenciador original está perdido, portanto o Google não sabe de onde você veio. Isso perde informações úteis, como quaisquer termos do mecanismo de pesquisa.
Como observação lateral, esse método tem a vantagem de remover qualquer parâmetro que possa ter sido proveniente de campanhas, mas ainda me permita capturá-los no servidor. Deixá-los na string de consulta leva as pessoas a marcarem favoritos, no twitter ou no blog, um link que não deveriam. Eu já vi isso várias vezes em que as pessoas enviaram links para o nosso site contendo IDs de campanha.
De qualquer forma, estou escrevendo um controlador de 'gateway' para todas as visitas recebidas no site que eu possa redirecionar para locais diferentes ou versões alternativas.
Por enquanto, eu me preocupo mais com o Google por agora (do que os marcadores acidentais) e quero poder enviar alguém que visite /
a página que eles obteriam se fossem /home/7
, que é a versão 7 de uma página inicial.
Como eu disse antes, se eu fizer isso, perco a capacidade do google de analisar o referenciador:
return RedirectToAction(new { controller = "home", version = 7 });
O que eu realmente quero é um
return ServerTransferAction(new { controller = "home", version = 7 });
o que me proporcionará essa visualização sem um redirecionamento do lado do cliente. Eu não acho que isso exista.
Atualmente, a melhor coisa que posso criar é duplicar toda a lógica do controlador HomeController.Index(..)
em minha GatewayController.Index
ação. Isso significa que eu tinha que passar 'Views/Home'
para 'Shared'
então era acessível. Deve haver uma maneira melhor ?? ..
fonte
ServerTransferAction
você está tentando replicar? Isso é uma coisa real? (não poderia encontrar qualquer informação sobre ele ... obrigado pela pergunta, btw, a resposta abaixo é excelente)if
declaração simples é uma solução tentadora demais.RouteBase
para que você possa colocar suaif
declaração lá em vez de dobrar tudo para trás para pular de um controlador para outro?Respostas:
Que tal uma classe TransferResult? (com base na resposta de Stans )
Atualizado: Agora funciona com MVC3 (usando o código da publicação de Simon ). Ele deve (não ter sido capaz de testá-lo) também trabalham em MVC2 olhando ou não ele está correndo dentro do pipeline integrado do IIS7 +.
Para total transparência; Em nosso ambiente de produção, nunca usamos o TransferResult diretamente. Usamos um TransferToRouteResult que, por sua vez, chama executa o TransferResult. Aqui está o que está realmente sendo executado nos meus servidores de produção.
E se você estiver usando o T4MVC (se não ... faça!), Esta extensão pode ser útil.
Usando esta pequena jóia você pode fazer
fonte
Editar: atualizado para ser compatível com o ASP.NET MVC 3
Desde que você esteja usando o IIS7, a seguinte modificação parece funcionar no ASP.NET MVC 3. Graças a @nitin e @andy por apontar o código original não funcionou.
Edit 11/11/2011: TempData quebra com Server.TransferRequest a partir do MVC 3 RTM
Modificado o código abaixo para gerar uma exceção - mas nenhuma outra solução no momento.
Aqui está minha modificação baseada na versão modificada de Markus da postagem original de Stan. Eu adicionei um construtor adicional para pegar um dicionário de Valor da Rota - e renomei-o para MVCTransferResult para evitar confusão de que poderia ser apenas um redirecionamento.
Agora posso fazer o seguinte para um redirecionamento:
Minha classe modificada:
fonte
Você pode usar Server.TransferRequest no IIS7 +.
fonte
Descobri recentemente que o ASP.NET MVC não suporta Server.Transfer (), por isso criei um método stub (inspirado no Default.aspx.cs).
fonte
Você não poderia simplesmente criar uma instância do controlador para o qual gostaria de redirecionar, invocar o método de ação desejado e retornar o resultado disso? Algo como:
fonte
otherController.ControllerContext = this.ControllerContext;
Eu queria redirecionar a solicitação atual para outro controlador / ação, mantendo o caminho de execução exatamente o mesmo como se o segundo controlador / ação fosse solicitado. No meu caso, Server.Request não funcionaria porque eu queria adicionar mais dados. Na verdade, é equivalente ao manipulador atual executando outro HTTP GET / POST e, em seguida, transmitindo os resultados para o cliente. Tenho certeza de que haverá maneiras melhores de conseguir isso, mas eis o que funciona para mim:
Seu palpite está certo: coloquei esse código em
e estou usando-o para exibir erros aos desenvolvedores, enquanto ele usa um redirecionamento regular na produção. Observe que eu não queria usar a sessão do ASP.NET, banco de dados ou outras formas de passar dados de exceção entre solicitações.
fonte
Em vez de simular uma transferência de servidor, o MVC ainda é capaz de realmente executar um Server.TransferRequest :
fonte
Apenas instale o outro controlador e execute seu método de ação.
fonte
Você pode reiniciar o outro controlador e chamar o método de ação retornando o resultado. Isso exigirá que você coloque sua exibição na pasta compartilhada.
Não tenho certeza se é isso que você quis dizer com duplicado, mas:
Editar
Outra opção pode ser criar seu próprio ControllerFactory, dessa forma você pode determinar qual controlador criar.
fonte
O roteamento não cuida desse cenário para você? ou seja, para o cenário descrito acima, você pode apenas criar um manipulador de rota que implemente essa lógica.
fonte
Para quem usa roteamento baseado em expressão, usando apenas a classe TransferResult acima, aqui está um método de extensão de controlador que executa o truque e preserva TempData. Não há necessidade de TransferToRouteResult.
fonte
Server.TransferRequest
é completamente desnecessário no MVC . Esse é um recurso antiquado que só era necessário no ASP.NET porque a solicitação veio diretamente para uma página e precisava haver uma maneira de transferir uma solicitação para outra página. As versões modernas do ASP.NET (incluindo MVC) têm uma infraestrutura de roteamento que pode ser personalizada para rotear diretamente para o recurso desejado. Não há sentido em deixar a solicitação chegar a um controlador apenas para transferi-la para outro controlador quando você pode simplesmente fazer com que a solicitação vá diretamente para o controlador e a ação que você deseja.Além disso, como você está respondendo à solicitação original , não há necessidade de colocar nada
TempData
ou outro armazenamento apenas para encaminhar a solicitação para o local certo. Em vez disso, você chega à ação do controlador com a solicitação original intacta. Você também pode ter certeza de que o Google aprovará essa abordagem, pois ela acontece inteiramente no lado do servidor.Embora você possa fazer bastante com ambos
IRouteConstraint
eIRouteHandler
, o ponto de extensão mais poderoso para roteamento é aRouteBase
subclasse. Essa classe pode ser estendida para fornecer rotas de entrada e geração de URL de saída, o que o torna um balcão único para tudo o que tem a ver com o URL e a ação que o URL executa.Portanto, para seguir seu segundo exemplo, para ir de
/
para/home/7
, basta uma rota que adicione os valores de rota apropriados.Mas voltando ao seu exemplo original, em que você tem uma página aleatória, é mais complexo porque os parâmetros da rota não podem ser alterados em tempo de execução. Portanto, isso pode ser feito com uma
RouteBase
subclasse da seguinte maneira.Que pode ser registrado no roteamento como:
Observe no exemplo acima, pode fazer sentido também armazenar um cookie registrando a versão da página inicial em que o usuário entrou, para que, quando retornem, recebam a mesma versão da página inicial.
Observe também que, usando essa abordagem, você pode personalizar o roteamento para levar em consideração os parâmetros da string de consulta (por padrão os ignora completamente) e encaminhar para uma ação apropriada do controlador.
Exemplos adicionais
fonte
Server.TransferRequest
não é "completamente desnecessário no MVC".Não é uma resposta em si, mas claramente o requisito seria não apenas para a navegação real "executar" a funcionalidade equivalente do Webforms Server.Transfer (), mas também para que tudo isso seja totalmente suportado nos testes de unidade.
Portanto, o ServerTransferResult deve "parecer" um RedirectToRouteResult e ser o mais semelhante possível em termos da hierarquia de classes.
Estou pensando em fazer isso olhando para Reflector e fazendo o que quer que seja a classe RedirectToRouteResult e também os vários métodos da classe base do Controller, e depois "adicionando" a última ao Controller por meio de métodos de extensão. Talvez estes possam ser métodos estáticos dentro da mesma classe, para facilitar / preguiça de baixar?
Se eu começar a fazer isso, publicarei, caso contrário, talvez alguém possa me derrotar!
fonte
Consegui isso aproveitando o
Html.RenderAction
ajudante em uma View:E no meu controlador:
fonte