How to combine using Membership API with own application related data? - asp.net

Designing a new application in asp.net 4 I have to make a decision how to use a MS SQL Membership API along with my own data in the MS SQL data base. Firstly I need to store and access user profile data in more flexible manner then the Profile provider supports. Secondly I would like to link other user related information (e.g. Orders).
No matter where you store your aspnetdb tables (in the separate data base or in the same data base with your data), the problem stays how to keep your data synchronized.
After a research I see the following relevant options:
1. Foreign key UserId from asp_Users (suggested in this tutorial).
2. No foreign key - use transactions (suggested here).
3. No foreign key - use customized AccountController (whatever it is, suggested here).
4. Additional table which links Membership UserId (uid) with custom UserId (int).
5. ...
On the one hand I like the first solution as it is quite straightforward and is suggested in an official asp.net tutorial.
On the other hand opponents note quite reasonably that using foreign keys breaks the general idea of providers which are supposed to help separating concerns and to be interchangeable. But unfortunately they do not go much into implementation details so it is not really easy to estimate those suggestions in terms of relevance and ease of implementation.
So what is the best option to approach this? Furthermore how would the implementation look like? Would it be enough to use just additional ADO.NET or LINQ etc code or is it worth implementing a custom Membership and/or Profile Provider?
Thank you in advance.

The first is the simpliest approach. Add the GUID of the user as a foreignkey in the related tables (f.e. Ordered_by). I don't see where it breaks separating concerns. If you want to keep the order-record in database, you also have to keep the user who has ordered, that makes perfectly sense.
I have used option 4 successfully in my current application. I've created a table aspnet_UserID with idUser int as primary-key and fiUser(the GUID of the aspnet_Users) as foreign-key. Here is the model:
(Note: User is the standard aspnet_Users table created via aspnet_regsql.exe and aspnet_UserId is my custom table that maps every Guid with my int-ID)
Now i'm storing only my idUser as FK in all related tables (like in your Order-Table). That has the advantage of less storage and more readable UserID's(i could never remember a GUID). Maybe it's somewhat more separated with this "wrapper-table" but that was not my main intention.
You can change the delete-rule on your foreignkeys if you want to control the behavior. Set it to Cascade if you f.e. want to delete all orders that were ordered by the user you're deleting or set it to no Action if you want to keep this order.
I can't suggest any alternatives for the Profile question because you haven't mentioned what you mean with "need to store and access user profile data in more flexible manner then the Profile provider supports".

You should consider writing your own custom membership provider that uses the tables/data as per your need (instead of using ASP.NET provided schema).
See this MSDn sample (schema, code) for writing a custom provider - this sample uses OLEDB to access database. Yet another sample is here - it uses active directory as a store.

Related

ASP.Net membership provider

I have a couple of questions regarding Membership Provider. My textbook got me started but I still need more information.
I am using Linq to Entities, does it make sense to also create LINQ entity relationships with my membership provider DB?
I would like to add additional user attributes other than provided in the membership provider. Can I add them to the aspnet.USER table without any issues?
My users will join the website and will gain privildges as they participate, much like Stack Overflow. I want to keep track of their postings by adding a field to the user table to manage that function.
Thanks in advance!
There are two ways to associate additional information with user accounts when using the Membership model. The first - which affords the greatest flexibility, but requires the most upfront effort - is to create a custom data store for this information. If you are using the SqlMembershipProvider, this would mean creating an additional database table that had as a primary key the UserId value from the aspnet_Users table and columns for each of the additional user properties. In the online messageboard example, the table might be called forums_UserProfile and have columns like UserId (a primary key and a foreign key back to aspnet_Users.UserId), HomepageUrl, Signature, and IMAddress.
Rather than using custom data stores, the ASP.NET Profile system can
be used to store user-specific information. The Profile system allows
the page developer to define the properties she wants to associate
with each user. Once defined, the developer can programmatically read
from and assign values to these properties. The Profile system
accesses or writes the property values to a backing store as needed.
Like Membership and Roles, the Profile system is based on the provider
model, and the particular Profile provider is responsible for
serializing and deserializing the property values to some data store.
The .NET Framework ships with a SqlProfileProvider class by default,
which uses a SQL Server database table (aspnet_Profile) as its backing
store.
Examining ASP.NET's Membership, Roles, and Profile - Part 6
By Scott Mitchell
This should get you started. I guess I could answer your questions as follow:
It shouldn't be necessary. Explore the membership API, everything you ever wanted is... probably in there.
Read the article and decide what's best.
Good luck, :).
Sincerely,
Maxime

