I'd like to pick your brains for what's the best solution to this problem...I have a standalone database that already contains username / password pairs.
I'd like to use those to validate users (Umbraco Members) on my Umbraco website. So, when a new umbraco member tries to login to my website I'd like to be able to check if they entered username/password pair that is present in the standalone database, and if they have, then check to see if the member on my umbraco website with the used username exists, if it doesn't I'd like to make a new member; if it does, then I'd like to login that existing member and read his personal property (which he would be able to change).
I'd like to do this without changing the standalone database, so my guess is a combo of a custom membership provider *with custom ValidateUser method - one that would do the username/password check and consequent creation of new members in the umbraco database* and a custom umbraco member type (that I'll be creating and expanding to have the property I'll use is needed).
Can I use the Umbraco API calls (and which plaese - which are bestpractice) inside the custom membership provider to make new members each
Create your own membership provider class, that inherits from the umbraco one. Override the methods that handle password stuff, so that it checks passwords against you own DB.:
public class MyMembershipProvider : umbraco.providers.members.UmbracoMembershipProvider
{
public override bool ValidateUser(string username, string password)
{
//Do your code here
}
//Override other methods like "change password" if you want to use those.
}
Then build your "create user if not exists" logic in your login control logic, rather than placing it in the membership provider.
You can create members using the standard asp.net membership classes, which will create them in umbraco. However, getting the custom userfield you should probably do through the umbraco api like this:
First off, thanks for your reply, it was helpful. I realized how to build my own membership provider and after a couple of days of tinkering got it working. The inital fault in setting it up was within my web.conifg default membership provider setting.
However, although I am now able to login, I am having problems accessing the currently logged in user after logging in...
According to umbraco wiki one should use the method call:
System.Web.Security.Membership.GetUser();
But, I'm guessing, it fails since I have not implemented that method (or even some other methods?!) in my custom membership provider...my question is...how should one implement it i.e. I tried to instance a new System.Web.Security.MembershipUser variable and return it inside
public override MembershipUser GetUser(string username, bool userIsOnline)
after just simply assiging the username field to that newly instantiated local MembershipUser variable, but that didn't work....
I'm relying on umbraco.library's GetCurrentMember call in XSLT but that returns a null, so please could you help me realize what and where am I missing stuff?
p.s.
Should I maybe place some umbraco's AddMemberToCache() call inside the logged in event handler of the asp:login control I am now using for logging members in? But if I don't have a working GetUser() what should I pass to the AddMemberToCache then? Much thanks in advance to all :)
Well, it depends on how you implemented your provider.
Did you inherit from umbraco provider, or how did you go about it?
I'm not sure exactly which method in your provider gets called when using the System.Web.Security.Membership.GetUser(); method. But you can probably find out by debugging through the code.
If you inherited from umbraco provider, then you should be able to just not override the method, and Umbraco will take care of it for you.
Yes you were right, I inherited the regular MembershipProvider instead of Umbraco's UsersMembershipProvider, and changing that did help in the sense that I now could use:
System.Web.HttpContext.Current.User.Identity.Name
to acess the currently logged in user in codebehind of controls that are placed inside the non-anonymous template of the asp:loginview control.
However, I am using the asp:loginview inside of whose anonymous template I placed a regular asp:login control which does the login for me (validating entered username/password through my custom membership provider which now inherits Umbraco's UsersMembershipProvider and overrides just that one ValidateUser method). What I thought should work is to have that validated (and what I thought was logged in) user get added to umbraco member cached by calling
inside of the asp:login controls' LoggedIn event handler code. However the value of
System.Web.HttpContext.Current.User.Identity.Name
is empty in the LoggedIn event handler of the asp:login control?
Maybe I wrote the ValidateUser wrong, maybe it should of done more than just return true if username/password is valid, but what more please?!
p.s.
On a sidenote...the System.Web.Security.Membership.GetUser() method call also returns null inside the LoggedIn event handler code, but also inside of the codebehind of controls that get displayed in the non-anonymous (logged in) template of the asp:loginview control...those controls are in fact just gonna be buttons that will do member customized postbacks or something like that.
Those now work using System.Web.HttpContext.Current.User.Identity.Name.
But my problem, I think, is that without the AddMemberToCache() call the umbraco.library XSLT extension GetCurrentMember() doesn't work either - and I need that to return data from the member profile I'd like store on umbraco's member storage.
Could you share your implementation? It might be easier to figure out what is going on if I could see the code.
I don't think you need to call the AddMemberToCache method. The base provider should take care of all that for you. Version 4.0.3 is not using any umbraco specific cookies when signing in. But there might be issues with the xslt extension as you mention.
Are you by any chance running your site with directory url's enabled? Or on the front page? There have been some reports that the System.Web.Security.Membership.GetUser() method returns null under those circumstances.
Offcourse I'll share, just unclear as to what (or how) exactly? I'll post code here if you'd like, but if you'd like I could also email the whole projects (membershipprovider & membershipcontrol) to a specified address... Only I couldn't find one on your website or a PM function here to ask for it.
As for the directory urls config I think it's off, it should be mostly untouched installation, but just to make sure I will try setting up on another umbraco vannilla install and get back to you here just as soon as I do (unless you get back to me first with instructions to post/send stuff elsewhere:)
Well I tried this on another Umbraco install and it's the same thing...XSLT calls to GetCurrentMember() don't return a logged in member though the login view control bellow shows me the logged in template view?!
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using umbraco.cms.businesslogic.member;
using umbraco.BusinessLogic;
using System.Net;
using System.Collections.Specialized;
using System.IO;
namespace ftnMemberControls
{
public partial class MemberLogin : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
// THIS WORKS FINE...ONCE THE ASP:LOGIN MyMebershipProvider VALIDATION...THE BUTTON WILL REDIRECT TO PERSONALIZED URL
protected void memberButton_Click(object sender, EventArgs e)
{
myDBDataContext db = new myDBDataContext(myConnectionString);
string pass = (string)(from user in db.WEB_USERS
where user.WEB_ID == System.Web.HttpContext.Current.User.Identity.Name
select user.WEB_PASS).SingleOrDefault();
string URLRedirect = "";
if (System.Web.HttpContext.Current.User.Identity.Name != null)
{
URLRedirect = "https://umbraco/do?action=login&userName=" + System.Web.HttpContext.Current.User.Identity.Name + "&pass=" + pass;
Response.Redirect(URLRedirect);
}
else
{
URLRedirect = "http://error"; Response.Redirect(URLRedirect);
}
db.Connection.Close();
}
protected void lbLogout_Click(object sender, EventArgs e)
{
FormsAuthentication.SignOut();
Response.Redirect("/");
}
protected void MyLoginControl_LoggedIn(object sender, EventArgs e)
{
MemberType mt = MemberType.GetByAlias("test");
MembershipUser mu = System.Web.Security.Membership.GetUser();
Member um = Member.GetMemberFromLoginName(System.Web.HttpContext.Current.User.Identity.Name);
//System.Web.Security.Membership.GetUser().UserName); <-- Tried this but won't work
//((TextBox)LoginView.FindControl("tbxUserName")).Text); <-- This used to work, but before I used asp:Login, but it also stopped working soon for some reason I didn't understand
if (um == null)
{
um = Member.MakeNew(System.Web.HttpContext.Current.User.Identity.Name, mt, umbraco.BusinessLogic.User.GetUser(0));
//((TextBox)LoginView.FindControl("tbxUserName")).Text, mt, umbraco.BusinessLogic.User.GetUser(0));
um.getProperty("frame").Value = "default";
}
////THIS IS WHAT I ALSO TRIED USING, BUT IT WOULDN'T WORK EITHER, THOUGH THE LOGGED IN USER NAME CHANGES THE XSLT GetCurrentMember() CALL DOESN'T WORK
//um.XmlGenerate(new System.Xml.XmlDocument());
//Member.RemoveMemberFromCache(Member.GetMemberFromLoginName(System.Web.HttpContext.Current.User.Identity.Name));
//Member.AddMemberToCache(Member.GetMemberFromLoginName(System.Web.HttpContext.Current.User.Identity.Name));
//// or alternatively
//Member.AddMemberToCache(um, true, new TimeSpan(0, 0, 0));
}
}
}
And here is the extremely simple MyMembershipProvider which I've set as defaultProvider:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Data.SqlClient;
using System.Data;
using umbraco.providers;
namespace FTNMembershipProvider
{
public class FTNMembershipProvider : UsersMembershipProvider
{
//public override string ApplicationName
//{
// get
// {
// throw new NotImplementedException();
// }
// set
// {
// throw new NotImplementedException();
// }
//}
//public override bool ChangePassword(string username, string oldPassword, string newPassword)
//{
// throw new NotImplementedException();
//}
//public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
//{
// throw new NotImplementedException();
//}
//public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
//{
// throw new NotImplementedException();
//}
//public override bool DeleteUser(string username, bool deleteAllRelatedData)
//{
// throw new NotImplementedException();
//}
//public override bool EnablePasswordReset
//{
// get { throw new NotImplementedException(); }
//}
//public override bool EnablePasswordRetrieval
//{
// get { throw new NotImplementedException(); }
//}
//public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
//{
// throw new NotImplementedException();
//}
//public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
//{
// throw new NotImplementedException();
//}
//public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
//{
// throw new NotImplementedException();
//}
//public override int GetNumberOfUsersOnline()
//{
// throw new NotImplementedException();
//}
//public override string GetPassword(string username, string answer)
//{
// throw new NotImplementedException();
//}
//public override MembershipUser GetUser(string username, bool userIsOnline)
//{
// throw new NotImplementedException();
//}
//public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
//{
// throw new NotImplementedException();
//}
//public override string GetUserNameByEmail(string email)
//{
// throw new NotImplementedException();
//}
//public override int MaxInvalidPasswordAttempts
//{
// get { throw new NotImplementedException(); }
//}
//public override int MinRequiredNonAlphanumericCharacters
//{
// get { throw new NotImplementedException(); }
//}
//public override int MinRequiredPasswordLength
//{
// get { throw new NotImplementedException(); }
//}
//public override int PasswordAttemptWindow
//{
// get { throw new NotImplementedException(); }
//}
//public override MembershipPasswordFormat PasswordFormat
//{
// get { throw new NotImplementedException(); }
//}
//public override string PasswordStrengthRegularExpression
//{
// get { throw new NotImplementedException(); }
//}
//public override bool RequiresQuestionAndAnswer
//{
// get { throw new NotImplementedException(); }
//}
//public override bool RequiresUniqueEmail
//{
// get { throw new NotImplementedException(); }
//}
//public override string ResetPassword(string username, string answer)
//{
// throw new NotImplementedException();
//}
//public override bool UnlockUser(string userName)
//{
// throw new NotImplementedException();
//}
//public override void UpdateUser(MembershipUser user)
//{
// throw new NotImplementedException();
//}
//SORY FOR THE COMMENTING OUT - I INITIALLY INHERITED REGULAR MEMBERSHIP PROVIDER ABSTRACT CLASS
public override bool ValidateUser(string username, string password)
{
bool isValid = false;
MyDBDataContext db = new MyDBDataContext(MyConnectionString);
IQueryable<WEB_USERS> MatchingUsers = from x in db.WEB_USERS
where x.WEB_ID.CompareTo(username) == 0 && x.WEB_PASS.CompareTo(password) == 0
select x;
if (MatchingUsers.Count() > 0)
{
isValid = true;
}
else
{
isValid = false;
}
return isValid;
}
}
}
What am I missing please?! It has to be something rather simple? Thanks in advance.
I just realized that I don't have MemberTypes anymore?!? It must be because of the custom MembershipProvider I wrote, or the way I configured it, but the nod in members umbraco backend section is no longer visible! Just the Members and MemberGroups nodes...
Here's my setup for the membership providers in web.config:
I'm guessing I forgot to implement something in the ultra simple MembershipProvider...or the defaultProvider should of stayed "UmbracoMembershipProvider/UsersMembershipProvider"...I'm gonna change defaultProvider and report back here ASAP.
Not it...that is...when I put "UmbracoMembershipProvider" GetCurrentMember() XSLT will work but only if I previously added the member manually to the backend (which is what I'm trying to avoid).
So, what am I doing wrong, I was guessing that the
MemberType mt = MemberType.GetByAlias("test");
could of been returning jibberish since I couldn't see member types node in the backend but by debuging (when default membership provider was set to my custom one) I saw it actually does return the type and "sees" all the properties I need...it's just that the two calls after that line inside of the logged in event handler don't work:
MembershipUser mu =System.Web.Security.Membership.GetUser();
^-- this one throws System.NullReferenceException: Object reference not set to an instance of an object.
Member um =Member.GetMemberFromLoginName(System.Web.HttpContext.Current.User.Identity.Name);
^-- this one just returns "" as the System.Web.HttpContext.Current.User.Identity.Name and the System.Web.HttpContext.Current.User.Identity.IsAuthenticated retruns false, thought this one call works when called inside the codebind associated with a button inside a logged in view template.
Will try and see if I can take a look at this tomorrow, but just a quick note. Seems like you are inheriting from the wrong provider. You should inherit from UmbracoMembershipProvider (frontend users) and not UsersMembershipProvider (Backend users).
Thanks for the tip, I changed the inherited provider, that being quite a dumm mistake from me - considering there's an uppercase tooltip saying that UmbracoMP is for Frontend and not Backend users.....However, the problem is still present, inside of the LoggedIn event handler of the asp:login control GetUsers() isn't working right for me.....I must of missed something very simple (was looking at Members.cs code last night and couldn't find it though).
using umbraco.BusinessLogic;
using umbraco.cms.businesslogic.member;
using umbraco.providers.members;
namespace MyMemberProvider
{
public class MyProvider : UmbracoMembershipProvider
{
public override bool ValidateUser(string username, string password)
{
bool isValid = true; //Do you validation stuff here
if (!isValid) return false; //Return false if not validated
var user = GetUser(username, false); //Try and get a user
if (user == null) {
//Create user
var memberType = MemberType.GetByAlias("StandardMember");
Member.MakeNew(username, memberType, new User(0));
}
return isValid;
}
}
}
In my web.config I added my new provider, and set it as the default:
In the web.config I also added a handler (<add name="RootHandler"....) to make sure that the asp.net modules were run on my root page. This helped with not getting nullreference exceptions when getting the current member. You may want to try the <modules runAllManagedModulesForAllRequests="true"> instead.
You're gonna be really mad...it works partially...I'm guessing that the problem is with my membership provider, since I can't see member properties in the backend, the following XSLT won't "see" the property either:
However in the codebehind the GetCurrentMember() on those asp:button controls works...and in the watch window I can see the property "frame"...should I be obligated to write a custom profile provider beside the memberprovider too?!
Unfortunately, that ^ is what I get, I will try today on another clean umbraco install (installed from microsoft web platform installer)...but I'm guessing that since I cannot see the property in the backend I cannot see it in GetCurrentMember() call...can you see your member's "myprop" property in the member backend section when the member is selected (or the member type node in the members tree on the left)?
Now I see the MemberTypes node in the backend and I can see the value of the custom "frame" property initially set in the login's user control via codebehind:
um.getProperty("frame").Value = "default";
However, when logged in, the value returned from GetCurrentMember() call is still empty as indicated by the selfclosing xml node on the bottom of the code bellow:
Sooo...even more strange...even though I could see the value in the backend, but not in GetCurrentMember XSLT queries, once I entered the value once again in the backend and clicked the save icon manually, voila, magic it's there (even in XSLT)!!! :))) So, even though you can see it in the backend it doesn't mean GetCurrentMember() will see it in the frontend (XSLT) :P So this is my solution for now, I deleted all the members which were created prior to the changes in membershipprovider and added the code bellow (which I think is an overkill though) after setting the proprty as I did before to the MembershipProvider which now works:
um.Save();
Just as a recap...
So you shouldn't rename the custom MembershipProvider to anything else but the "UmbracoMembershipProvider"...just change the type value in web.config...that is enough. Make new umbraco members inside of the codebehind of your membership provider (please confirm Morten?!) and use Save() - though that might be an overkill. And don't use the asp:Login control's LoggedIn event, it doesn't work, well not as it name implies (since the User won't be set in the Context at the time it runs).
Will try this later today on the vanilla umbraco, hopefully it will all work (as it works on this staging install;), fingers crossed X
Good to hear that it is working. The reason that the value didn't show up might be because the xml that the xslt get's is cached somewhere, and because of that, the newest value is not apperaing. So the Save() call might just be the thing that refreshes that cache, and repopulates the xml.
With regards to the name of the provider, in this case I think it is ok to use the same name. Umbraco's members section is dependant on it's own API, so it probably disables stuff when it is not the original provider. But since yours inherits from the original, I think it will be fine.
membership api question
Hi,
I'd like to pick your brains for what's the best solution to this problem...I have a standalone database that already contains username / password pairs.
I'd like to use those to validate users (Umbraco Members) on my Umbraco website. So, when a new umbraco member tries to login to my website I'd like to be able to check if they entered username/password pair that is present in the standalone database, and if they have, then check to see if the member on my umbraco website with the used username exists, if it doesn't I'd like to make a new member; if it does, then I'd like to login that existing member and read his personal property (which he would be able to change).
I'd like to do this without changing the standalone database, so my guess is a combo of a custom membership provider *with custom ValidateUser method - one that would do the username/password check and consequent creation of new members in the umbraco database* and a custom umbraco member type (that I'll be creating and expanding to have the property I'll use is needed).
Can I use the Umbraco API calls (and which plaese - which are bestpractice) inside the custom membership provider to make new members each
TIA
My setup:
Umbraco v4.0.3
IIS 7 / ASP.NET 3.5
WIN SERVER 2008 R2
I think you could do the following:
Create your own membership provider class, that inherits from the umbraco one. Override the methods that handle password stuff, so that it checks passwords against you own DB.:
You can create members using the standard asp.net membership classes, which will create them in umbraco. However, getting the custom userfield you should probably do through the umbraco api like this:
I wrote a post on setting up the membership provider so that the "Create" functions work:
http://www.mortenbock.dk/blog/2009/04/01/setting-up-membership-in-umbraco.aspx
Enjoy
Hi morten,
First off, thanks for your reply, it was helpful. I realized how to build my own membership provider and after a couple of days of tinkering got it working. The inital fault in setting it up was within my web.conifg default membership provider setting.
However, although I am now able to login, I am having problems accessing the currently logged in user after logging in...
According to umbraco wiki one should use the method call:
But, I'm guessing, it fails since I have not implemented that method (or even some other methods?!) in my custom membership provider...my question is...how should one implement it i.e. I tried to instance a new System.Web.Security.MembershipUser variable and return it inside
after just simply assiging the username field to that newly instantiated local MembershipUser variable, but that didn't work....
I'm relying on umbraco.library's GetCurrentMember call in XSLT but that returns a null, so please could you help me realize what and where am I missing stuff?
p.s.
Should I maybe place some umbraco's AddMemberToCache() call inside the logged in event handler of the asp:login control I am now using for logging members in? But if I don't have a working GetUser() what should I pass to the AddMemberToCache then? Much thanks in advance to all :)
Well, it depends on how you implemented your provider.
Did you inherit from umbraco provider, or how did you go about it? I'm not sure exactly which method in your provider gets called when using the System.Web.Security.Membership.GetUser(); method. But you can probably find out by debugging through the code.
If you inherited from umbraco provider, then you should be able to just not override the method, and Umbraco will take care of it for you.
Hi Morten,
Yes you were right, I inherited the regular MembershipProvider instead of Umbraco's UsersMembershipProvider, and changing that did help in the sense that I now could use:
to acess the currently logged in user in codebehind of controls that are placed inside the non-anonymous template of the asp:loginview control.
However, I am using the asp:loginview inside of whose anonymous template I placed a regular asp:login control which does the login for me (validating entered username/password through my custom membership provider which now inherits Umbraco's UsersMembershipProvider and overrides just that one ValidateUser method). What I thought should work is to have that validated (and what I thought was logged in) user get added to umbraco member cached by calling
System.Web.HttpContext.Current.User.Identity.Name
is empty in the LoggedIn event handler of the asp:login control?
Maybe I wrote the ValidateUser wrong, maybe it should of done more than just return true if username/password is valid, but what more please?!
p.s.
On a sidenote...the System.Web.Security.Membership.GetUser() method call also returns null inside the LoggedIn event handler code, but also inside of the codebehind of controls that get displayed in the non-anonymous (logged in) template of the asp:loginview control...those controls are in fact just gonna be buttons that will do member customized postbacks or something like that.
Those now work using System.Web.HttpContext.Current.User.Identity.Name.
But my problem, I think, is that without the AddMemberToCache() call the umbraco.library XSLT extension GetCurrentMember() doesn't work either - and I need that to return data from the member profile I'd like store on umbraco's member storage.
Could you share your implementation? It might be easier to figure out what is going on if I could see the code.
I don't think you need to call the AddMemberToCache method. The base provider should take care of all that for you. Version 4.0.3 is not using any umbraco specific cookies when signing in. But there might be issues with the xslt extension as you mention.
Are you by any chance running your site with directory url's enabled? Or on the front page? There have been some reports that the System.Web.Security.Membership.GetUser() method returns null under those circumstances.
Hi Morten and again thanks for replying,
Offcourse I'll share, just unclear as to what (or how) exactly? I'll post code here if you'd like, but if you'd like I could also email the whole projects (membershipprovider & membershipcontrol) to a specified address... Only I couldn't find one on your website or a PM function here to ask for it.
As for the directory urls config I think it's off, it should be mostly untouched installation, but just to make sure I will try setting up on another umbraco vannilla install and get back to you here just as soon as I do (unless you get back to me first with instructions to post/send stuff elsewhere:)
TIA
Hi Morten,
Well I tried this on another Umbraco install and it's the same thing...XSLT calls to GetCurrentMember() don't return a logged in member though the login view control bellow shows me the logged in template view?!
Here's the login control:
Here's the codebehind:
And here is the extremely simple MyMembershipProvider which I've set as defaultProvider:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Security; using System.Data.SqlClient; using System.Data; using umbraco.providers; namespace FTNMembershipProvider { public class FTNMembershipProvider : UsersMembershipProvider { //public override string ApplicationName //{ // get // { // throw new NotImplementedException(); // } // set // { // throw new NotImplementedException(); // } //} //public override bool ChangePassword(string username, string oldPassword, string newPassword) //{ // throw new NotImplementedException(); //} //public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer) //{ // throw new NotImplementedException(); //} //public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status) //{ // throw new NotImplementedException(); //} //public override bool DeleteUser(string username, bool deleteAllRelatedData) //{ // throw new NotImplementedException(); //} //public override bool EnablePasswordReset //{ // get { throw new NotImplementedException(); } //} //public override bool EnablePasswordRetrieval //{ // get { throw new NotImplementedException(); } //} //public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords) //{ // throw new NotImplementedException(); //} //public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords) //{ // throw new NotImplementedException(); //} //public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords) //{ // throw new NotImplementedException(); //} //public override int GetNumberOfUsersOnline() //{ // throw new NotImplementedException(); //} //public override string GetPassword(string username, string answer) //{ // throw new NotImplementedException(); //} //public override MembershipUser GetUser(string username, bool userIsOnline) //{ // throw new NotImplementedException(); //} //public override MembershipUser GetUser(object providerUserKey, bool userIsOnline) //{ // throw new NotImplementedException(); //} //public override string GetUserNameByEmail(string email) //{ // throw new NotImplementedException(); //} //public override int MaxInvalidPasswordAttempts //{ // get { throw new NotImplementedException(); } //} //public override int MinRequiredNonAlphanumericCharacters //{ // get { throw new NotImplementedException(); } //} //public override int MinRequiredPasswordLength //{ // get { throw new NotImplementedException(); } //} //public override int PasswordAttemptWindow //{ // get { throw new NotImplementedException(); } //} //public override MembershipPasswordFormat PasswordFormat //{ // get { throw new NotImplementedException(); } //} //public override string PasswordStrengthRegularExpression //{ // get { throw new NotImplementedException(); } //} //public override bool RequiresQuestionAndAnswer //{ // get { throw new NotImplementedException(); } //} //public override bool RequiresUniqueEmail //{ // get { throw new NotImplementedException(); } //} //public override string ResetPassword(string username, string answer) //{ // throw new NotImplementedException(); //} //public override bool UnlockUser(string userName) //{ // throw new NotImplementedException(); //} //public override void UpdateUser(MembershipUser user) //{ // throw new NotImplementedException(); //} //SORY FOR THE COMMENTING OUT - I INITIALLY INHERITED REGULAR MEMBERSHIP PROVIDER ABSTRACT CLASS public override bool ValidateUser(string username, string password) { bool isValid = false; MyDBDataContext db = new MyDBDataContext(MyConnectionString); IQueryable<WEB_USERS> MatchingUsers = from x in db.WEB_USERS where x.WEB_ID.CompareTo(username) == 0 && x.WEB_PASS.CompareTo(password) == 0 select x; if (MatchingUsers.Count() > 0) { isValid = true; } else { isValid = false; } return isValid; } } }
OMG OMG OMG!!!
I just realized that I don't have MemberTypes anymore?!? It must be because of the custom MembershipProvider I wrote, or the way I configured it, but the nod in members umbraco backend section is no longer visible! Just the Members and MemberGroups nodes...
Here's my setup for the membership providers in web.config:
I'm guessing I forgot to implement something in the ultra simple MembershipProvider...or the defaultProvider should of stayed "UmbracoMembershipProvider/UsersMembershipProvider"...I'm gonna change defaultProvider and report back here ASAP.
Stay tuned :)
Nope... :(
Not it...that is...when I put "UmbracoMembershipProvider" GetCurrentMember() XSLT will work but only if I previously added the member manually to the backend (which is what I'm trying to avoid).
So, what am I doing wrong, I was guessing that the
could of been returning jibberish since I couldn't see member types node in the backend but by debuging (when default membership provider was set to my custom one) I saw it actually does return the type and "sees" all the properties I need...it's just that the two calls after that line inside of the logged in event handler don't work:
^-- this one throws System.NullReferenceException: Object reference not set to an instance of an object.
^-- this one just returns "" as the System.Web.HttpContext.Current.User.Identity.Name and the System.Web.HttpContext.Current.User.Identity.IsAuthenticated retruns false, thought this one call works when called inside the codebind associated with a button inside a logged in view template.
Will try and see if I can take a look at this tomorrow, but just a quick note. Seems like you are inheriting from the wrong provider. You should inherit from UmbracoMembershipProvider (frontend users) and not UsersMembershipProvider (Backend users).
Hi Morten,
Thanks for the tip, I changed the inherited provider, that being quite a dumm mistake from me - considering there's an uppercase tooltip saying that UmbracoMP is for Frontend and not Backend users.....However, the problem is still present, inside of the LoggedIn event handler of the asp:login control GetUsers() isn't working right for me.....I must of missed something very simple (was looking at Members.cs code last night and couldn't find it though).
Anything from you is appreciated.
Ok, I have this working now. This is my solution:
My membership provider looks like this:
In my web.config I added my new provider, and set it as the default:
In the web.config I also added a handler (<add name="RootHandler"....) to make sure that the asp.net modules were run on my root page. This helped with not getting nullreference exceptions when getting the current member. You may want to try the <modules runAllManagedModulesForAllRequests="true"> instead.
In my template I just added a totally vanilla login control:
When doing this, I am able to use the xslt extension to get the current member and so on.
Let me know if it works for you.
You're gonna be really mad...it works partially...I'm guessing that the problem is with my membership provider, since I can't see member properties in the backend, the following XSLT won't "see" the property either:
However in the codebehind the GetCurrentMember() on those asp:button controls works...and in the watch window I can see the property "frame"...should I be obligated to write a custom profile provider beside the memberprovider too?!
When I use this xslt:
I get this xml
<node id="1054" version="0bbff1ec-12b3-49fc-8b47-298626593a39" parentID="-1" level="1" writerID="0" nodeType="1052" template="0" sortOrder="2" createDate="2010-05-03T19:17:32" updateDate="2010-05-03T19:17:32" nodeName="mbs" urlName="mbs" writerName="Administrator" nodeTypeAlias="StandardMember" path="-1,1054" loginName="mbs" email="[email protected]"> <data alias="myprop">testdfsfds</data> </node>
Do you get the same?
Unfortunately, that ^ is what I get, I will try today on another clean umbraco install (installed from microsoft web platform installer)...but I'm guessing that since I cannot see the property in the backend I cannot see it in GetCurrentMember() call...can you see your member's "myprop" property in the member backend section when the member is selected (or the member type node in the members tree on the left)?
Ok, some more, to me atleast, strager than bread behaviour...
I renamed my custom mebership provider to default "UmbracoMembershipProvider" and changed it to be default membership provider:
Now I see the MemberTypes node in the backend and I can see the value of the custom "frame" property initially set in the login's user control via codebehind:
However, when logged in, the value returned from GetCurrentMember() call is still empty as indicated by the selfclosing xml node on the bottom of the code bellow:
Sooo...even more strange...even though I could see the value in the backend, but not in GetCurrentMember XSLT queries, once I entered the value once again in the backend and clicked the save icon manually, voila, magic it's there (even in XSLT)!!! :))) So, even though you can see it in the backend it doesn't mean GetCurrentMember() will see it in the frontend (XSLT) :P So this is my solution for now, I deleted all the members which were created prior to the changes in membershipprovider and added the code bellow (which I think is an overkill though) after setting the proprty as I did before to the MembershipProvider which now works:
Just as a recap...
So you shouldn't rename the custom MembershipProvider to anything else but the "UmbracoMembershipProvider"...just change the type value in web.config...that is enough. Make new umbraco members inside of the codebehind of your membership provider (please confirm Morten?!) and use Save() - though that might be an overkill. And don't use the asp:Login control's LoggedIn event, it doesn't work, well not as it name implies (since the User won't be set in the Context at the time it runs).
Will try this later today on the vanilla umbraco, hopefully it will all work (as it works on this staging install;), fingers crossed X
Thanks for endless patience Morten
Good to hear that it is working. The reason that the value didn't show up might be because the xml that the xslt get's is cached somewhere, and because of that, the newest value is not apperaing. So the Save() call might just be the thing that refreshes that cache, and repopulates the xml.
With regards to the name of the provider, in this case I think it is ok to use the same name. Umbraco's members section is dependant on it's own API, so it probably disables stuff when it is not the original provider. But since yours inherits from the original, I think it will be fine.
is working on a reply...