3
votes

I have a piece very simple code that used to work before I tried upgrading to ASP.NET Identity. This is a real head-scratcher. Using ASP.NET MVC 5 with ASP.NET Identity 2.1 (latest-and-greatest at the time of writing this post) I have a "user forgot their email" controller action that does this:

await this.UserManager.SendEmailAsync(
      user.Id,
      AccountStrings.ForgotPasswordEmailTitle,
     string.Format(AccountStrings.ForgotPasswordEmailMessage, callbackUrl));  

My user manager uses an implementation of IIdentityMessageService to shoot out the email and my code is in Task SendAsync(IdentityMessage message). Inside that method I need an active Http context since I'm using the Razor view engine to construct the email. Again, this used to work, until today.

As of today, an exception is thrown inside my method as the email is being rendered telling me I have no active Http context. And sure thing, HttpContext.Current is null. It's not null when the SendEmailAsync is called inside the controller action, it's not null after the await in the task continuation, but it's null inside SendEmailAsync.

I'm using the correct <system.web><httpRuntime targetFramework="4.5.1" /></system.web> flags inside web.config, everything is by the book. And now, after updating some component - whether it's a minor ASP.NET MVC version or ASP.NET Identity version - I don't know - HttpContext.Current is null.

I have an ugly "fix" where I save the HttpContext.Current to a local var as my IdentityMessageService is created and set the current HttpContext to that value while SendAsync is executing, which works, but this definitely smells like a pretty serious regression inside the ASP.NET stack, somewhere.

Has anyone encountered anything similar?

1
What exactly do you mean by "correct flag inside web.config"?Stephen Cleary
oops - SO ate my formatting. Was talking about the <httpRuntime> flag to enable the "friendly" task scheduler.Dimitar Velitchkov

1 Answers

0
votes

I have not encountered this exact problem, but my gut feeling say that HttpContext.Current should not be used inside SendEmailAsync and this is not a bug, but intentional implementation on the part of Identity framework. I'll guess that a completely new thread is created just to send out an email and this thread does not have access to HttpContext.Current, i.e. this thread does not depend on the Http request/response.

So my thought would be to decouple your email generation from HttpContext. And to help you do this there is a RazorEngine project that allows to work with Razor views, but without HttpContext. This project is available via nuget:

Install-Package RazorEngine

And judging by the documentation it is pretty easy to work with. I have never used it myself though, so can't go beyond what these web-pages are saying.