Entity Framework log any errors - c#

What's the best practice to log any appearing errors caused by Entity Framework?
Currently I'm using log4net, but I think this is independent to the logging framework.
Regarding an example API:
public class TestController : ApiController
{
[HttpGet]
public IEnumerable<Test> GetTests()
{
using(var context = new DatabaseContext())
{
return context.Tests.Where(w=>w.Enabled).ToList();
}
}
}
For now, I would have to stick my method body in a try/catch (and I'd have to stick all method bodies of all controllers in try/catch blocks)
try
{
using (var context = new DatabaseContext())
{
return context.Tests.Where(w=>w.Enabled).ToList();
}
}
catch(Exception e)
{
// TODO: handle also those ValidationErrors, thrown by Entity Framework
// so here we get a lot more code
_logger.Error(e);
}
But I don't want to put any method body of my API in a try/catch block.
Is there a possibility like adding an OnException in my DatabaseContext class, where I always can log any exception thrown by Entity Framework?

You can look into the following:
Global Error Handling in ASP.NET Web API 2
Exception Filters
To take things even further, if you want to get detailed information about what is going on with the underlying commands, you can implement an Interceptor as well.

Related

Asp.Net WebApi catch exceptions generated in controller constructor

In my base API controller class constructor, I am populating user permissions based on windows authentication. I am using something like
var ctx = new PrincipalContext(ContextType.Domain, System.Environment.UserDomainName.ToUpper());
var userInfo = UserPrincipal.FindByIdentity(ctx, System.Environment.UserName.ToUpper());
to get user information from AD. The problem is that when the user is locked out the application is failing with 500 since the exception occurs in the constructor. Is there a way to handle the exception of these calls and bubble it up as an Unauthorized exception or something else? I tried to surround it with try catch and throw httpresponse exception with unauthorized but it still bubbles up as 500.
edit #1
There are few more things happening in constructor and when it is failing I do not want to fail with 500. I need to catch the exception and throw something else. Authorization was just an example of one of those few things.
edit #2
To all who write that I should not have any logic in the constructor:
Constructors are used to initialize the object to a valid state. The controller of this part of the application has to have a database connection, user information and some other properties populated because all of the requests are using all this information. If any of those is failing I want to return a different type of the error to the user. In the case of a standard class it would be different type of exceptions (SqlException, DbConnectionException, Some sort of AD Exception). In the case of WebApi I want it to be a different type of the response codes (Unauthorized, Not Implemented (501) etc). Copy pasting the same code to every request in that section of the application represents a maintenance issue.
Since the original exception is wrapped into other exceptions few times the only way I found so far is to have a global exception filter and then navigate through the inner exceptions of the context. Exception till it is null or I didn't reach the exception of the type I am looking for.
namespace SomeWebApi
{
public class GlobalExceptionHandler : ExceptionHandler
{
public override async Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
{
if (context.Exception != null)
{
Exception filteredException = context.Exception;
while (
(filteredException != null)
&&
(filteredException.GetType() != typeof(HttpResponseException)
)
{
filteredException = filteredException.InnerException ;
}
if (
(filteredException != null)
&&
(filteredException != context.Exception)
)
{
var httpResponseException = (HttpResponseException) filteredException;
var response = context.Request.CreateErrorResponse(
httpResponseException.Response.StatusCode,
httpResponseException
);
context.Result = new ResponseMessageResult(response);
}
}
}
}
}
Next I needed to register it in WebApiConfig.Register:
config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler());
The eseaiest way is to not use user / sesion related logic in controllers constructor.
For authentication You can use attribute filters, for geting user information just create helper class and use it when needed.
edit
one last thing: try to use dependency injection (like structure map) it will force You to make proper changes in constructor and it will make initializing easier. https://www.exceptionnotfound.net/setting-up-dependency-injection-in-web-api-with-structuremap/

Handle 'underlying provider failed on open' in one place

I have an MVC Razor application that uses entity framework 6.0. However, if the DB is down or something, my code starts throwing exceptions at all kinds of random places like when I start evaluating my IEnumerable<T>s and IQueryable<T>s.
The model constructor is generated code that will be overwritten if I modify it which wouldn't help anyway because the constructor doesn't throw exceptions. Instead, the exceptions come in places like this
using (var dataContext = new ArchiveVMADDatabase.ArchiveDatabaseModel())
{
IQueryable<HDeploy> deploys = Helpers.GetProdDeploysFromArchive(dataContext);
var query = getBranchSelectListQuery(deploys);
listItems.AddRange(query);// EXCEPTION IF DB IS DOWN
}
Is there a good way for me to handle this in one place and avoid wrapping nearly 100% of my code in giant try catch blocks? I would really like to have it just return empty sets if it can't talk to the DB.
I'm not sure whether you are working with MVC or Web API, but in Web API one would use Exception Filters to centralize exception handling.
An exception filter is basically a derivative of the ExceptionFilterAttribute that can create a specific response depending on the caught exception:
public class NotImplExceptionFilterAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
if (context.Exception is NotImplementedException)
{
context.Response = new HttpResponseMessage(HttpStatusCode.NotImplemented);
}
}
}
You don't need to add try {} catch {} blocks anywhere -- Web API triggers the configured exception filters automatically as soon as an exception reaches the outer most layer of your system (i.e. the controller level).
You can activate an exception filter only for specific ApiControllers or globally for every controller.

