Search code examples
asp.net-mvcasp.net-routing

Public method for every view? Default ActionResult and Routes in ASP.MVC


I'm experimenting with ASP.NET MVC and Routes.

It appears MVC forces me to add a public method to the controller any time I want to create a view. For example:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

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

    //... a public method for every view.. :(
}

I do not want to create a public method for every view. By default, I want the behavior of "return View()" for all views in the system, unless otherwise specified.

For example, HTTP GET:

site.com/about
site.com/features
site.com/
site.com/testimonials
site.com/contact-us

As it stands now, I would have to add:

HomeController.About()
HomeController.Features()
HomeController.Index()
HomeController.Testimonials()
HomeController.ContactUs()

All result in "return View()". This is my problem, I am trying to eliminate creating public action methods for simple views.

For views that require additional processing, like a Contact Us page on an HTTP POST to:

site.com/contact-us

I would like to specifically add a method in the controller to send an SMTP message.


The following is a more concise example of what I am trying to do:

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()
   }

}

Thanks, Brian


Solution

  • The potential problem with having the ShowBasicView from your edit is that due to the implicit wiring of views, each of those urls will all return the same view, namely:

    \Views\Home\ShowBasicView.aspx

    Now, this might be what you want, although it's probably unlikely.

    You could possibly set this up by having a route such as:

    routes.MapRoute(  
      "ShowBasic",
      "{id}",
      new { controller = "Home", action = "ShowBasicView", id = "home" }
    );
    

    And modify your controller to:

    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();
      }
    }
    

    Alternatively, if the content is hardcoded in the views you could try:

    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);
      }
    }
    

    You'll possibly also have to add a route for the base URL, as the ShowBasic route will only hit for a URL with a string value.