Extending a member profile with two further layers - asp.net mvc - asp.net-mvc

I have a modeling question related to profiles. Firstly, I have looked into using the SQLTableProvider and using the in built profiling system but didn't feel they were suitable. So, with that said, I have a membership scheme where every person has a profile, then that person can upgrade their profile to either an individual (additional fields) or a company account (additional fields again).
So I thought, use a Profile base class and then inherit from that for the Company account and Individual account. However, when it comes to implementing this in MVC I'm hitting a brick wall.
Since either the company or individual edit pages are effectively updating both the base Profile table and also the individual/company tables from the same page. How would I go about implementing this within the model (which is currently generated via LinqToSQL) and also at the view level?
Apologies if that wasn't very clear, tricky one to explain!

If you are using Linq to SQL, then you already have a model. Linq generates the entities and collections based on your database for you. The generated model is a shallow one, but is pretty solid and workable. The Linq to SQL model can be extended via partial classes allowing you to enhance entities or the context itself for additional functionality.
The controller can work directly against the generated model and pass entities or collections of entities to the view as needed.
I would suggest that, for what you appear to be trying to do, you might consider not using the built-in profile provider system at all. The profile providers in asp.net work well for simple personalization stuff, but it doesn't work well for concrete data like contact info and such. Also keep in mind that the profile provider systems tend to store object data as serialized strings in the database... this makes getting at profile data very difficult from admin tools and such. Performance starts to become a problem VERY fast in any case where you are needing multiple user's profile information (such as with an admin user editor).
For a when you are storing important personal details like the stuff you mentioned, what you are really storing are "account details" not "user profiles". You can extend a membership provider to expose your additional details, but I've generally found it much easier to just roll my own data model and access logic to deal with the additional account information.
My rule of thumb is this: if the information is ONLY needed during a request made by the user to whome the data belongs, then it goes in profiles. If I would need the data for one user to be read during another user's request, or if I would need a "list" of that data for different users, then it doesn't go in asp.net profiles.

Do you mean settings like choosing how many items to view on each page, and choosing some style sheet?
public class Profile
{
int? ItemsPerPage { get; set; }
string PreferredStyleSheet { get; set; }
}
The company selects some values that will work for users unless the users have chosen some other values for themselves. Is that what you have in mind?
In that case: I don't know how to do it together in ASP.NET Profile, but how about the following tables in the database:
TABLE Setting
(
SettingID int NOT NULL,
SettingName varchar(32) NOT NULL,
DefaultValue nvarchar(128) NULL
)
TABLE CompanySetting
(
CompanySettingID int NOT NULL,
RefSettingID int NOT NULL,
RefCompanyID int NOT NULL,
SettingValue nvarchar(128) NOT NULL
)
TABLE UserSetting
(
UserSettingID int NOT NULL,
RefSettingID int NOT NULL,
RefUserId uniqueidentifier NOT NULL,
SettingValue nvarchar(128) NOT NULL
)
And then make some joins for the present user. If the user setting is not given, take the company setting; if the company setting is not given, take the default value.

Related

Identity 2.0. How to relate a user table in my EF context to Identity AspNetUsers table

I am using a boiler-plate VS2013 generated project (Code First, Migrations).
I wish to take the easy route and use all the built-in Identity API for handling of authentication and accounts (register, login all that).
Yet I wish to have a separate user table (let’s call it AppUser) with its own attributes that is not part of Identity because I am implementing my own domain with other relationships (Company => user hierarchy, Documents, etc) this is all admin’d outside of Identity by my custom pages. The AspNetUser would have already registered his account prior to my custom pages wiring him in.
My issue is how do I setup a relationship in the context from AppUser to AspNetUsers.
I thought this would be pretty simple but I am lost.
The only thing I can come up with is to have AppUser have a string called AspNetUser_ID that I would manually join to the AspNetUser table.
This seems pretty brittle and I would prefer it could have a FK constraint.
The other thing I cannot figure out is how to get AspNetUser in my DBContext so it is accessible.
Any help would be great.
Since you're using the boilerplate template, you should be able to find a class file named IdentityModels.cs in the Models folder. There, you can find the ApplicationUser class, to which you can add all the extra properties you want, as with any other Code First entity. This is the entity that maps to the AspNetUsers table. Here you could just add your AppUser class as a navigation property, or maybe, to keep things simple, add the properties from AppUser to ApplicationUser, so you only have one ***User entity to deal with.

