MembershipProvider and Caching (NHibernate) - c#

Hey there, I have my own Membership-Provider where I open a NHibernate-Session in the constructor:
public class OwnMembershipProvider : MembershipProvider
{
protected NHibernate.ISession HibSession;
public OwnMembershipProvider ()
{
HibSession = NHibernateTools.OpenSession();
}
//...
I figured out if I set a breakpoint into the constructor, it is called only once during application start. This gives me a headache since the same NHibernate-Session is used for each request, leading to funny things like "oh, i can't change my password" (the NHibernate-Session returns a cached user when calling ValidateUser(), which still contains the old password).
How can I force the framework to reconstruct the MemberShipProvider for each single request? Or how should it be done different?
Thx for any tipps

Opening a separate session in each method sounds like a good idea. Better yet, open one session and transaction for each HTTP request and then commit the transaction when request ends.

Related

Why is my scoped service being called as a new instance every time?

This is a practice ASP.NET project I'm using to better understand a few techniques, and while I've got Dependency Injection working, its not working quite as I want it to. I have a class that I want to use to store a history, so every time the user hits a submit button, it displays a result, and after the second time it starts displaying the history. Anyway I added the history to the DI as a scoped service, thinking that would mean it would be created and then remain the same instance for the duration of the session for that user. However according to the debugger it looks like the list never gets bigger than one, and thats at the point of adding the item to the list. So the code.
The object
{
public class RollHistory : IRollHistory
{
public List<IRollMessage> Entries { get; set; } = new List<IRollMessage>();
}
}
The DI
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddTransient<IDiceTray, DiceTray>();
services.AddTransient<IRollMessage, RollMessage>();
services.AddScoped<IRollHistory, RollHistory>();
}
The Controller constructor
public HomeController(ILogger<HomeController> logger, IDiceTray diceTray, IRollMessage rollMessage, IRollHistory rollHistory)
{
_logger = logger;
_diceTray = diceTray;
_rollMessage = rollMessage;
_rollHistory = rollHistory;
}
And the code for when the button gets clicked
[HttpPost]
public IActionResult Index(DiceRollModel diceRoll)
{
_diceTray.DiceRoll(diceRoll.DiceType, diceRoll.DiceCount, diceRoll.Bonus, diceRoll.VantageType);
_rollMessage.RollMessages(_diceTray);
diceRoll.RollResult = _rollMessage;
_rollHistory.Entries.Add(_rollMessage);
diceRoll.History = _rollHistory.Entries;
return View(diceRoll);
}
It's worth noting I've tried to code this at least 4 different ways with and without DI, the only way it works is if I use AddSingleton, while this might not be an issue because this app is unlikely to ever be live, its a poor excuse not to do it right.
I believe “scope” is by default per request which would explain that each submit gets is own service.
“Doing stuff right” is of course to some extend a matter of opinion. But my opinion would clearly be that I would avoid server-side session to avoid problems with scaling to more than one instance. There are also ways to support shared state, but this is difficult. To me singletons are not a code smell either, but they have their own problems.
Your problem might be solved by storing whatever state you need in the browser either in a cookie or localStorage. Your service would then have request scope, but it would read user state from browser causing “user scope” for the data. (But don’t rely on browser state to persist and remember it is modifiable to the user.)

Restart IIS AppDomain on type initializer/static constructor exception

I've got an ASP.NET that relies on some code that uses static constructors. The code in these type initializers sometimes fails. Let's say, for sake of argument, that the code is:
public static readonly string Thing = SomeSpecialCallThatRarelyFails();
Perhaps that's vile, but it cannot be changed. And this kinda code is in every controller, so ASP.NET can't create the controller and just sits there broken until someone comes along to restart it.
I understand this is the way it should be, because the problem may very well be non-transient and auto-restarting would create a loop. Or perhaps only one controller fails, so the app is still sort of alive. So I get the default behaviour to just keep returning the error. But in this particular case, let's pretend the best thing is to notice this failure and restart.
How can I automate the detection of this scenario and trigger a restart or recycle of the IIS app pool/AppDomain?
I've noticed that if I cause an exception on Application_Start, then the app will auto-restart. So one way is for me to iterate over all my types and try accessing them. If they have .cctor failures, then I'll crash Application_Start and ASP.NET will restart. But that's pretty hacky, plus it won't help if the actual request code references another type that I don't know about which throws on .cctor.
Is there a better way? Should I write a Web API filter and look for TypeInitializerException or something?
Just a thought. Is the 'rare failure' deterministic? Could it be solved by adding retry logic?
public static readonly string Thing = RetrySpecialCall();
private static string RetrySpecialCall()
{
while (true)
{
try
{
return SomeSpecialCallThatRarelyFails();
}
catch (Exception) {}
}
}
So here's a way to handle it in Web API 1:
In Application_Start, iterate over your controller types, calling System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor to force all your known type constructors to run. If it Application_Start fails, ASP.NET seems to restart.
Add an exception filter that looks for TypeInitializationExceptions. Then call HttpRuntime.UnloadAppDomain().
The two parts are needed as a controller failing to construct will not hit the exception filters.
With Web API 2 it seems like you could do it in one go by implementing System.Web.Http.ExceptionHandling.IExceptionLogger and registering it as a global service. Same logic: check for TypeInitializationException and UnloadAppDomain if so.

SimpleMembershipProvider intermittently returning wrong user

