Detail
I am developing web application in asp.net core with Identity. now in my application I have two kind of user. Customer and Partner both have different profile information and login scenario.customer can login from simple signup from web page but partner can signup from different view with different mandatory fields.
Problem
How can I design Schema.
what are the good practices in this case.
What are the drawback.
Code
This is what I have done so far
public class ApplicationUser : IdentityUser
{
public CustomerProfile CustomerProfile { get; set; }
}
Use inheritance:
public class ApplicationUser : IdentityUser {}
public class Customer : ApplicationUser
{
// Customer-specific properties
}
public class Partner : ApplicationUser
{
// Partner-specific properties
}
By default, this will be implemented via STI (single-table inheritance). That means you'll have just your standard AspNetUsers table containing columns for the properties on ApplicationUser and all derived types. A discriminator column will be added to indicate which type was actually saved, which will then be used to instantiate the right type when queried.
For the most part, this works just fine. The one downside is that properties on derived classes must be nullable. The reason is simple: it would be impossible to provide values for Customer columns while saving a Partner and vice versa. However, the properties only need be nullable at the database-level. You can still require that they be set in forms and such via a view model.
The alternative is to use TPT (table-per-type). With this approach, you'll get AspNetUsers, but also Customers and Partners tables as well. However, the tables for the derived types will have columns corresponding only to the properties specific to that type and a foreign key back to AspNetUsers. All common properties are stored there. With this, you can now enforce columns have values at the database-level, but querying users will require a join. To use TPT, you simply add the Table attribute to your class, i.e. [Table("Customers")] and [Table("Partners")], respectively.
The one important thing to keep in mind with using inheritance, though, is that you need to work with the type you actually want to be persisted. If you save an ApplicationUser instance, it will be an ApplicationUser, not a Customer or Partner. In this regard, you need to be careful with using the correct types with things like UserManager which generically reference the user type. Even if you create an instance of Customer, if you save it via an instance of UserManager<ApplicationUser>, it will upcast to ApplicationUser and that is what will be persisted. To create a new Customer, you'll need an instance of UserManager<Customer>. Likewise, for partners.
However, this also works to your benefit, as if you attempt to look up a user from an instance of UserManager<Customer> for example, you will only find them if they are in fact a Customer. In this way, it makes it trivially simple to have separate portals where only one or the other can log in, as you've indicated that you want.
Related
In the Spring/Hibernate/Java/Tomcat app I'm writing I have a OneToMany relationship between an Organization and its Contacts.
Organization 1:M Contact (has foreign key org_id)
In Organization I have this field:
#OneToMany(mappedBy="organization")
private List<Contact> contacts;
In Contact I have this field:
#ManyToOne
#JoinColumn(name="org_id")
private Organization organization;
All is working OK so far. Now I'm adding the concept of an Offer. The Offer can be made by an Organization, and you speak with the designated Contact for that particular Offer.
Offer has foreign keys for its organization (org_id) and designated contact (contact_id).
So far, the Offer would look like:
#OneToOne
#JoinColumn(...)
private Organization offering_org;
#OneToOne
#JoinColumn(...)
private Contact offering_contact;
Here comes the point of my question. I've already annotated the Contact class for use with Organization. If I try to persist the Offer object in the usual Hibernate way, I'll need to store copies of an Organization object and a Contact object into the Offer object. This seems to conflict with my existing Organization : Contact use of the two Java classes. For example, if I've a 1:1 with Offer, if I put this into the Contact class do I get an optional use of either or a mandatory simultaneous use of both?
Since the Offer is yet another relationship, do I need to write a data transfer object version of Contact for use in the Offer relationship?
Thanks,
Jerome.
Perhaps I do not fully understand the problem but I'd just do something like this:
// contact & organization being already persisted entity objects
Offer offer = new Offer();
offer.setOffering_org(organization);
offer.setOffering_contact(contact);
// Persisting the new Offer object to the database,
// implicitly making the relations.
service.saveObject(offer);
I see no reason to create copy(s) of the organization object?
It just happens to be that the collection of "contacts" in the Organization object can also be a Contact within one or more Offer objects.
I'm thinking that my original question is kind of stupid. What I did try is to put this in Offer.java:
#Column(name="org_id")
private Long orgId = null;
#Column(name="contact_id")
private Long contactId = null;
I fill orgId manually because an offer is always tied to the user's Organization. It is a hidden field in the web page.
I put a SELECT filled with appropriate Contact objects (contact.id, contact.name) in the web page.
When the web page is submitted the Offer's orgId and contactId fields are filled in the #ModelAttribute parameter. This takes me where I want to go.
To address the comments of Mr. mspringer, your example could work (you illustrated a "create new" situation) if I were willing to use an Organization or Contact list in my Offer object. It is also somewhat the topic of my original question. But since I see that I don't really want to play with the expanded objects within Offer, nor do I wish to, I can avoid the topic of my original question.
Thanks to all who looked at my exercise in confusion.
I have read Scott Guthrie's Blog - ASP.NET MVC 3: New #model keyword in Razor
One things i don't realizes is a page will binding value in different ways,but why we have to enforce the view binding from Model?
For example, a user control panel of forum website, it may have the user information, the post history, the user setting etc.
From the view of data model, the binding source can be come from different table : users, posts, user_settings etc.
However, one view only can reference one #model directive.
Actually ,i can add what properties to model that i have to use.
So what is the advantage of make the view became strongly-typed?
However, one view only can reference one #model directive.
Yes, and this should be your view model. A view model is a class that you specifically design to meet the requirements of a given view. And you do this for each view
From the view of data model, the binding source can be come from
different table : users, posts, user_settings etc.
Great, then design a view model that will contain all the necessary properties and have the controller build this view model aggregating the information from the different places and pass it to the view for displaying.
You should never pass your domain models to your views. Because views are normally the projection of one or more domain models => thus the need to define a view model.
1) You can use automatic scaffolding
2) IntelliSense support
3) Compile time type checking
Your view model should be decoupled from your business models.
A single page will have a single view model.
For example:
public class UserPost
{
public string UserName { get; set; }
public string Subject { get; set; }
public IEnumerable<Message> Messages { get; set; }
}
Your UserName property will be coming from the Users table and the UserName field in it.
Your Subject might be coming from a Subjects table and the Messages from another one.
Your view should be concerned only with presenting already processed information, and not querying data sources.
Therefore it is best practice to create a ViewModel per View. This ViewModel contains all properties needed by the view (users, post, settings etc).
In the controller/model you can instantiate the ViewModel and fill its properties. So don't supply a single table/list of records to a view, but a ViewModel.
The advantage is that, with everything strongly typed, there's less chance on runtime errors. Further, when something changes (i.e. database columns), these errors will be detected by the IDE directly.
I need some help with MVC architecture. I use the following architecture for an object named User.
UserRepository -> IUserRepository -> UserService -> IUserService -> UserController
The User object comes from my database and I'm using EntityFramework. I have a function that returns a list of users Return_All_Users(). One of the fields that gets returned is "UserType". This comes out as a number, but when I show the list in my Index.aspx page, I would like it to show as a string. The number for "UserType" needs to look into a Dictionary to find the string that goes along with the number like "Administrator" and I would like this string to show in my Index page.
How would I go about doing this? I'm currently using this function:
public IEnumerable<User> Return_All_Users()
{
//my code here
}
I had another post for a similar question, and it was suggested that my IEnumerable should return a string, not the User object. I tried that, but then I'm working with a Dynamic model and I didn't want to do that. Nor do I know how to work with a Dynamic model, so I thought maybe there is a better way of doing this.
Should this happen in my UserService? Maybe I need to create a new class called NewUser, and define the UserType as a string, then instantiate a new NewUser and pass the value from User. Before the UserType is passed, I would look in the dictionary and get the correct value for the key.
Should I do that, or is there a better way?
After I posted this question, I just thought of doing this with a stored procedure. Maybe use a stored procedure in my database to return the data, as opposed to looking up my data straight from my database table.
I would create a View Model UserView that was formatted to the representation of how your view would best use that data. You could perform the mapping from User to UserView within your Repository or Controller depending on where you prefer doing this kind of mapping.
I have a few models in my MVC3 web app that have fields that need to be set "behind the scenes" when a user creates or edits an object/entity.
I'm trying to figure out what the best practice is regarding these types of fields.
For example...
public class EntityA {
public int Id { get; set; }
public string Title { get; set; }
...
[ForeignKey("User")]
public int UpdatedBy_Id { get; set; }
public virtual User UpdatedBy { get; set; }
}
The create and edit views for this allow the user to edit the "Title" field, but the "UpdatedBy" field needs to be set by the app when the entity is inserted or updated.
Is it best to drop a hidden field on the views and set "UpdatedBy_Id" there, or use the model property "get/set" body to do so? ...or... Should this be on the HttpPost in the controller?
This is where DTOs (Data Transfer Objects) come in handy.
Your view uses a DTO as it's model. The DTO mirrors your entity object in terms of properties, but excludes properties which you don't want the user to be able to manipulate.
Then in your controller when you are ready to persist the Entity, you create a new Entity object, and take the properties from the DTO passed to the action and copy them to your Entity object. It is at this point you can set the UpdatedBy property.
To make life easier when mapping properties from the Entity to the DTO (and vice versa), you can look at AutoMapper, which will handle this automatically, if you use the same names for your properties.
If you just pass the Entity to the view, there is the potential for the user to change the values of properties that you don't want them to be able to.
I'd prefer to place fields like this outside of user control. Especially if they're integer fields a user can edit to make phony records. The choices then fall between using TempData(if session is enabled) or possibly retrieving it on the fly for the current user. If you're not worried about the user modifying them, then I'd go with a simple hidden field or placing it in the route values for the post, allowing the framework to do the work for you.
I'd say use a hidden field and set the UpdatedBy_Id. It will then be posted back with the form and it can be databound like the rest of the information.
I know it could be bad to use domain models as view models. If my domain model has a property named IsAdmin and I have a Create controller action to create users, someone could alter my form and get it to POST a IsAdmin=true form value, even if I did not expose such a text field in my view. If I'm using model binding then when I committed my domain model, that person would now be an admin. So the solution becomes exposing just the properties I need in the view model and using a tool like AutoMapper to map the property values of my returning view model object to that of my domain model object. But I read that the bind attribute on a class can be used to instruct the Model Binder which properties it should and shouldn't bind. So what really is the reason for making two separate classes (domain model and view model) that essential represent the same thing and then incure overhead in mapping them? Is it more a code organization issue and if so, how am I benefiting?
EDIT
One of the most important reasons I've come across for a View Model that's separate from the Domain Model is the need to implement the MVVM pattern (based on Martin Fowler's PM pattern) for managing complex UIs.
I have found that while my domain model gets me 85% of the way to having the fields I want, it has never covered 100% of the values I want on my view. Especially when it comes to permissions and whether or not a user should have access to certain portions of the view.
The design concept I attempt to follow is to have as little logic in my views as possible. This means I have fields in my view model like "CanViewThisField" or "CanEditThisField." When I first started with MVC I would have my domain model be my view model and I was always running into the scenario where I needed just one or two more fields to make my view less cluttered. I've since gone the View Model/Model Builder route and it has worked wonderfully for me. I don't battle my code any longer but am able to enhance my view model as I need to without affecting the domain model.
Another good reason to have a ViewModel is paging large sets of data. You could pass the view an array of Person ( Person[] ) but metadata such as the number of pages, the number of the current page, the size of the page would not belong on the Person class.
Therefore a PersonListViewModel would solve this issue.
A ViewModel holds only those members which are required by the View. They can usually be thought of as a simplification or a "flattening" of the underlying domain model.
Think of them like this:
ViewModel: this is the data that is appropriate to render on this
view
Domain model: this is all the information my application needs
about this entity in order to perform all it's functionality
For example, my Order class has a member called Customer which is a composition association, that is, my Order has a Customer. This Customer object has members such as Firstname, Lastname, etc... But how would I show this on a "details" view of the order or a list of Orders and the Customers who placed them?
Well, using a ViewModel I can have an OrderListItemViewModel which has a CustomerName member and I can map the combination of Firstname and Lastname from the Customer object to this. This can be done manually, or much preferably using Automapper or similar.
Using this approach, you can have multiple Order ViewModels that are specific to different views, e.g. the Order list view might render the customer name in a different way to the Order details view.
Another advantage of ViewModels is that you can cut down on extraneous data not required of the underlying domain object on a view, e.g. if I'm viewing a list of orders, do I really want to see all the customer's contact information, billing details, etc...? I guess that depends on the purpose of the list but, probably not.
Sometimes you need to display the data in a specific manner (ie, displaying a date in the format mm/dd/yyyy vs. yyyy/mm/dd) and often it is easier to make this property in the view and not in the domain model, where you would (or should) have a mapping to a column in your db.
you need to remember
that your domain model classes are only used internally; that is, they are never sent to the
client. That’s what your service model types (View Model types) are used for—they represent the data that will be going back and forth between the client and your service.