MVC Membership change UserId Value

Using MVC when registering a new user a record gets created in webpages_Membership and UserProfile
The UserId by default gets created as sequential number 1, 2, 3...
my model
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
}
When I go to edit the record in the URL it shows /profile/1
I want to change the id's value to something random e.g. profile/f8934hre987f8987f9f8 for security reasons.
Same thing I want to generate random number when details gets viewed by members so instead
/details/1 want it to be /details/783787483743874873
The ViewModel for displaying the details contains Id field as a primary key which is also gets generated sequentially.
I read using [GUID] is not great for performance.
Advice how to change it without affecting the performance? Suggestions. Thank you.
EDIT
Have similar like groupon site, when user attempts to edit his/her profile instead of showing /edit/1 have something like:
So user doesnt know how many records in the database or what record number the user is.
I am not 100% sure what you mean by something random. I am assuming that you mean encryption. Please take a look at this MSDN link for the details on encryption.
After that ,you can have your action method like /detail/{encrypteduserId}
Then you can have action method like below
public class Detail(string id)
{
var decryptedUserId = GetDecryptedId(id);
// GetDecryptedId gives the decrypted information.
// You can implement it based on the MSDN link
// You can use decryptedUserId to run queries on the database.
}
This way you can achieve your goals without making schema changes. This seems like a minimum possible friction approach.
There is no security benefit to having a random user id, so long as your site implements proper controlled access. That is, nobody should be able to access /profile/1 except the user with a user id of 1 (or another user who is authorized to do so, such as an administrator). All other users should get an error.
An even better approach is to not use an id at all. Simply get the current users ID and show the profile of the currently logged in user. Then user with userid 1 just goes to /profile and they see their profile, and user with an id of 2 goes to /profile and they see their profile and there is no way for one user to see the others.
That's not always possible however, for instance in maintenance screens where an admin is viewing other users profiles, but in that case only the authorized admin should be able to do that.
Obscuring the userid is a false sense of security, since the id will be visible anyways. You are simply fooling yourself if you think this adds any security value, unless you haven't implement proper security in the first place, in which case it's just hiding your real problem.
It also adds needless complexity, and confusion. It's equivalent to saying "I want to change the address of my house to a random number for security reasons". Think of all the problems that would cause, for dubious results.
Having the User ID displayed in the URL is a genuine security concern, be it a simple integer user id or some GUID (if that GUID can be used to identify a user). This is especially true in cases of Transport layer security (HTTPS) where the URL is not encrypted like the content is.
Here are a couple of ways I can think of going around this:-
1.) As suggested by Erik above, use User.Identity.Name to identify the currently logged in user. This wouldn't however work for the administrator accessing another member's profile. It would also not work for unauthenticated scenarios.
2.) Instead of creating a direct hyperlink, create a form which posts the user id as part of a custom type (model). Then use model binding to access the User ID as a property of the custom model object in the Action method. In this case, the user ID is submitted as part of the form and hence is transported over the wire encrypted (if HTTPS) and not visible in the URL. This would work in both cases where a member is trying to access his/her own profile, or when an administrator chooses a profile to access on screen.
An example of scenario 2::
public ActionResult EditProfile(UserProfile userProfile)
{
bool success = false;
if (User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
if (WebSecurity.UserExists(userProfile.UserName))
{
// your code to update profile here.
}
}
}
if (success)
{
ViewBag.Message = "Profile updated successfully.";
}
else
{
ViewBag.Message = "Profile not updated:";
}
return View();
}

MVC and NOSQL: Saving View Models directly to MongoDB?