I am administrator of a small practice project web application, AngularJS front-end pulling its back-end data from a C#/.NET WebAPI, and I'm handling security using the SimpleMembershipProvider.
I suspect that the way I implemented said security is not the best (I'm told ASP.NET Identity is now the way to go?) but that's another question altogether.
The issue that I'm very bewilderingly running into is that I get occasional reports that on a given page load to display a particular user's data, it returns somebody else's. Reloading the page fixes the issue (evidently) and I haven't been able to duplicate the scenario myself, or figure out anything particularly consistent in the users to which this happens.
None of the information being displayed is at all sensitive in nature (the app's just a friendly front end for an already public third-party API) so I'm not in panic mode about this, but I am both concerned and confused and want it fixed.
Here is what one of my API controller endpoints looks like:
[Authorize]
public class UserController : ApiController
{
private static int _userId;
private readonly IUserProfileRepository _userProfileRepository;
public UserController()
{
_userProfileRepository = new UserProfileRepository(new DatabaseContext());
_userId = WebSecurity.GetUserId(User.Identity.Name);
}
public UserProfileDto Get()
{
return _userProfileRepository.GetUserProfileById(_userId).ToDto();
}
}
Any feedback on where I might be going wrong here or what might be causing the intermittant inconsistency would be very much appreciated. (Laughter also acceptable if the way I handled this is just really bad. :P )
Static class fields are shared by all instances/threads of the same AppDomain (in your case - process). Different http requests are processed by threads running in parallel. Any two threads running [almost] at the same time may (will) change the value of _userId. You are assigning _userId in the constructor of your controller, and a new instance of this controller is created for each http request that is to be responded to by UserController. Therefore, this assignment will happen multiple times.
You will have hard time replicating this problem, since you are a single user testing the code, hence there are no overlapping request threads.
Remove static specifier from the _userId field declaration of the controller class.
Note: make sure that DatabaseContext is disposed of. One place that can be used for this is the overriden Controller.Dispose.
Change the Get to retrieve the user id rather than from a static variable:
public UserProfileDto Get()
{
return _userProfileRepository.GetUserProfileById(WebSecurity.GetUserId(User.Identity.Name)).ToDto();
}

override Request.QueryString

Hello fellow seasoned developers!
I was wondering if it were possible to override the .Net Request.QueryString object somehow? It would be really nice if this could be done without having to create my own HTTP module as well.
I have been tasked with RSA(1024) encrypting all the querystrings in my application. However, the application is already built and there's a LOT of places where querystrings are being set so ideally i would like to make a global change that would decrypt the query and place it in the normal Request.QueryString so as to not have to change my code everywhere, and maybe pass it along to other devs within my team and they also don't have to change their code.
Now, I already built the encryption object and use the SessionID for salts to make the keys unique per session. I have also tried intercepting the HTTP request in Global.asax so as to rewrite the request path with the decrypted query, however, that was a bust as any postbacks being performed on those pages put the decrypted querystring back into the POST, which i obviously don't want.
So now i'm at a stage where i would like instead of re-writing the path, to intercept or override the Request.QueryString object on a global level and use my decryption methods there whenever a call to this[key] is placed, and thus again, not having to stop using Request.QueryString. However, after hours of searching on the web, i could not find a single example on how to do this...
If anyone could help me out with this i would be most grateful!
I think the easiest way to accomplish this is to use an Extension Method. Perhaps something like this:
class Program
{
static void Main()
{
var decryptedValue = HttpContext.Current.Request.DecryptQueryStringParam("myParam");
}
}
public static class HttpRequestExtensions
{
public static string DecryptQueryStringParam(this HttpRequest extendee, string name)
{
// do stuff to decrypt
return DecryptMethodStub(extendee.QueryString[name]);
}
private string DecryptMethodStub(string queryString)
{
return "something decrypted the string";
}
}
Please note that the Program class above is for illustrative purposes only... in reality you would call Request.{ExtensionMethod} within the body of a asp.net web forms page or an MVC controller which already provide direct access to the HttpRequest object through the Request property.
here is some information about extensions:
http://msdn.microsoft.com/en-us/library/bb383977.aspx

Code to be run automatically when the request is finished?

I have my own SQL based session class. I want to automatically commit the data in the session at the end of program execution (i.e. at the end of serving the page request). Do object destructors (finalizers) not get executed at the end of every request? Is there anyway of doing this instead of having to explicitly call a Dispose() method every time I am done with my session object?
One possibility is by using the global.asax. There is a handler for the end of a request, in C# the call inside global.asax.cs would look something list this:
protected void Application_EndRequest(object sender, EventArgs e){
//perform action - you have access to the HttpContext
}
You have to watch out for what is going through the handler though - depending on your configuration your assets (stylesheet, images, etc.) may also be hitting this request so you may have to devise a way to ensure only your pages have the actions taken on them.
In C#, finalizers are non-deterministic, which means you don't have any guarantee when it will be executed. So, no, you can't use them for your scenario.
I see two ways to approach this:
Programmatically calling Dispose at some point towards the end of the page's life cycle (or via the global.asax as mentioned by Michael G.).
Have your SQL based session class wire itself up to a page event (such as the Unload event) to do whatever actions it wants to clean itself up.
UPDATE:
In response to your question about suggestion #2, I will expound a bit. This option would be to somehow allow your SQL based session class to gain a refernce to the web page instance. One option (which I'll show below) would be to use the constructor of the SQL based session class to obtain a reference to the web page. Then the SQL based session class can sign up for any event that it desires in order to know what is happening to the page.
namespace SomeNamespace
{
using System.Web.UI;
public class SqlBasedSession
{
public SqlBasedSession(Page webPage)
{
webPage.Unload += new EventHandler(webPage_Unload);
}
void webPage_Unload(object sender, EventArgs e)
{
// the web page is being unloaded so this class can
// cleanup it's resources now
}
}
}
Let me know if this still isn't clear.
I would suggest to go with IOC container provider for these kind of stuff. You can hook them up, to the end of a request and execute some code, especially good for some transactional stuff.
I have been using Autofac, it has OnActivated() method, which I use to hook my transaction commits to on activation of session.

Categories