Question

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

Was it helpful?

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.

OTHER TIPS

You can add following method in your Controller, it

protected override void HandleUnknownAction(string actionName)
{
    try{
       this.View(actionName).ExecuteResult(this.ControllerContext);
    }catch(Exception ex){
       // log exception...
       base.HandleUnknownAction(actionName);
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top