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?
1 Answer
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"}
);
}
BaseControllershould not contain anypublic ActionResultmethods so there is nothing the user could navigate to. Just create protected helper methods that can be called from other controllers/ThisUrlDoesNotExistand get a 404 error :) - Why would you navigate to a page that does not exist