|
Hi Ray,
When I tested the providers I've noticed that the profile declaration varies depending on the type of web project that you use. If you use a web site project you can specify the properties directly in the web.config markup. However, in case of the web application project you will have to declare your own profile class (derived from ProfileBase) and inherit from it in the profile declaration within the web.config.
Have a look at the example above it uses MyProfile as profile class containing all the profile properties that you wish to use.
Later on in the code you can use the profile information in the following way:
MyProfile profile = (MyProfile) ProfileBase.Create(user.Identity.Name);
Cheers,
Michael
|
|
|
|
|
Hi Michael
I am testing your EF Providers and I think you did a GREAT job but I have a small problem with the Profiles..in the example cod there is no example of actually using the providers an I am new to the EF Framework usage. I have imp custom membership before but never worked with Profile provider before. Can you please explain a bit more how to imp custom profile properties in this scenario?
|
|
|
|
|
Hi,
I'm happy that you like my article.
Regarding the Profile provider, you have to implement your own class (MyProfile) in my example that derives from ProfileBase. This class only has the properties that you want to be part of your profile. Here an example of the test class that I used:
using System;
using System.Web.Profile;
namespace EFProvidersWebApplication
{
public class MyProfile : ProfileBase
{
public string FirstName
{
get { return base["FirstName"] as string; }
set { base["FirstName"] = value; }
}
public string LastName
{
get { return base["LastName"] as string; }
set { base["LastName"] = value; }
}
public int NumberOfVisits
{
get { return Convert.ToInt32(base["NumberOfVisits"]); }
set { base["NumberOfVisits"] = value; }
}
}
}
As you may have noticed, the MyProfile class is declared in the profile provider section of the web.config, in particular in the "inherits" attribute.
Than you can create/use the profile in your code behind in the following way:
MyProfile profile = (MyProfile) ProfileBase.Create(HttpContext.Current.User.Identity.Name);
profile.NumberOfVisits++;
profile.Save();
This obviously implies that you use membership provider which sets up the principal in your HttpContext and hence allows you to access the username of the logged on user.
Let me know if you need more information and don't forget to vote my article.
Cheers,
Michael
|
|
|
|
|
Hi Michael
I have not gotten to imp the Profile provider yet..still working on the Roles (see new message) I will NOT forget to vote on your article.
I have one question, Do I need to imp the profile values (the usual way) in web.config as well as in my class?
|
|
|
|
|
Hi,
As mentioned earlier in this thread, depending on your project type you can do it decleratively or by inheriting the profile class. If you choose your custom profile class no declerative property configuration is required.
Cheers,
M
|
|
|
|
|
Hi Michael
Thank you, I will try this during the weekend and get back to you
|
|
|
|
|
I opened it as a website in my VS.
it opens and show all the files in the site.
can you explain how to change the webconfige? didn't work for me
thanks
|
|
|
|
|
Hi. Thanks for creating this, Michael. I'm trying to get it to work. I'm calling Membership.ValidateUser() and got a Configuration Error:
Could not load file or assembly 'SmartSoft.EFProviders.Web, Version=1.0.0.0, Culture=neutral, PublicKeyToken=53fb08796b3f3bb2'
I took the EFProviders solution and created a new website project within it, called TestEFP. I set the web.config within that project for the EFMembershipProvider and referenced the SmartSoft.EFProviders.Web project from the website project.
I also tried rebuilding and got a dialog, "Import Key File," saying:
This project includes a password-encrypted key used for signing. Enter the password for the key file to import the key file into the local crypto-store database for use" ... "Key file: SmartSoft.pfx"
Can you help me get this working?
|
|
|
|
|
Hi Kevin,
You can ignore the error regarding the password protected key file. I suggest once you opened the solution, delete the key file and create your own key file (can be done in the project properties window).
Dont forget to update your public key after that in the web.config file since this will change with a new key file.
Cheers,
Michael
|
|
|
|
|
OK, thanks Michael!
Another question: If I'm implementing my own admin functionality (to edit users, etc), I don't need to use the methods in the Providers, do I? Is it okay to use the entities from EF directly? For example, get a User entity, update some fields, and call context.SaveChanges() .. without having to deal with a MembershipUser at all?
I'm using ASP.NET MVC. So the default login functionality works great. I'm also implementing functionality for admins to create/edit/delete other users. Based on the Apress ASP.NET MVC book (Steven Sanderson), I'm creating a repository as an interface to the entities - e.g. an AccountRepository, for Users, Roles, Profiles.
|
|
|
|
|
I noticed one thing. In EFMembershipProvider.UnlockUser(), it was setting LastLockOutDate to Now, but wasn't setting IsLockedOut to false. (so it wasn't unlocking the user)
|
|
|
|
|
Thanks for your efforts. Exactly what i needed.
http://deltabis.com/steven
|
|
|
|
|
Thanks!
|
|
|
|
|
Hi Michael,
On more question:
Did you ever implemented a profile provider that works with a Profile table with the traditional columns instead of the Property Names / Property Values?
My Entity Framework model contains a normal Profile SQL table and that is related with other tables and I would like to make the Profile Provider to access my Profile Repository and return a MyProfile object based on those tables.
Thanks,
Miguel
|
|
|
|
|
Hi Michael,
I am posting the SQL script, tested, where I added a few columns.
The Length of the columns are a little bit different than from the original.
Instead of using those 256, 128 lengths I tend to use 200, 100, ...
One thing I am not sure even from your code are the "On Delete No Action" on Users and Profiles table.
Probably it is correct ... Just wanting to confirm.
Here is my SQL Script:
<pre>
use Membership;
go
/* ------ { Tables } ------ */
-- Applications
create table dbo.Applications
(
Id uniqueidentifier rowguidcol not null constraint DF_Applications_Id default (newid()),
Description nvarchar(200) null,
[Name] nvarchar(100) not null,
constraint PK_Applications primary key clustered (id)
)
-- Profiles
create table dbo.Profiles
(
UserId uniqueidentifier rowguidcol not null constraint DF_Profiles_UserId default (newid()),
LastUpdatedDate datetime not null,
PropertyNames ntext null,
PropertyValuesBinary image null,
PropertyValuesString ntext null,
constraint PK_Profiles primary key clustered (UserId)
)
-- Roles
create table dbo.Roles
(
Id uniqueidentifier rowguidcol not null constraint DF_Roles_Id default (newid()),
ApplicationId uniqueidentifier not null,
Description nvarchar(200) not null,
[Name] nvarchar(100) not null,
constraint PK_Roles primary key clustered (id)
)
-- Users
create table dbo.Users
(
Id uniqueidentifier rowguidcol not null constraint DF_Users_Id default (newid()),
ApplicationId uniqueidentifier not null,
Comment nvarchar(200) null,
CreationDate datetime null,
Email nvarchar(200) not null,
FailedPasswordAnswerAttemptCount int null,
FailedPasswordAnswerAttemptWindowStart datetime null,
FailedPasswordAttemptCount int null,
FailedPasswordAttemptWindowStart datetime null,
IsAnonymous bit not null constraint DF_Users_IsAnonymous default (0),
IsApproved bit not null constraint DF_Users_IsApproved default (1),
IsLockedOut bit not null,
IsOnline bit null,
LastActivityDate datetime not null,
LastLockedOutDate datetime null,
LastLoginDate datetime null,
LastModified datetime null,
LastPasswordChangedDate datetime null,
[Name] nvarchar(100) null,
Password nvarchar(100) null,
PasswordAnswer nvarchar(200) null,
PasswordFormat int not null,
PasswordQuestion nvarchar(200) null,
PasswordSalt nvarchar(100) not null,
Username nvarchar(200) not null,
constraint PK_Users primary key clustered (id)
)
-- UsersRoles
create table dbo.UsersRoles
(
UserId uniqueidentifier not null,
RoleId uniqueidentifier not null,
constraint PK_UsersRoles primary key clustered (UserId, RoleId)
)
/* ------ { Constraints } ------ */
-- Roles
alter table dbo.Roles
add constraint FK_Roles_Applications foreign key (ApplicationId) references dbo.Applications(Id) on delete cascade on update cascade;
-- Users (NO CASCADE ON DELETE??)
alter table dbo.Users
add constraint FK_Users_Applications foreign key (ApplicationId) references dbo.Applications(Id) on delete no action on update no action;
-- UsersRoles
alter table dbo.UsersRoles
add constraint FK_UsersRoles_Roles foreign key(RoleId) references dbo.Roles(Id) on delete cascade on update cascade,
constraint FK_UsersRoles_Users foreign key(UserId) references dbo.Users(Id) on delete cascade on update cascade;
-- Profiles (NO CASCADE ON DELETE??)
alter table dbo.Profiles
add constraint FK_Profiles_Users foreign key(UserId) references dbo.Users(Id) on delete no action on update no action;
</pre>
Thanks,
Miguel
|
|
|
|
|
Hi,
Thank you for the posting. I didn't test it yet.
I will post here any problem I might find.
At the moment I could mention that the tables could be named: Users, Profiles, Roles, ... instead of User, Profile, Roles ...
Then you could add a note saying to rename the name of the Entities on the EF as usual.
And is there a FirstName and LastName on original ASP.NET Membership Users table?
Just wondering if you added any columns to the tables.
Thank You,
Miguel
|
|
|
|
|
Hi Miguel,
I guess the correct table names would be: Users, Roles, Profile if you directly want to relate to the SQL providers. However, the SQL providers split the user information into membership and users.
You are right, I've added the FirstName and LastName.
Cheers,
|
|
|
|
|
Hi Michael,
I have been going around your SQL code. I made a few changes (I didn't test it yet).
What is strange is that you don't have delete cascade on Users/Profiles and on Applications/Users.
If a User is deleted shouldn't its Profiles being deleted.
I am posting my SQL (It is cleaner. I recoded not using SQL Man. Studio)
Note that I didn't test it yet. I wanted to know your opinion about the cascade delete before.
create table dbo.Applications
(
Id uniqueidentifier rowguidcol not null constraint DF_Applications_Id default (newid()),
Description nvarchar(200) null,
[Name] nvarchar(100) not null,
constraint PK_Applications primary key clustered (id)
)
create table dbo.Profiles
(
UserId uniqueidentifier rowguidcol not null constraint DF_Profiles_UserId default (newid()),
LastUpdatedDate datetime not null,
PropertyNames ntext null,
PropertyValuesBinary image null,
PropertyValuesString ntext null,
constraint PK_Profiles primary key clustered (id)
)
create table dbo.Roles
(
Id uniqueidentifier rowguidcol not null constraint DF_Roles_Id default (newid()),
ApplicationId uniqueidentifier not null,
Description nvarchar(200) not null,
[Name] nvarchar(100) not null,
constraint PK_Roles primary key clustered (id)
)
create table dbo.Users
(
Id uniqueidentifier rowguidcol not null constraint DF_Users_Id default (newid()),
ApplicationId uniqueidentifier not null,
Comment nvarchar(200) null,
CreationDate datetime null,
Email nvarchar(100) not null,
FailedPasswordAnswerAttemptCount int null,
FailedPasswordAnswerAttemptWindowStart datetime null,
FailedPasswordAttemptCount int null,
FailedPasswordAttemptWindowStart datetime null,
IsAnonymous bit not null constraint DF_Users_IsAnonymous default (0),
IsApproved bit not null constraint DF_Users_IsApproved default (1),
IsLockedOut bit not null,
IsOnline bit null,
LastActivityDate datetime not null,
LastLockedOutDate datetime null,
LastLoginDate datetime null,
LastModified datetime null,
LastPasswordChangedDate datetime null,
[Name] nvarchar(100) null,
Password nvarchar(100) null,
PasswordAnswer nvarchar(200) null,
PasswordQuestion nvarchar(200) null,
Username nvarchar(50) not null,
constraint PK_Users primary key clustered (id)
)
create table dbo.UsersRoles
(
UserId uniqueidentifier not null,
RoleId uniqueidentifier not null,
constraint PK_UsersRoles primary key clustered (id)
)
And the restrictions:
alter table dbo.Roles
add constraint FK_Roles_Applications foreign key (ApplicationId) references dbo.Applications(Id) on delete cascade on update cascade;
alter table dbo.Users
add constraint FK_Users_Applications foreign key (ApplicationId) references dbo.Applications(Id) on delete no action on update no action;
alter table dbo.UsersRoles
add constraint FK_UsersRoles_Roles foreign key(RoleId) references dbo.Roles(Id) on update cascade on delete cascade;
constraint FK_UsersRoles_Users foreign key(UserId) references dbo.Users(Id) on update cascade on delete cascade;
alter table dbo.Profiles
add constraint FK_Profiles_Users foreign key(UserId) references dbo.Users(Id) on delete no action on update no action;
Thanks,
Miguel
|
|
|
|
|
And one more question:
Is there any reason why your removed the columns
PasswordSalt
PasswordFormat
MobileAlias
From the tables?
Thanks,
Miguel
|
|
|
|
|
Hi Miguel,
I removed the MobileAlias because as far as I could see it is nowhere used. In what table did you find the PasswordSalt and PasswordFormat columns?
Cheers
Michael
|
|
|
|
|
Hi Michael,
I found out that Mobile Alias is an Orphan in ASP.NET 2.0. It was originally placed in the table on early development of ASP.NET 2.0 where mobile clients were to be considered.
PasswordSalt and PasswordFormat are in Membership table just after Password column.
Check the table on the bottom:
http://msdn.microsoft.com/en-us/library/aa478949.aspx
It contains the columns of Membership table.
I am confirming the other tables to.
In Roles you are missing one: Description.
I am not saying this is necessary, but it would be a good idea to keep the same columns when possible just in case.
I have my SQL code working. I will post it here.
Thanks,
Miguel
|
|
|
|
|
Hi Michael,
I am posting the SQL code, tested, where I added a few columns.
The Length of the columns are a little bit different than from the original.
Instead of using those 256, 128 lengths I tend to use 200, 100, ...
One thing I am not sure even from your code are the "On Delete No Action" on Users and Profiles table.
Probably it is correct ... Just wanting to confirm.
Here is my SQL Script:
use Membership;
go
-- Applications
create table dbo.Applications
(
Id uniqueidentifier rowguidcol not null constraint DF_Applications_Id default (newid()),
Description nvarchar(200) null,
[Name] nvarchar(100) not null,
constraint PK_Applications primary key clustered (id)
)
-- Profiles
create table dbo.Profiles
(
UserId uniqueidentifier rowguidcol not null constraint DF_Profiles_UserId default (newid()),
LastUpdatedDate datetime not null,
PropertyNames ntext null,
PropertyValuesBinary image null,
PropertyValuesString ntext null,
constraint PK_Profiles primary key clustered (UserId)
)
-- Roles
create table dbo.Roles
(
Id uniqueidentifier rowguidcol not null constraint DF_Roles_Id default (newid()),
ApplicationId uniqueidentifier not null,
Description nvarchar(200) not null,
[Name] nvarchar(100) not null,
constraint PK_Roles primary key clustered (id)
)
-- Users
create table dbo.Users
(
Id uniqueidentifier rowguidcol not null constraint DF_Users_Id default (newid()),
ApplicationId uniqueidentifier not null,
Comment nvarchar(200) null,
CreationDate datetime null,
Email nvarchar(200) not null,
FailedPasswordAnswerAttemptCount int null,
FailedPasswordAnswerAttemptWindowStart datetime null,
FailedPasswordAttemptCount int null,
FailedPasswordAttemptWindowStart datetime null,
IsAnonymous bit not null constraint DF_Users_IsAnonymous default (0),
IsApproved bit not null constraint DF_Users_IsApproved default (1),
IsLockedOut bit not null,
IsOnline bit null,
LastActivityDate datetime not null,
LastLockedOutDate datetime null,
LastLoginDate datetime null,
LastModified datetime null,
LastPasswordChangedDate datetime null,
[Name] nvarchar(100) null,
Password nvarchar(100) null,
PasswordAnswer nvarchar(200) null,
PasswordFormat int not null,
PasswordQuestion nvarchar(200) null,
PasswordSalt nvarchar(100) not null,
Username nvarchar(200) not null,
constraint PK_Users primary key clustered (id)
)
-- UsersRoles
create table dbo.UsersRoles
(
UserId uniqueidentifier not null,
RoleId uniqueidentifier not null,
constraint PK_UsersRoles primary key clustered (UserId, RoleId)
)
-- Roles
alter table dbo.Roles
add constraint FK_Roles_Applications foreign key (ApplicationId) references dbo.Applications(Id) on delete cascade on update cascade;
-- Users (NO CASCADE ON DELETE??)
alter table dbo.Users
add constraint FK_Users_Applications foreign key (ApplicationId) references dbo.Applications(Id) on delete no action on update no action;
-- UsersRoles
alter table dbo.UsersRoles
add constraint FK_UsersRoles_Roles foreign key(RoleId) references dbo.Roles(Id) on delete cascade on update cascade,
constraint FK_UsersRoles_Users foreign key(UserId) references dbo.Users(Id) on delete cascade on update cascade;
-- Profiles (NO CASCADE ON DELETE??)
alter table dbo.Profiles
add constraint FK_Profiles_Users foreign key(UserId) references dbo.Users(Id) on delete no action on update no action;
Thanks,
Miguel
|
|
|
|
|
|
Thanks!
|
|
|
|
|