I have an MVC3 app with a simple Log service. All my services are invoked using Microsoft's Unity Dependency Injection container.
For most methods, I ignore exceptions; they're caught in a top-level error handler, which categorizes them and decides whether or not to log them, generates the HTTP response I desire and calls an action method on the error controller to return my custiom error page.
Sometimes, tho, I don't want to do that; I want to handle the exception where it happens, e.g. in my controller. In that case, I want to log the error before substituting an appropriate default value and continuing with the controller's logic.
I did that in one place: in my controller, I added:
var logService = DependencyResolver.Current.GetService<ILogService>();
try { /* something indeterminate */ }
catch ( Exception ex ) {
logService.LogException(category, ex);
/* do something else instead */
}
Now I want to do it a second time in that controller (as it happens, later in the same method). As soon as I do this again, I see it's time to refactor, as I'm repeating myself.
What's the best way to make my logger available to my controllers? My controllers all inherit from a custom ControllerBase; my first thought is to add it to the ControllerBase's constructor. BUT:
- currently I don't have a constructor in the ControllerBase,
- I'm a bit worried that referencing the DI container in the controller breaks the isolation of the controller, negating the value of DI to begin with, and
- I don't think I can pass the logger in to the ControllerBase's c开发者_StackOverflowonstructor, because (as I understand it, pls correct me if 'm wrong) controllers can only have parameterless constructors, so there's no way to pass anything to them.
Where's the proper place to make the service available to all my controllers?
Place it in your constructor. You can even place it in a BaseController
.
Ideally, you will use Dependency Injection and have it come in on your controller. Controllers can have parameters if your IoC container supports it.
private readonly ILogService logService;
public MyController(ILogService logService)
{
this.logService = logService;
}
I wouldn't add it to the base controller for the sole reason that it sounds as if you only use it sporadically. I would add it as Daniel White suggests in the constructor of the controller. If it's looking as though you use it in most controllers, then I'd consider moving it to the base.
精彩评论