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?
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.
Related
This is the situation:
I use a third-party library to do some SPF checks
The checks are done from an ASP.NET web site
The third-party library uses lots of 'await/async' code, although I am calling a non-async method to do it
Most of the time, w3wp (yes, the actual w3wp.exe) simply crashes with the following error ' Invalid token for impersonation - it cannot be duplicated'.
I am assuming this is because the await/async grabbed a Thread from the threadpool which has some sort of illegal / weird identity on it, so I am wondering if there's any way to call a bit of code and tell .Net to 'forget about' async/await and just run it synchronously, on the same thread.
I've found a solution: somewhere in the product the user was being impersonated with identity.impersonate(), but the impersonation context was never .undo()'d. After making sure the identity.impersonate() was properly matched by an .undo(), the problem stopped occurring.
I did try making my own SynchronizationContext, but that didn't work in this instance, as passing on the impersonation just passed on the 'illegal' impersonation context too.
I'm have a small project that uses the Asp.Net Core Identity framework together with EF Core.
One function calls the UserManager.FindByIdAsync(id) and it returns the proper object. However, it only works a few minutes after the application is started. As long as the server is busy it works fine, but as soon as the application is idle more than 1-2 minutes the request fails.
It fails with:
*OperationCanceledException: The operation was canceled.
System.Threading.CancellationToken.ThrowOperationCanceledException()*
The stacktrace looks like this:
*System.Threading.CancellationToken.ThrowOperationCanceledException()
Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore.FindByIdAsync(string userId, CancellationToken cancellationToken)
Microsoft.AspNetCore.Identity.UserManager.FindByIdAsync(string userId)
MyProject.Areas.Admin.ControllerServices.UserService+<GetUser>d__11.MoveNext() in UserService.cs*
I'm still logged in as other pages are working fine.
A simple call to the EF context.Users.FindAsync(new object[] { id }) will work as expected, but the next line containing FindByIdAsync will fail.
All this works perfect in the dev environment, the error occurs when the application is installed on the server running IIS on WS 2008 R2. Recycling the app pool will make it work again until it is idle again for a few minutes.
I have noted that when lines like 'Connection id "0HL5E91K33IIQ" reset.' are being logged, then the app starts to fail. Prior to that it works.
FindByIdAsync is not the only identity function to fail, many other functions fails with the same error.
What am I missing?
I will answer my own question, and hopefully this will help someone else in the future.
For me, it all boiled down to the lifetime of the injected services.
UserManager depends on IHttpContextAccessor (this is where the CancellationToken comes from) and it behaves incorrectly when lifetimes do not match up.
IHttpContextAccessor is added as a Singleton service, while the UserManager is added as a scoped service. My service that used the UserManager was added as a Singleton service.
Changing this to Scoped made the errors go away.
In my case it boiled down to the exact same issue, but was caused by a very subtle design "flaw" in ASP.Net Core's DI implementation. For various reasons I prefer using SimpleInjector, but stuffing ASP.Net Identity Core into it is hard, compared to the nice extension methods provided for the build in container. So I put the framework stuff in the framework container, and my business stuff in SimpleInjector, deciding that "Authentication and Authorization" is considered "framework". Only the AccountController is resolved by the framework container using cross wiring. However, using app.ApplicationServices.GetService<AccountController>() outside a request scope does not fail but returns a Singleton that will survive! Unfortunately exactly this happens when you let SimpleInjector verify it's configuration. The first request causing a malfunction (bad login) leaves your whole runtime with a defect singleton instance. Solution for this is well documented in SimpleInjectors documentation, use their extension app.GetRequiredRequestService<AccountController>() instead.
Update asp.net core 2.0
Now, you won't get the fishy singleton instance, but an exception:
System.InvalidOperationException: 'Cannot resolve scoped service 'WebApplication15.Controllers.AccountController' from root provider.'
I've seen a lot of similar threads but none that actually address my particular situation.
I'm writing unit tests in ASP.NET 4.0 web application (ASP.NET Forms, not MVC). There are several spots in the code where I call the ServerVariables collection to call variables like REMOTE_ADDR. Since my unit tests do not actually initiate HttpRequests when executing my code, things like ServerVariables are Null and therefore error when I try to call HttpContext.Current.Request.ServerVariables("REMOTE_ADDR")
All the solutions I've found to address this issue refer to MVC and so they assume that HttpRequest derives from HttpRequestBase, which it does in MVC but not in ASP.NET Forms.
I tried using Moq but you can't mock a sealed class, and HttpRequest is unfortunately sealed with no interface.
The HttpRequestBase and HttpRequestWrapper classes can be used with a bit of work.
Wherever you currently access HttpContext.Current.Request -- or just plain Page.Request -- you'll need to use an injectable instance of HttpRequestBase instead. Then you'll need to inject a different subclass of HttpRequestBase depending on whether you're testing or live.
For live code, you'd probably inject an HttpRequestWrapper instance that wraps HttpContext.Current.Request:
var liveRequest = new HttpRequestWrapper(HttpContext.Current.Request);
For test code, you'd need to create and inject your own mock subclass of HttpRequestBase. Presumably Moq can do that for you on-the-fly.
I'm using JQuery to load controls dynamically in an ASP.NET development environment using JSON and WebServices. Within this solution I have a business logic layer which has a built in validation mechanism (i.e. validating properties and business rules similar to that of CSLA)
When requesting a new control to be loaded dynamically using JQuery and an ASP.NET WebService, I would like to validate the input from the current control against the business logic validation mechanism (i.e. server side validation) and notify the user if there was any problems.
I managed to achieve this, however, when validation fails in the web service I would like to throw a customer exception containing the validation field id's and associated error messages.
In JQuery, I test for this specific ExceptionType and would like to apply the error messages dynamically to the controls listed in the exception type properties. This is where my problem comes in. Even though I created a custom exception with custom properties the exception that is passed to JQuery in JSON format from the WebService is still a standard exception with none of the additional properties listed. I could simply create a JSON formatted string of values in the exception's message property but would ultimately prefer something a little more elegant. Does anyone know how you can override the serialized exception created by ASP.NET for situations such as this...
Thank you in advance...
G
I ran into something very similar a couple days ago - basically there's no way to make ASP.NET generate custom exceptions. This is by design, since returning a specific type of exceptions would
[...] expose implementation
details/bugs to the clients. We could
do something with special exception
type that we let pass through, but its
too late for this release [...]
You could always return different HTTP status codes, and have the browser handle them as custom exceptions - for example, a 500 error would mean one thing, a 401 something else, etc. I think the best solution is to make your method return a string with the exception stack - not elegant, but at least this way the client has all the exception details.
Dave Ward also has info on ASP.NET AJAX service errors.
I am using NHibernate on a new ASP.NET project, and am running into what I believe to be strange behavior. I am attempting to manage my session by using an HttpModule to catch the EndRequest event and close the session. This is working fine, however, after the EndRequest event fires, I am getting an exception in the OnLoad event of one of my custom controls that is attempting to read a Property from my object that is lazy loaded. I get an exception stating 'failed to lazily initialize a collection, no session or session was closed'. Turning lazy load off for these properties does fix the problem, and is an acceptable solution. But this seems to be going against what I always thought to be true.
I would assume that the OnLoad event and all server side processing would be done at the point that EndRequest is fired. This is also the first time that I have used IIS 7 on a project. Is this a reason for the behavior? What is the expected behavior?
I just had a 'palm slaps forehead' moment. Despite the fact that I am in fact deploying to an IIS 7 server, I have been debugging using the VS 2008 Built in Web server (Casini). Casini passes all requests through the ASP.NET pipeline, IIS does not. This was causing a request for an image file or javascript file (or any other static resource) to close my NHibernate session before I was actually thinking it should close.
Thanks for the list of resources, I will certainly look into them.
If your object is lazy-init and no session is open, resolving the properties will fail.
Remember that lazy exceptions will most probably appear when you have some relationship with another entity that hasn't been initialized.
http://forum.springframework.org/showthread.php?t=13474
I would also recommend using something like the HTTP Module in Rhino Commons to manage your NHibernate Sessions.
You should use a shrinkwrapped package for dealing with this.
I like to use Autofac with ASP.NET/MVC integration. You simply ask the RequestContainer for an ISession whenever you need it and, because the ISession is IDisposable, the RequestContainer automatically knows to dispose of the ISession when the current request ends. Everything is taken care of for you.
use HttpModule if you need lazy loading. Inherit your class from it and then you'd have two methods you can override (can't remember their names). First one is called each time any page is requested. Open the session there and put the session in viewstate. The other method is called when page is posted back, close your session there.