Método público para cada ponto de vista? Padrão ActionResult e Rotas em ASP.MVC
-
21-08-2019 - |
Pergunta
Eu estou experimentando com ASP.NET MVC e Rotas.
Parece MVC me obriga a adicionar um método público para o controlador qualquer momento eu quero criar uma visão. Por exemplo:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult About()
{
return View();
}
//... a public method for every view.. :(
}
Eu não quero criar um método público para cada vista. Por padrão, quero que o comportamento de "retorno View ()" para todos os pontos de vista do sistema, a menos que especificado em contrário.
Por exemplo, HTTP GET:
site.com/about site.com/features site.com/ site.com/testimonials site.com/contact-us
Tal como está agora, eu teria que adicionar:
HomeController.About()
HomeController.Features()
HomeController.Index()
HomeController.Testimonials()
HomeController.ContactUs()
Todos os resultado em "return View ()". Este é o meu problema, eu estou tentando eliminar a criação de métodos de ação pública para vistas simples.
Para vistas que requerem processamento adicional, como uma página Fale Conosco sobre um HTTP POST para:
site.com/contact-us
Eu gostaria de adicionar especificamente um método no controlador para enviar uma mensagem SMTP.
A seguir é um exemplo mais conciso do que estou tentando fazer:
public class HomeController{
public ActionResult ShowBasicView(){
//HTTP GET:
//site.com/about
//site.com/features
//site.com/
//site.com/testimonials
//All URLs above map to this action
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ContactUs(FormCollection data){
//HTTP POST:
//site.com/contact-us
//POST URL maps here.
SmtpClient.Send(new MailMessage()) //etc...
return View()
}
}
Obrigado, Brian
Solução
O problema potencial com ter a ShowBasicView de sua edição é que, devido à fiação implícita de pontos de vista, cada um desses urls tudo vai voltar ao mesmo ponto de vista, a saber:
\ Views \ Home \ ShowBasicView.aspx
Agora, isso pode ser o que quiser, embora seja pouco provável.
Você poderia configurar isso por ter uma rota tais como:
routes.MapRoute(
"ShowBasic",
"{id}",
new { controller = "Home", action = "ShowBasicView", id = "home" }
);
e modificar seu controlador para:
public class HomeController: Controller{
public ActionResult ShowBasicView(string pageName){
// Do something here to get the page data from the Model,
// and pass it into the ViewData
ViewData.Model = GetContent(pageName);
// All URLs above map to this action
return View();
}
}
Como alternativa, se o conteúdo é codificado nas vistas você pode tentar:
public class HomeController: Controller{
public ActionResult ShowBasicView(string pageName){
// All URLs above map to this action
// Pass the page name to the view method to call that view.
return View(pageName);
}
}
Você vai, possivelmente, também tem que adicionar uma rota para o URL base, como a rota ShowBasic só vai bater para uma URL com um valor de string.
Outras dicas
Você pode adicionar seguinte método em seu controlador, ele
protected override void HandleUnknownAction(string actionName)
{
try{
this.View(actionName).ExecuteResult(this.ControllerContext);
}catch(Exception ex){
// log exception...
base.HandleUnknownAction(actionName);
}
}