I've read the excellent article by Aaron about using a custom ProfileProvider. This is all good and well and works as advertised.
However, I am trying to fill the properties during the registration and it is not working. When I save the user, the custom profile fields get set properly, using the custom class MemberProfile, like in Aaron's example.
I then save the profile, but when I go into the Umbraco backoffice, I don't see the property being filled.
using System;
using System.Web.UI.WebControls;
namespace Omega.Membership
{
public partial class MemberRegister : System.Web.UI.UserControl
{
protected void CreatedUser(Object sender, EventArgs e)
{
TextBox username = (TextBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("username");
TextBox lastname = (TextBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("lastname");
var profile = ((MemberProfile) Context.Profile);
profile.Initialize(username.Text, true);
profile.LastName = lastname.Text;
(Context.Profile).Save();
}
}
}
It seems that the .Save(); does not save the profile values to Umbraco. I can see in my watch that the "profile" has a "lastname" property that is actually filled.
When I do fill the "lastname" in the Umbraco backoffice and do something like this, the lastname doesn't show up either:
using System;
using System.Web.UI.WebControls;
namespace Omega.Membership
{
public partial class MemberRegister : System.Web.UI.UserControl
{
protected void Page_Load(Object sender, EventArgs e)
{
var profile = ((MemberProfile)Context.Profile);
profile.Initialize("test22", true);
Response.Write(profile.LastName);
}
}
}
As a temporary work around I'm overriding the Save() method of the ProfileBase class.
Something like this, this is proof of concept code (not production).
using System;
using System.Web.Profile;
using umbraco.cms.businesslogic.member;
namespace cogworks.incisive.providers
{
public class MemberProfile : ProfileBase
{
public override void Save()
{
base.Save();
var members = Member.GetMemberByName(UserName,false);
var member = members[0];
member.getProperty("favouriteColour").Value = FavouriteColour;
member.Save();
}
[SettingsAllowAnonymous(false)]
public string FavouriteColour
{
get
{
var propertyValue = GetPropertyValue("favouriteColour");
return propertyValue == DBNull.Value ? "" : (string) propertyValue;
}
set
{
SetPropertyValue("favouriteColour", value);
}
}
}
}
@Tim well yeah, but that defeats the whole purpose. I have since had to stop working on membership to implement some higher priority features, but will get back to this problem next week.
It seems that I'll have to go the API route like you did here, but ditch the profile provider completely as well. Shame, I wish I knew more about this subject so I could create a working implementation and share it.
I'd assume that you've got your web.config set up as I described it in the post? I'm not overly sure that you need to call the Save method, the setter for the profile properties should invoke the saving against the Member in the Umbraco database.
If someone's got a sample app which I can play with I'm happy to have a step through the full source tree and see I can work out whether it's a core bug or not.
Yeah I think that's contributing to the problem Tim. The properties element defines how the Umbraco aliases are mapped, and which provider they are mapped to (since you can have properties coming from different providers).
It could be that since that's not defined it doesn't know how to save the data.
I've fixed the This profile property has already been defined error (I'd set the property to the name of the property in the MemberProfile class rather than the name of the property - oops!)
However I discovered another issue which again may be related to my implementation.
Basically whether then property saves or not seems to depend on how it is called.
var memberProfile = ProfileBase.Create("test");
memberProfile.FavouriteColour = "Yellow";
However by adding an invocation of the Save() method in the set method of the property the example above can be also made to save see below: (This saves whichever way it is instantiated)
using System;
using System.Web.Profile;
using System.Web.Security;
using umbraco.cms.businesslogic.member;
namespace cogworks.providers
{
public class MemberProfile : ProfileBase
{
[SettingsAllowAnonymous(false)]
public string FavouriteColour
{
get
{
var propertyValue = GetPropertyValue("favourite_colour");
return propertyValue == DBNull.Value ? "" : (string) propertyValue;
}
set
{
SetPropertyValue("favourite_colour", value);
Save();
}
}
}
}
So for now I'm just adding Save(); alls to my profile properties.
If your data source is a database and you do multiple changes to a profile at the same time you might want to consider calling Save() from where you are doing the editing (such as a profile page) instead.
Save() checks all properties to see if they're changed and then saves the to the database. If you are changing ten properties you will perform ten checks, and more important, ten individual updates to the database...
Using ProfileProvider during registration
I've read the excellent article by Aaron about using a custom ProfileProvider. This is all good and well and works as advertised.
However, I am trying to fill the properties during the registration and it is not working. When I save the user, the custom profile fields get set properly, using the custom class MemberProfile, like in Aaron's example.
I then save the profile, but when I go into the Umbraco backoffice, I don't see the property being filled.
This is what I have so far.
MemberRegister.ascx
MemberRegister.ascx.cs:
using System; using System.Web.UI.WebControls; namespace Omega.Membership { public partial class MemberRegister : System.Web.UI.UserControl { protected void CreatedUser(Object sender, EventArgs e) { TextBox username = (TextBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("username"); TextBox lastname = (TextBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("lastname"); var profile = ((MemberProfile) Context.Profile); profile.Initialize(username.Text, true); profile.LastName = lastname.Text; (Context.Profile).Save(); } } }
It seems that the .Save(); does not save the profile values to Umbraco. I can see in my watch that the "profile" has a "lastname" property that is actually filled.
When I do fill the "lastname" in the Umbraco backoffice and do something like this, the lastname doesn't show up either:
using System; using System.Web.UI.WebControls; namespace Omega.Membership { public partial class MemberRegister : System.Web.UI.UserControl { protected void Page_Load(Object sender, EventArgs e) { var profile = ((MemberProfile)Context.Profile); profile.Initialize("test22", true); Response.Write(profile.LastName); } } }
I must be missing something obvious..?
Did you find any joy with this as I am also experiencing the same problem?
Tim
As a temporary work around I'm overriding the Save() method of the ProfileBase class.
Something like this, this is proof of concept code (not production).
Tim
@Tim well yeah, but that defeats the whole purpose. I have since had to stop working on membership to implement some higher priority features, but will get back to this problem next week.
It seems that I'll have to go the API route like you did here, but ditch the profile provider completely as well. Shame, I wish I knew more about this subject so I could create a working implementation and share it.
Thanks for your reply though!
I'd assume that you've got your web.config set up as I described it in the post? I'm not overly sure that you need to call the Save method, the setter for the profile properties should invoke the saving against the Member in the Umbraco database.
If someone's got a sample app which I can play with I'm happy to have a step through the full source tree and see I can work out whether it's a core bug or not.
Hi Slace,
My web.config is not exactly as you have specified.
I do not have the <properties> element, when this is present I get the following error: "This profile property has already been defined"
Removing the <properties> element seems to fix this, but of course this may be the problem...
Tim
Yeah I think that's contributing to the problem Tim. The properties element defines how the Umbraco aliases are mapped, and which provider they are mapped to (since you can have properties coming from different providers).
It could be that since that's not defined it doesn't know how to save the data.
OK,
I've fixed the This profile property has already been defined error (I'd set the property to the name of the property in the MemberProfile class rather than the name of the property - oops!)
However I discovered another issue which again may be related to my implementation.
Basically whether then property saves or not seems to depend on how it is called.
Example 1 (this saves correctly):
Example 2 (this does not save correctly):
However by adding an invocation of the Save() method in the set method of the property the example above can be also made to save see below: (This saves whichever way it is instantiated)
So for now I'm just adding Save(); alls to my profile properties.
Tim
If your data source is a database and you do multiple changes to a profile at the same time you might want to consider calling Save() from where you are doing the editing (such as a profile page) instead.
Save() checks all properties to see if they're changed and then saves the to the database. If you are changing ten properties you will perform ten checks, and more important, ten individual updates to the database...
Quite correct Emil.
A very sensible solution. Although if I set it like this:
It will do the DB updates individually anyway....
T
is working on a reply...