WebAPI Global Exception Handling

I have a ASP WebAPI project. I'm trying to setup a global exception handler on my basecontroller. So I created an ExceptionFilterAttribute like so.
using System.Web.Http.Filters;
public class MyExceptionFilterAttribute : ExceptionFilterAttribute
{
protected static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
var exception = actionExecutedContext.Exception;
log.Fatal(exception);
base.OnException(actionExecutedContext);
}
}
Then I also registered it in /App_Start/WebApiConfig.cs
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// ...
// Setup Filters
config.Filters.Add(new MyExceptionFilterAttribute());
}
}
When I add the attributes to my controller (or base-controller), nothing gets logged. What am I doing wrong?
Edit: My controller throwing the exception:
[HttpGet]
public string Hello(string name)
{
if (name.Equals("error", StringComparison.OrdinalIgnoreCase))
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
else
{
return name;
}
}
Actually when you add that filter to your HttpConfiguration it means that it will be executed for any action. That is, you don't need to add the whole attribute to your API controllers.
What can be skipping your filter? Other filter. The first filter to set the response wins and it can happen that the action itself gets never executed.
Anyway, maybe you need to switch to implement an IExceptionHandler and configure it as follows:
config.Services.Replace(typeof(IExceptionHandler), new MyExceptionHandler());
This approach is better because it's a true last-chance exception handler and it will be always called independently of the behavior of filters.
Like #ShekharPankaj had pointed out, not all exceptions are handled by the attribute (or the approach #Matías provided). My code was fine. I simple changed the exception to a ArgumentException and it gets handled.
See also this SO-thread: catch all unhandled exceptions in ASP.NET Web Api
To answer my own question, this isn't possible!
Handling all exceptions that cause internal server errors seems like a
basic capability Web API should have, so I have put in a request with
Microsoft for a Global error handler for Web API:
https://aspnetwebstack.codeplex.com/workitem/1001
If you agree, go to that link and vote for it!
In the meantime, the excellent article ASP.NET Web API Exception
Handling shows a few different ways to catch a few different
categories of error. It's more complicated than it should be, and it
doesn't catch all interal server errors, but it's the best approach
available today.
Update: Global error handling is now implemented and available in the
nightly builds! It will be released in ASP.NET MVC v5.1. Here's how it
will work:
https://aspnetwebstack.codeplex.com/wikipage?title=Global%20Error%20Handling

How to organize transactions?

