I\'ve seen a lot of people talk about using base controllers in their ASP.NET MVC projects. The typical examples I\'ve seen do this for logging or maybe CRUD scaffolding. What are some other good uses of a base controller class?
问题:
回答1:
There are no good uses of a base controller class.
Now hear me out.
Asp.Net MVC, especially MVC 3 has tons of extensibility hooks that provide a more decoupled way to add functionality to all controllers. Since your controllers classes are very important and central to an application its really important to keep them light, agile and loosely coupled to everything else.
Logging infrastructure belongs in a constructor and should be injected via a DI framework.
CRUD scaffolding should be handled by code generation or a custom ModelMetadata provider.
Global exception handling should be handled by an custom ActionInvoker.
Global view data and authorization should be handled by action filters. Even easier with Global action filters in MVC3.
Constants can go in another class/file called ApplicationConstants or something.
Base Controllers are usually used by inexperienced MVC devs who don\'t know all the different extensibility pieces of MVC. Now don\'t get me wrong, I\'m not judging and work with people who use them for all the wrong reasons. Its just experience that provides you with more tools to solve common problems.
I\'m almost positive there isn\'t a single problem you can\'t solve with another extensibility hook than a base controller class. Don\'t take on the the tightest form of coupling ( inheritance ) unless there is a significant productivity reason and you don\'t violate Liskov. I\'d much rather take the < 1 second to type out a property 20 times across my controllers like public ILogger Logger { get; set; }
than introduce a tight coupling which affects the application in much more significant ways.
Even something like a userId or a multitenant key can go in a ControllerFactory instead of a base controller. The coupling cost of a base controller class is just not worth it.
回答2:
I like to use base controller for the authorization.
Instead of decorating each action with \"Authorize\" attribute, I do authorization in the base controller. Authorized actions list is fetched from database for the logged in user.
please read below link for more information about authorization. Good practice to do common authorization in a custom controller factory?
回答3:
I use it for accessing the session, application data etc.
I also have an application object which holds things like the app name etc and i access that from the base class
Essentially i use it for things i repeat a lot
Oh, i should mention i don\'t use it for buisiness logic or database access. Constants are a pretty good bet for a base class too i guess.
回答4:
I have used base controller in many of my projects and worked fantastic. I mostly used for
- Exception logging
- Notification (success, error, adding..)
- Invoking HTTP404 error handling
回答5:
From my experience most of the logic you\'d want to put in a base controller would ideally go into an action filter. Action Filter\'s can only be initialized with constants, so in some cases you just can\'t do that. In some cases you need the action to apply to every action method in the system, in which case it may just make more sense to put your logic in a base as opposed to annotating every action method with a new actionFilter attribute.
I\'ve also found it helpful to put properties referencing services (which are otherwise decoupled from the controller) into the base, making them easy to access and initialized consistently.
回答6:
We use the BaseController for two things:
- Attributes that should be applied to all Controllers.
- An override of Redirect, which protects against open redirection attacks by checking that the redirect URL is a local URL. That way all Controllers that call Redirect are protected.
回答7:
What i did was to use a generic controller base class to handle:
- I created
BaseCRUDController<Key,Model>
which required aICRUDService<TModel>
object as constructor parameter so the base class will handle Create / Edit / Delete. and sure in virtual mode to handle in custom situations - The
ICRUDService<TModel>
has methods like Save / Update / Delete / Find / ResetChache /... and i implement it for each repository I create so i can add more functionality to it. - using this structure i could add some general functionality like PagedList / AutoComplete / ResetCache / IncOrder&DecOrder (if the model is IOrderable)
Error / Notification messages handling: a part in Layout with
@TempData[\"MHError\"]
code and a Property in base Controller likepublic Notification Error { set { TempData[\"MHError\"] = value; } get { return (Notification) TempData.Peek(\"MHError\"); } }
With this Abstract classes i could easily handle methods i had to write each time or create with Code Generator. But this approach has it\'s weakness too.
回答8:
I\'m using a base controller now for internationalization using the i18N library. It provides a method I can use to localize any strings within the controller.
回答9:
Filter is not thread safe, the condition of database accessing and dependency injection, database connections might be closed by other thread when using it.