ASP.NET Dynamic Data: Access rights only to specific rows

I want to use ASP.NET Dynamic Data for my next project, but there is a problem a can't manage to solve. In the database we manage authorization on a per-row basis. For example no user is permitted to see all rows of the Contracts table. So there is a Many to Many Relationship between Contracts and Users. So everytime Dynamic Data performs a Select to show all Contracts it has to look into the ContractUsers junction table to see what contracts the current user is permitted to see (filtered by UserID which will be stored in a session variable). Of course these junction tables should be invisible to the users.
By default Dynamic Data returns all rows of a table, so is it possible to customize this behaviour for every query the user performs?
I want to use Dynamic Data together with LINQ to SQL but if this task would much easier to accomplish using Entity Framework I would look into that too.
Thanks for your help and time.
Implementing such a solution in Dynamic Data it will probably require the creation of a custom Entity Template; not really easy but once done it will not require the creation of custom pages just the editing of the page templates.
I think it will be really usefull to check the excellent work on DD done by S.J.Naughton and presented on his blog.
Greetings, F.
You should not use dynamic data because you need full control over querying and manually write all linq queries to add your data level security. If you still insist on dynamic data be aware that you will still write most of pages yourselves and you will only use dynamic templates. You will have to manually define ever data source and correctly pass where condition to filter results based on logged user.
In addition linq-to-sql is not able to hide junction table and entity framework is able to do that only if junction table contains just two FKs for many-to-many relation. If this table contains any other column you want to use in the application you will have to map it as any other entity and dynamic data will show it as an entity.
Dynamic data are technology for quick creation of simple application where you need to provide access to database through web interface but what you describe is not a simple scenario. You need per record authorization which can differ among entity types.

ASP.NET Membership - A design for tracking additional information

