0

I am working on a MVC.NET project. I have some question about this technology. I have some functions ( or actions ) which are common between controllers. One of the ways to have shared function among controllers is creating a BaseController and extend this controller from Controller and extend another Controllers from BaseController but it has some problems. One of this problems which bothers me so much is that user can request this url www.MySite.com/BaseController (am I right? ) and if I use Authorize attribute all of my actions needs Authorization. What is another way to use share function in different Controllers. I need those share function use ViewBag. Can you help me?

Behzad Hassani
  • 2,129
  • 4
  • 30
  • 51
  • Your `BaseController` should not contain any `public ActionResult` methods so there is nothing the user could navigate to. Just create protected helper methods that can be called from other controllers –  May 16 '15 at 12:24
  • maybe http://stackoverflow.com/questions/16870413/how-to-call-another-controller-action-from-a-controller-in-mvc – uowzd01 May 16 '15 at 12:24
  • @StephenMuecke but when he try to access to this controller he will notice the 404 error. because no action will be found. isn't it matter? – Behzad Hassani May 16 '15 at 12:26
  • The user can also navigate to `/ThisUrlDoesNotExist` and get a 404 error :) - Why would you navigate to a page that does not exist –  May 16 '15 at 12:30
  • @StephenMuecke ph yeah you are right :) I thought Controller not found and action not found code are different but both of them produce 404 error. thank you buddy :) but there isn't another way for share functions? – Behzad Hassani May 16 '15 at 12:31
  • If your wanting to access properties and methods of the `Controller`class e.g. `ViewBag` then using `BaseController : Controller` is the best way I can think of (although I recommend you don't use `ViewBag` and instead use view models) –  May 16 '15 at 12:35
  • Also if you decorate your `BaseController` with `[Authorize]`, then you just override that in specific Action methods in other controllers with `[AllowAnonymous]` - e.g. your login/register methods –  May 16 '15 at 12:44

1 Answers1

1

I'd recommend you a different approach.

First of all, I'm not a big fan of inheritance. Often people misunderstand this concept and use it to avoid code replication. The purpose of inheritance is actually to be able to treat objects of different classes with a common ancestor in a unique way and to take advantage of polymorphism. I your case I think I'd rather go with composition. I'd introduce another layer between your controller and model. This layer would be called business logic and would cover all the complex data processing and decision making. By composition I'd just have instances of the classes from business logic layer in controllers and delegate the specific jobs to them. This way the controllers would only be the entry points to the real business operations encapsulated in the business logic layer.

Another thing to consider is to create a separate controller(s) for the actions that are shared. If they are shared, than maybe they are not really related to their controllers and somewhat violate the separation of concerns rule?

One more thing you can do is to define custom routes. This way you could extract the controller(s) with the shared functions like I described above and still provide users with elegant urls. Something like this:

public static void RegisterRoutes(RouteCollection routes)
{
    ...
     routes.MapRoute(
         name: "Route1",
         url: "Controller1/Action1",
         defaults: new { controller = "CommonController", action = "CommonAction"}
     ); 
     routes.MapRoute(
         name: "Route2",
         url: "Controller2/Action1",
         defaults: new { controller = "CommonController", action = "CommonAction"}
     ); 
}
Community
  • 1
  • 1
Andrzej Gis
  • 13,706
  • 14
  • 86
  • 130