I understand that the "proper" structure for separation-of-concerns in MVC is to have view-models for your structuring your views and separate data-models for persisting in your chosen repository. I started experimenting with MongoDB and I'm starting to think that this may not apply when using a schema-less, NO-SQL style database. I wanted to present this scenario to the stackoverflow community and see what everyone's thoughts are. I'm new to MVC, so this made sense to me, but maybe I am overlooking something...
Here is my example for this discussion: When a user wants to edit their profile, they would go to the UserEdit view, which uses the UserEdit model below.
public class UserEditModel
{
public string Username
{
get { return Info.Username; }
set { Info.Username = value; }
}
[Required]
[MembershipPassword]
[DataType(DataType.Password)]
public string Password { get; set; }
[DataType(DataType.Password)]
[DisplayName("Confirm Password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
[Required]
[Email]
public string Email { get; set; }
public UserInfo Info { get; set; }
public Dictionary<string, bool> Roles { get; set; }
}
public class UserInfo : IRepoData
{
[ScaffoldColumn(false)]
public Guid _id { get; set; }
[ScaffoldColumn(false)]
public DateTime Timestamp { get; set; }
[Required]
[DisplayName("Username")]
[ScaffoldColumn(false)]
public string Username { get; set; }
[Required]
[DisplayName("First Name")]
public string FirstName { get; set; }
[Required]
[DisplayName("Last Name")]
public string LastName { get; set; }
[ScaffoldColumn(false)]
public string Theme { get; set; }
[ScaffoldColumn(false)]
public bool IsADUser { get; set; }
}
Notice that the UserEditModel class contains an instance of UserInfo that inherits from IRepoData? UserInfo is what gets saved to the database. I have a generic repository class that accepts any object that inherits form IRepoData and saves it; so I just call Repository.Save(myUserInfo) and its's done. IRepoData defines the _id (MongoDB naming convention) and a Timestamp, so the repository can upsert based on _id and check for conflicts based on the Timestamp, and whatever other properties the object has just get saved to MongoDB. The view, for the most part, just needs to use #Html.EditorFor and we are good to go! Basically, anything that just the view needs goes into the base-model, anything that only the repository needs just gets the [ScaffoldColumn(false)] annotation, and everything else is common between the two. (BTW - the username, password, roles, and email get saved to .NET providers, so that is why they are not in the UserInfo object.)
The big advantages of this scenario are two-fold...
I can use less code, which is therefore more easily understood, faster to develop, and more maintainable (in my opinion).
I can re-factor in seconds... If I need to add a second email address, I just add it to the UserInfo object - it gets added to the view and saved to the repository just by adding one property to the object. Because I am using MongoDB, I don't need to alter my db schema or mess with any existing data.
Given this setup, is there a need to make separate models for storing data? What do you all think the disadvantages of this approach are? I realize that the obvious answers are standards and separation-of-concerns, but are there any real world examples can you think of that would demonstrate some of the headaches this would cause?
Its also worth noting that I'm working on a team of two developers total, so it's easy to look at the benefits and overlook bending some standards. Do you think working on a smaller team makes a difference in that regard?
The advantages of view models in MVC exist regardless of database system used (hell even if you don't use one). In simple CRUD situations, your business model entities will very closely mimick what you show in the views, but in anything more than basic CRUD this will not be the case.
One of the big things are business logic / data integrity concerns with using the same class for data modeling/persistence as what you use in views. Take the situation where you have a DateTime DateAdded property in your user class, to denote when a user was added. If you provide an form that hooks straight into your UserInfo class you end up with an action handler that looks like:
[HttpPost]
public ActionResult Edit(UserInfo model) { }
Most likely you don't want the user to be able to change when they were added to the system, so your first thought is to not provide a field in the form.
However, you can't rely on that for two reasons. First is that the value for DateAdded will be the same as what you would get if you did a new DateTime() or it will be null ( either way will be incorrect for this user).
The second issue with this is that users can spoof this in the form request and add &DateAdded=<whatever date> to the POST data, and now your application will change the DateAdded field in the DB to whatever the user entered.
This is by design, as MVC's model binding mechanism looks at the data sent via POST and tries to automatically connect them with any available properties in the model. It has no way to know that a property that was sent over wasn't in the originating form, and thus it will still bind it to that property.
ViewModels do not have this issue because your view model should know how to convert itself to/from a data entity, and it does not have a DateAdded field to spoof, it only has the bare minimum fields it needs to display (or receive) it's data.
In your exact scenario, I can reproduce this with ease with POST string manipulation, since your view model has access to your data entity directly.
Another issue with using data classes straight in the views is when you are trying to present your view in a way that doesn't really fit how your data is modeled. As an example, let's say you have the following fields for users:
public DateTime? BannedDate { get; set; }
public DateTime? ActivationDate { get; set; } // Date the account was activated via email link
Now let's say as an Admin you are interested on the status of all users, and you want to display a status message next to each user as well as give different actions the admin can do based on that user's status. If you use your data model, your view's code will look like:
// In status column of the web page's data grid
#if (user.BannedDate != null)
{
<span class="banned">Banned</span>
}
else if (user.ActivationDate != null)
{
<span class="Activated">Activated</span>
}
//.... Do some html to finish other columns in the table
// In the Actions column of the web page's data grid
#if (user.BannedDate != null)
{
// .. Add buttons for banned users
}
else if (user.ActivationDate != null)
{
// .. Add buttons for activated users
}
This is bad because you have a lot of business logic in your views now (user status of banned always takes precedence over activated users, banned users are defined by users with a banned date, etc...). It is also much more complicated.
Instead, a better (imho at least) solution is to wrap your users in a ViewModel that has an enumeration for their status, and when you convert your model to your view model (the view model's constructor is a good place to do this) you can insert your business logic once to look at all the dates and figure out what status the user should be.
Then your code above is simplified as:
// In status column of the web page's data grid
#if (user.Status == UserStatuses.Banned)
{
<span class="banned">Banned</span>
}
else if (user.Status == UserStatuses.Activated)
{
<span class="Activated">Activated</span>
}
//.... Do some html to finish other columns in the table
// In the Actions column of the web page's data grid
#if (user.Status == UserStatuses.Banned)
{
// .. Add buttons for banned users
}
else if (user.Status == UserStatuses.Activated)
{
// .. Add buttons for activated users
}
Which may not look like less code in this simple scenario, but it makes things a lot more maintainable when the logic for determining a status for a user becomes more complicated. You can now change the logic of how a user's status is determined without having to change your data model (you shouldn't have to change your data model because of how you are viewing data) and it keeps the status determination in one spot.
tl;dr
There are at least 3 layers of models in an application, sometimes they can be combined safely, sometimes not. In the context of the question, it's ok to combine the persistence and domain models but not the view model.
full post
The scenario you describe fits equally well using any entity model directly. It could be using a Linq2Sql model as your ViewModel, an entity framework model, a hibernate model, etc. The main point is that you want to use the persisted model directly as your view model. Separation of concerns, as you mention, does not explicitly force you to avoid doing this. In fact separation of concerns is not even the most important factor in building your model layers.
In a typical web application there are at least 3 distinct layers of models, although it is possible and sometimes correct to combine these layers into a single object. The model layers are, from highest level to lowest, your view model, your domain model and your persistence model. Your view model should describe exactly what is in your view, no more and no less. Your domain model should describe your complete model of the system exactly. Your persistence model should describe your storage method for your domain models exactly.
ORMs come in many shapes and sizes, with different conceptual purposes, and MongoDB as you describe it is simply one of them. The illusion most of them promise is that your persistence model should be the same as your domain model and the ORM is just a mapping tool from your data store to your domain object. This is certainly true for simple scenarios, where all of your data comes from one place, but eventually has it's limitations, and your storage degrades into something more pragmatic for your situation. When that happens, the models tend to become distinct.
The one rule of thumb to follow when deciding whether or not you can separate your domain model from your persistence model is whether or not you could easily swap out your data store without changing your domain model. If the answer is yes, they can be combined, otherwise they should be separate models. A repository interface naturally fits here to deliver your domain models from whatever data store is available. Some of the newer light weight ORMs, such as dapper and massive, make it very easy to use your domain model as your persistence model because they do not require a particular data model in order to perform persistence, you are simply writing the queries directly, and letting the ORM just handle the mapping.
On the read side, view models are again a distinct model layer because they represent a subset of your domain model combined however you need in order to display information to the page. If you want to display a user's info, with links to all his friends and when you hover over their name you get some info about that user, your persistence model to handle that directly, even with MongoDB, would likely be pretty insane. Of course not every application is showing such a collection of interconnected data on every view, and sometimes the domain model is exactly what you want to display. In that case there is no reason to put in the extra weight of mapping from an object that has exactly what you want to display to a specific view model that has the same properties. In simple apps if all I want to do is augment a domain model, my view model will directly inherit from the domain model and add the extra properties I want to display. That being said, before your MVC app becomes large, I highly recommend using a view model for your layouts, and having all of page based view models inherit from that layout model.
On the write side, a view model should only allow the properties you wish to be editable for the type of user accessing the view. Do not send an admin view model to the view for a non admin user. You could get away with this if you write the mapping layer for this model yourself to take into account the privileges of the accessing user, but that is probably more overhead than just creating a second admin model that inherits from the regular view model and augments it with the admin properties.
Lastly about your points:
Less code is only an advantage when it actually is more understandable. Readability and understand-ability of it are results of the skills of the person writing it. There are famous examples of short code that has taken even solid developers a long time to dissect and understand. Most of those examples come from cleverly written code which is not more understandable. More important is that your code meets your specification 100%. If your code is short, easily understood and readable but does not meet the specification, it is worthless. If it is all of those things and does meet the specification, but is easily exploitable, the specification and the code are worthless.
Refactoring in seconds safely is the result of well written code, not it's terseness. Following the DRY principle will make your code easily refactorable as long as your specification correctly meets your goals. In the case of model layers, your domain model is the key to writing good, maintainable and easy to refactor code. Your domain model will change at the pace at which your business requirements change. Changes in your business requirements are big changes, and care has to be taken to make sure that a new spec is fully thought out, designed, implemented, tested, etc. For example you say today you want to add a second email address. You still will have to change the view (unless you're using some kind of scaffolding). Also, what if tomorrow you get a requirements change to add support for up to 100 email addresses? The change you originally proposed was rather simple for any system, bigger changes require more work.

Need ideas in designing Domain classes Grails

I am learning Grails, I am trying to build a small application. And for now I am working on the registration part.
There are 3 different views for registration process
1) As an employee my registration view is different with different fields
2) As an employer registration view would be different where I would be collecting company details, an authorized representative who can act on behalf of the company. So as a matter of fact I was thinking that company(employer) is not the actor but representative is an actor and hence need a representative domain class.
3) retailer registration view is different.
So I need to define the domain classes and its relationships I am very much new to grails and I need some guidance in designing
I was initially thinking of User domain class and have UserTypes(which defines different types of users ex. representative,retailer and employee) but not sure if that works.
Appreciate if someone could help me in building my domain classes.
Thanks
You definitely want to map out your domain classes before you start working on the views. Is the authorized rep always going to be an employee, or is it a completely different entity?
Think of it in terms of objects, and try to mimic it as much as possible. A company has employees, and can have an authorized representative. Here's a sample mock up:
class Employee {
String firstName, lastName /* etc... */
}
class Company {
String name /* etc */
Representative authorizedRepresentative
static hasMany = [ employees : Employee ]
}
class Representative {
}
Of course, you may want to have references from the Employees back to its Company. Have a look at the Object Relational Mapping portion of the Grails docs.

Incorporate Membership in ASP.NET MVC

I have been wondering on how to use ASP.NET Membership together with MVC. The basic setup is very simple, but if I want to use extra fields like address, nickname etc, should I then use ProfileCommon or should I create a separate table which contains the extra data and link to the UserId in Aspnet_users?
I have an issue where I have changed the name in Membership to use the email, and I then need the extra fields (address, nickname etc.). If I use ProfileCommon I can receive the object by
public static ProfileCommon GetProfile(string username)
{
return ((ProfileCommon)(ProfileBase.Create(username)));
}
The problem is I save the UserId in different tables, and I can't figure out how to receive the ProfileCommon object by UserId instead of username (which in my case is the email)?
I could then either change the relation in the different tables to use the email, but this would be a very slow implementation, or I could create a separate table with the extra fields.
Is there perhaps a third and better option?
You could simply join the user table in order to receive the email.
Generally it does not seem to be a good idea to use two different fields as the id.
I chose to create the separate table, since I would not be limited by the ProfileBase class.

Resources