I'm working on an ASP.NET4.0/C# application for a public site that needs to authenticate only the employees that work at the associated business. The idea is for the site to have a CMS such that employees can go in and make changes to certain content without having to work with any html.
My question relates to the design and use of a ASP.NET membership provider. I'm not trying to make the site work with an existing database, so there's no need to create my own MembershipProvider for that purpose. However, since each user is an employee, I want to track additional information such as name and office number. I can think of two readily apparent ways to accomplish this:
Use the default SqlMembershipProvider class. As a result, I would need to add the appropriate tables to my database and create a separate table for any "additional" information I want to store. This effectively creates a vertical partition on the user table, since I would use the asp.net-assigned userID as the primary key of the employee table as well. To retrieve the "additional" information, I could ask the provider for information about the current user and requery the database in the event I want to know anything else.
Create one table for all employee information (including login and password) and create my own custom MembershipProvider and MembershipUser classes with the functionality I desire.
I've also considered the use of profiles to store such information, however, the site will publicly contain employee listings, and these pages will need to access some of this information. As a result, I should probably cache this data and it seems like using the serialized fields that profiles provide would cause a problem.
Thus, purely in regards to design... would it be best to make a distinction between a user and an employee and use the default SqlMembershipProvider and associated tables, or write my own user tables that store the information I need and my own MembershipProvider for accessing that information?
If I understand your question correctly, you'd like to store additional user info within the ASP.NET Membership. I've created a number of sites using the following setup.
Install the default .NET Membership using the aspnet_regsql.exe tool
Create a UserProfile table with a uniqueidentifier (PK) UserID column that is linked via a foreign key to the aspnet_Users table
To access that information, all you need is the UserId of a particular User, then you can query your custom table for more information.
Microsoft has written an excellent post on how to do this.
Good luck!
M
I am doing something similar, using your option 1. Works great for me.
My business logic has some functions for mutating users. It knows when to touch my users table or the Membership functionality.
Using a custom MembershipProvider for this sort of thing will give you more work than you bargained for.
SQL Table profile provider (http://weblogs.asp.net/scottgu/archive/2006/01/10/435038.aspx ) will help you do just that.
You will get the power of the Profiles and on the same time not worry about caching or serialization since this provider stores the profile information in clear database table without any serialization. You can use them directly in your queries.

Use ASP.NET Profile or not?

I need to store a few attributes of an authenticated user (I am using Membership API) and I need to make a choice between using Profiles or adding a new table with UserId as the PK. It appears that using Profiles is quick and needs less work upfront. However, I see the following downsides:
The profile values are squished into a single ntext column. At some point in the future, I will have SQL scripts that may update user's attributes. Querying a ntext column and trying to update a value sounds a little buggy to me.
If I choose to add a new user specific property and would like to assign a default for all the existing users, would it be possible?
My first impression has been that using profiles may cause maintainance headaches in the long run. Thoughts?
There was an article on MSDN (now on ASP.NET http://www.asp.net/downloads/sandbox/table-profile-provider-samples) that discusses how to make a Profile Table Provider. The idea is to store the Profile data in a table versus a row, making it easier to query with just SQL.
More onto that point, SQL Server 2005/2008 provides support for getting data via services and CLR code. You could conceivably access the Profile data via the API instead of the underlying tables directly.
As to point #2, you can set defaults to properties, and while this will not update other profiles immediately, the profile would be updated when next it is accessed.
Seems to me you have answered your own question. If your point 1 is likely to happen, then a SQL table is the only sensible option.
Check out this question...
ASP.NET built in user profile vs. old stile user class/tables
The first hint that the built-in profiles are badly designed is their use of delimited data in a relational database. There are a few cases that delimited data in a RDBMS makes sense, but this is definitely not one of them.
Unless you have a specific reason to use ASP.Net Profiles, I'd suggest you go with the separate tables instead.

Relationship Between ASPNET Membership Provider Tables and Custom Membership Tables

I went through a custom profile provider example a while ago and I am
now revisiting it.
My database has all the dbo.aspnet_* tables created when I ran the aspnet registration
wizard. In these tables I have aspnet_Profile which has a FK constraint pointing to aspnet_Users.
I also have two tables in MyDB: The first, dbo.ProfileData, has a foreign key constraint
pointing to dbo.Profile.
What I want to understand is how the tables in MyDB relate to
those in dbo.aspnet_*. Shouldn't there be a foreign key constraint (or some kind of
relationship) between the profile tables in MyDB and the aspnet tables? Some discussion
of how my custom tables relate to those provided by aspnet would be wonderful.
Thanks in advance.
There are two options I can see, both of which will yield basically the same result:
FK from dbo.aspnet_User.UserID to dbo.Profile.UserID, then define a unique key on dbo.Profile.UserID (unless you use it as the PK column for dbo.Profile)
FK from dbo.aspnet_Profile.ProfileID to dbo.Profile.ProfileID
dbo.aspnet_User is logically 1 - 1 with dbo.aspnet_Profile, so it doesn't really matter which approach you use as you will still get the same relational integrity.
If you are replacing the standard profile data table with your own implementation then it makes more sense to use the first suggestion, otherwise if you are extending the Profile schema then use the second suggestion.
EDIT
aspnet_Profile is the standard table - the standard SqlProfileProvider stores the user's profile data as a serialized property bag in aspnet_Profile, hence why there is no separate aspnet_ProfileData table as well.
This approach allows the profile schema to be customized easily for different applications without requiring any changes to the underlying database, and is the most optimal solution for a framework such as .NET. The drawback is that SQL Server does not have easy access to this data at all, so it is much more difficult to index, update and query the user's profile data using T-SQL and set-based logic.
The most common approach I have seen to remove this limitation is to extend the standard SqlProfileProvider to write to a custom profile data table which has specific columns for application-specific profile properties. This table naturally has a 1-1 relationship with the aspnet_Profile table, so it has a foreign key as indicated above.
The role of the extended provider is to promote specific profile properties to columns during profile writes, and read in the columns when the profile is retrieved.
This allows you to mix-and-match storage solutions on an as-needs basis, as long as your extended provider knows how to fall back to the standard implementation where it does not 'know' about a given property.
I always think it is best to leave the standard membership tables as-is, and extend where necessary using new tables with appropriate foreign keys, then subclass the appropriate provider and override the provider methods with your own implementation (calling into the base implementation wherever possible).

Resources