I have services been called through the 'Guardian' method, that has TransactionScope opened for each request and complete that transaction if everything is fine:
void ExecuteWorker(...)
{
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew))
{
...CallLogicMethods...
scope.Complete();
}
}
One of the methods interacts with 'External' service, and in case if that interaction fails all my transaction fails also. As a result, I don't save required data (been calculated before request to external service.
void DoLogic1(...)
{
CalculateSomeData(...);
SaveCalculatedData(...);
DoRequestToExternalService(...);
}
What is the best way to resolve that issue?
Application is written using C#, .NET 4.0, MS SQL 2008.
Myself I see two solutions
Using try/catch:
void DoLogic11(...)
{
CalculateSomeData(...);
SaveCalculatedData(...);
try
{
DoRequestToExternalService(...);
}
catch(Exception exc)
{
LogError(...);
}
}
The lack of this approach is that I'm hiding exception from the caller. But I would like to pass error outside as an exception (to be logged, etc).
Using 'Nested transcation', but I not sure how that works.
Here is my vision it should be:
void DoLogic12(...)
{
using (TransactionScope scopeNested = new TransactionScope(TransactionScopeOption.Suppress))
{
CalculateSomeData(...);
SaveCalculatedData(...);
scopeNested.Complete()
}
DoRequestToExternalService(...);
}
I've implemented that, tried to use, but it seems that nested transcation is committed only in case when external is committed also.
Please advise.
I am not sure I understood it correctly. Can you put all your logic methods in one try-catch? Each call is a separate transaction using TransactionScopeOption.RequiresNew
void DoLogic1(...)
{
try
{
CalculateSomeData(...);
SaveCalculatedData(...);
DoRequestToExternalService(...);
}
catch(Exception ex)
{
LogException(...)
throw;
}
}
But I would like to pass error outside
as an exception (to be logged, etc).
Can you use throw?
I've decided to change my 'ExecuteWorker' method to create transaction conditionally. Therefore I'm able to create transaction in the 'DoLogicX' method itself.

Unit testing with entlib - excluding catches

I've got a method that does some IO that generally looks like this:
public bool Foo()
{
try
{
// bar
return true;
}
catch (FileNotFoundException)
{
// recover and complete
}
catch (OtherRecoverableException)
{
// recover and complete
}
catch (NonRecoverableException ex)
{
ExceptionPolicy.HandleException(ex, "LogException");
return false;
}
}
The method isn't mission critical to be completed, there are external recovery steps - and it's relatively common for NonRecoverableException to be thrown - it's in the spec for it to return false, report 'cannot be completed at this time' and processing moves along. A NonRecoverableException does not put the program in an invalid state.
When I'm unit testing, and one of these exceptions is thrown, I get the error that
Activation error occured while trying to get instance of type ExceptionPolicyImpl
And I'd like to suppress that in favor of getting the actual/original exception information instead of EntLib not being able to log (and, indeed to force the NonRecoverableException and have an [ExpectedException(typeof(NonRecoverableException))] unit test to ensure that this method complies with the spec.
How might I go about that?
edit
Using preprocessor directives is not ideal as I hate seeing test-specific code in the codebase.
Testability of your code using the Entlib static facades is difficult. Without changing your code a little, your only answer is to add an app.config file to your test assembly and set up the Entlib exception block with an innocuous policy that does nothing.
However, in Entlib 4 (and 5, which I see you're using) there's another way. We added an instance entry point to all the blocks specifically to improve the testability story. For the exception block, that instance is the ExceptionManager. Using it is pretty simple. Get an exception manager instance into your type, and then call it instead of ExceptionPolicy. Something like this:
public class Whatever {
private ExceptionManager exm;
public Whatever(ExceptionManager exm) { this.exm = exm; }
public bool Foo() {
try {
... do whatever ...
}
catch(NonRecoverableException ex) {
exm.HandleException(ex, "LogException");
return false;
}
}
}
Now that you've got that in there, you can mock out the ExceptionManager (it's an abstract base class) to essentially no-op it during test, either manually or using a mock object framework.
If you don't want to force your users to use a DI container, you can add a default constructor that gets the current exception manager:
public class Whatever {
private ExceptionManager exm;
public Whatever() : this(EnterpriseLibraryContainer.Current.GetInstance<ExceptionManager>()) { }
public Whatever(ExceptionManager exm) { this.exm = exm; }
}
End users use the default constructor, your tests use the one that takes in an explicit ExceptionManager, and you have your hook to mock out anything Entlib uses.
All the blocks now have these "Manager" classes (where they make sense, anyway).
Hmm, you could refactor the code to place everything in the try block in a separate method and configure you tests to call that instead of the existing method?

Categories

Resources