Accessing HttpContext from within a customised (extended) MembersRoleProvider class
Hi all,
I have a question in regards to accessing the HttpContext from within an extended MembersRoleProvider class.
I'll give some background first:
To allow me to authenticate against a separate system / database rather than standard Umbraco backend users, I have bypassed the Umbraco membership login / authentication by extending both the UsersMembershipProvider & MembersRoleProvider classes (along with changing the UmbracoMembershipProvider and UmbracoRoleProvider keys of the Web.Config so it makes use of these extended classes). This is based roughly on Umbraco 7 Custom Membership and Role Providers, and it is all working well.
To allow me to return a little more than just the normal MembershipUser info, I have also (within the extended UsersMembershipProvider class) extended the MembershipUser class (which is what gets returned by GetUser method). It returns a few additional parameters to what it usually would when authenticating (being additional parameters which are essentially roles defined within the separate system / database and which are to get used for displaying / hiding certain pages within the site - or occasionally a section of the site such as on the home page). Having done this, it allows me to obtain these additional parameters from within my SignInController (by calling this GetUser method of the custom Membership Provider), and after which I then add these parameters as Session variables (for accessing them elsewhere later):
Finally, to tie the roles from the separate system / database to the Umbraco backend, I have (within the Umbraco back office) created Member Groups that each correlate to one of these aforementioned roles (parameters) obtained from the separate system, i.e. these can get linked to a content page created in the back office by using the Public Access / Role Based Protection option in the backoffice to apply role based protection to the page and all its children), and within the string [] GetRolesForUser method of my extended MembersRoleProvider I return a string of roles corresponding to the just mentioned ones in existence in the Umbraco backend.
Here lies the problem. In order to establish which roles to return within this string [] GetRolesForUser method I'd like to be able to access my session variables which would already have been set earlier when having authenticated, e.g. HttpContext.Current.Session["roleparam1"] etc, however I am unable to work out how to access the HTTP Context from here (from within my extended MembersRoleProvider class)? When I try HttpContext.Current is null.
I am able obtain the roles / parameters once again by directly calling a method I exposed within the extended UsersMembershipProvider class (which in turn just calls the GetUser method within the UsersMembershipProvider class once again), however it does result in unnecessary hits on the database, since (as example) every time I make use of @if (Members.IsLoggedIn()) within a cshtml template (a View), the string [] GetRolesForUser method of the extended MembersRoleProvider gets invoked. Rather than hit the database each time this is invoked I'd much rather just poll this information I have already obtained and saved into the HTTP Context as session variables.
Below is my string [] GetRolesForUser method (GetVSPlatUser is just a method I exposed within my custom UsersMembershipProvider class - which I use also during initial authentication initiated from my SignInController code to obtain the additional parameters):
public override string[] GetRolesForUser(string username)
{
StringCollection CollectionOfRolesForUser = new StringCollection();
//Unnecessary call to method in UsersMembershipProvider just in order to obtain roles (taking into account they'd already be set as session variables)
PlatinumMembershipUser platinumMembershipUser = PlatinumUserHelperFunctions.GetVSPlatUser(username);
if (platinumMembershipUser.HasRegisteredCardForAuWHV)
CollectionOfRolesForUser.Add("Australia");
if (platinumMembershipUser.HasRegisteredCardForNzWHV)
CollectionOfRolesForUser.Add("New Zealand");
// What I'd ideally want to be able to do
//if (HttpContext.Current.Session["Has_Registered_Card_ForAuWHV"] != null)
// if (((bool)(HttpContext.Current.Session["Has_Registered_Card_ForAuWHV"]) == true))
// CollectionOfRolesForUser.Add("Australia");
//if (HttpContext.Current.Session["Has_Registered_Card_ForNzWHV"] != null)
// if (((bool)(HttpContext.Current.Session["Has_Registered_Card_ForNzWHV"]) == true))
// CollectionOfRolesForUser.Add("New Zealand");
string[] ArrayOfRolesForUser = new string[CollectionOfRolesForUser.Count];
CollectionOfRolesForUser.CopyTo(ArrayOfRolesForUser, 0);
return ArrayOfRolesForUser;
}
My SignInController code:
public class SignInController : SurfaceController
{
public ActionResult SignIn(SignInModel model)
{
if (!ModelState.IsValid)
{
Members.Logout();
Session.Clear();
return CurrentUmbracoPage();
}
CustomMembershipProvider custMemProvider = new CustomMembershipProvider();
//if we can login ok redirect to page
if (Members.Login(model.EmailAddress, model.Password))
{
PlatinumMembershipUser platUser = custMemProvider.GetUser(model.EmailAddress);
//Set Session variables
System.Web.HttpContext.Current.Session["Has_Registered_Card_ForAuWHV"] = platUser.HasRegisteredCardForAuWHV;
System.Web.HttpContext.Current.Session["Has_Registered_Card_ForNzWHV"] = platUser.HasRegisteredCardForNzWHV;
// Just mucking about but this is not required as occurs automatically during custMemProvider.GetUser
//custMemProvider.ValidateUser(model.EmailAddress, model.Password);
if ((CurrentPage.Url == "/") || (CurrentPage.Url == "/home/" ) || (CurrentPage.Url == "/contact/"))
{
if (platUser.HasRegisteredCardForAuWHV)
{
return Redirect("/australia");
}
else if (platUser.HasRegisteredCardForNzWHV)
{
return Redirect("/new-zealand");
}
else
{
return Redirect("/home");
}
}
else
{
return RedirectToCurrentUmbracoPage();
}
}
else
{
ModelState.AddModelError("", "Invalid Login");
if (Members.IsLoggedIn())
{
Members.Logout();
}
Session.Clear();
return Redirect("/home");
}
}
public ActionResult SignOut()
{
Members.Logout();
Session.Clear();
return Redirect("/home");
}
}
Sorry for the long writeup of the background related to my question, but I didn't want to ask the question without it making some sense why I am asking it.
I am hoping there is something simple I am missing whereby I could access my already set Session variables (set at time of authenticating), so that I don't end up having to hit the database every time the string [] GetRolesForUser method gets invoked (every time the roles for the user gets requested and returned), so if anyone can steer me to what I may be overlooking that would be tremendously appreciated.
Accessing HttpContext from within a customised (extended) MembersRoleProvider class
Hi all,
I have a question in regards to accessing the HttpContext from within an extended MembersRoleProvider class.
I'll give some background first:
To allow me to authenticate against a separate system / database rather than standard Umbraco backend users, I have bypassed the Umbraco membership login / authentication by extending both the UsersMembershipProvider & MembersRoleProvider classes (along with changing the UmbracoMembershipProvider and UmbracoRoleProvider keys of the Web.Config so it makes use of these extended classes). This is based roughly on Umbraco 7 Custom Membership and Role Providers, and it is all working well.
To allow me to return a little more than just the normal MembershipUser info, I have also (within the extended UsersMembershipProvider class) extended the MembershipUser class (which is what gets returned by GetUser method). It returns a few additional parameters to what it usually would when authenticating (being additional parameters which are essentially roles defined within the separate system / database and which are to get used for displaying / hiding certain pages within the site - or occasionally a section of the site such as on the home page). Having done this, it allows me to obtain these additional parameters from within my SignInController (by calling this GetUser method of the custom Membership Provider), and after which I then add these parameters as Session variables (for accessing them elsewhere later):
Finally, to tie the roles from the separate system / database to the Umbraco backend, I have (within the Umbraco back office) created Member Groups that each correlate to one of these aforementioned roles (parameters) obtained from the separate system, i.e. these can get linked to a content page created in the back office by using the Public Access / Role Based Protection option in the backoffice to apply role based protection to the page and all its children), and within the string [] GetRolesForUser method of my extended MembersRoleProvider I return a string of roles corresponding to the just mentioned ones in existence in the Umbraco backend.
Here lies the problem. In order to establish which roles to return within this string [] GetRolesForUser method I'd like to be able to access my session variables which would already have been set earlier when having authenticated, e.g. HttpContext.Current.Session["roleparam1"] etc, however I am unable to work out how to access the HTTP Context from here (from within my extended MembersRoleProvider class)? When I try HttpContext.Current is null.
I am able obtain the roles / parameters once again by directly calling a method I exposed within the extended UsersMembershipProvider class (which in turn just calls the GetUser method within the UsersMembershipProvider class once again), however it does result in unnecessary hits on the database, since (as example) every time I make use of @if (Members.IsLoggedIn()) within a cshtml template (a View), the string [] GetRolesForUser method of the extended MembersRoleProvider gets invoked. Rather than hit the database each time this is invoked I'd much rather just poll this information I have already obtained and saved into the HTTP Context as session variables.
Below is my string [] GetRolesForUser method (GetVSPlatUser is just a method I exposed within my custom UsersMembershipProvider class - which I use also during initial authentication initiated from my SignInController code to obtain the additional parameters):
My SignInController code:
Sorry for the long writeup of the background related to my question, but I didn't want to ask the question without it making some sense why I am asking it.
I am hoping there is something simple I am missing whereby I could access my already set Session variables (set at time of authenticating), so that I don't end up having to hit the database every time the string [] GetRolesForUser method gets invoked (every time the roles for the user gets requested and returned), so if anyone can steer me to what I may be overlooking that would be tremendously appreciated.
This is an Umbraco version 7.5.4 site.
Regards,
Keith
In similar situations I will pass in the HttpContext from the calling object.
This would change the signature of your GetRolesForUser method to something like
which you can then use like
You would then call the method like this
is working on a reply...