My scenario: My application is a Web Api 2 app using a business logic and repository layer for data access. The web application uses ASP.NET Impersonation to login to the database as the user accessing the website (authenticated via PKI). I have several async controller methods. However, when I await
on the data access methods, the database call may complete on a different thread which will then access the database under the identity of my application pool which is not allowed to connect to the database.
Example Controller:
public class TestApiController : ApiController {
private IBusinessLogicObject _myBlObject;
public TestApiController(IBusinessLogicObject myBlObject){
_myBlObject = myBlObject; //Populated through Unity
}
public async Task<int> CountMyJobs(string name){
return await _myBlObject.CountMyJobsAsync(name);
}
}
Example Business Logic Class:
public class BusinessLogicObject : IBusinessLogicObject
{
private IGenericRepository<Job> _jobRepository;
public BusinessLogicObject(IGenericRepository<Job> _jobRepository)
{
_jobRepository = jobRepository; //Populated with Unity
}
public Task<int> CountMyJobsAsync(string name)
{
using (WindowsIdentity.GetCurrent().Impersonate())
{
//JobRepository is effectively a DbSet<Job> and this call returns IQueryable<Job>
return _jobRepository.Where(i => i.Name == name).CountAsync();
}
}
}
If I move the using
statement into the controller (wrapped around the await), it works fine.
The issue seems to be that because the await
is outside of the impersonation context, it does not impersonate the database call (the CountAsync()
) and I am unable to open a connection to my database.
The Question:
Is there a way I could write an ActionFilter
or some other attribute on my controller method so that the method itself (containing the await call) would be automatically wrapped in the using statement?