I have a few different types of companies that can access my web application e.g
Different types of Companies:
Client
Supplier
Agent
Each have their own table in the database, linked to the main table Company which stores all common data e.g. Address, Tel, Email, TypeOfCompany with a FK to the relevant table (Client etc.)...
What is the best way to handle this OO throughout my app?
I currently do something like:
public class CompanyDTO
{
public int Id {get;set;}
public string Name {get;set;}
public Address Address {get;set;}
public string Type {get;set;} //type of company
//etc...
}
then inherit from that class and add aditional properties e.g.
public class ClientDTO : CompanyDTO
{
public string Key {get;set;}
public Address Billing {get;set;}
}
However I am finding it problematic at times for example
Supplier user wants to access: AllCompanies, - show a list of all companies
Then the user from the Supplier Company wants to view a specific companies detail, now if it is a client I will need to show ClientDTO or SupplierDTO? In this instance I want to show that specific companies Full details
What would be the best way to handle this?
e.g. GetCompanyByID(int companyid); or GetClientByID(int clientid); What type of object should I return in both instances, presuming I want Client details in both instances...
Funny how databases don't understand OO practices like derivation, aggregation, and encapsulation. It is an unfortunate failing but still only a part of what is overall referred to as "database impedance mismatch".
What your attempting to do is common enough there are several solutions...
Firstly there is the choice of the data model stored. There are basically three possibilities.
Split the tables as you have done.
Declare all fields for all derived types in the same table.
Use a blob field (json/xml/whatever) to house the uncommon fields.
Secondly there is the issue you bring up, requesting the data from the database. Primarily this is centered around the request of a list of the 'common' base type and how to then access the uncommon fields that they don't share. Again there are several possibilities.
When listing the base type only those common fields are returned. Then subsequent queries are issued one-off to lazy load the other fields.
When listing the base type all other tables needed are also outer joined to the main table to ensure all fields are available to instantiate the object model fully.
When listing the base type, multiple result sets are returned, one for each 'sub type' table that may be needed for the results. The client then pieces the records together building up the object model until it is complete.
Not an exhaustive list, but a start. Personally I prefer to avoid data models like the one you describe for this reason. Essentially my preference is to have the data model define the union of all fields (model #2), and then use a business layer to determine what properties are exposed, validated, required, etc. I have also used model #3 above, using blob fields for multiple values, and it works well enough also depending upon need. The only downside to model #3 over #2 is that you will not be able to query or sort on those fields. Ultimately either approach still needs the business logic layer involved to know what data to expose.
Remember databases are stupid, treat them as such and you will get along well. (note: this advice does not work on people, just databases)
I want to access: AllCompanies, - show a list of all companies
When you want a list of companies, aren't you asking for the general details that instances of CompanyDTO describe? Maybe your data access (service, repository, etc) could look like:
public class CompanyRepository : ICompanyRepository
{
public IEnumerable<CompanyDTO> GetCompanies()
{
// get companies and map them to CompanyDTO objects as necessary
}
}
Then you asked (well, there is a question mark)
Then I want to view a specific companies detail, now if it is a client I will need to show ClientDTO or SupplierDTO?
I'm assuming this would be a separate view, or at least broken down into a separate partial views. But, you could use Display Templates to describe your child types of companies since you've describes an inheritance above.
I will pretend you showed us your controller and it looks like this:
public class CompanyController : Controller
{
public ActionResult Details(int id)
{
CompanyRepository repo = new CompanyRepository();
return View(repo.GetCompanyById(id));
}
}
Then, add a strongly-typed view named Details, that inherits a CompanyDTO object, and add a call to Html.DisplayForModel():
<%--some scaffolded code ommitted for brevity--%>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<%= Html.DisplayForModel() %>
</asp:Content>
Then, here's where display templates come in. Add a folder:
~/Views/Company/DisplayTemplates
Then add to that folder 3 strongly-typed, partial views--one for each child type. Visual Studio will help you with this:
Right-click the DisplayTemplates folder --> Add View...
Name it "ClientDTO" (this is important)
tick "Create a partial view"
tick "Create a strongly-typed view"
Select the ClientDTO class
Select Details for view content (this will give you some auto generated markup)
Click Add
Repeat this process for other child types and the correct template will be rendered based on the child type of the model passed to your Details view.
Related
I'm developing a site in MVC, and I have a payment form which includes customer information as well as payment information. I'm not storing payment info in my database, so I don't want to add any of it to my customer info model. It'd be nice if I could do something like this:
public void PaymentConfirmation(CustomerInfo customer, PaymentInfo payment)
{
//do stuff
}
But I don't think the mvc model binder does anything like that by default. What's the best practice for handling situations like this?
I am assuming that when you say
I'm not storing payment info in my database, so I don't want to add
any of it to my customer info model.
What you mean is that your customer model is a domain model (generated from EF or some other ORM). If not using an ORM, the single responsibility principle still comes into play in that PaymentInfo is really not related to the CustomerInfo and should have its own base class. Not combining these into a big "do everything" class makes sense.
What you can do, however, is create a ViewModel for this particular view that contains all of the information that you need. This will not cause a DB change and is, basically, a simple wrapper for all the data that is needed by the view to do whatever it does. A basic example would be
public class PaymentConfirmationViewModel{
public CustomerInfo Customer {get;set;}
public PaymentInfo Payment {get;set;}
}
As you can see, we are wrapping two stand alone classes into one for consumption by the view/action result. However, using View Models allows you to completely customize and restrict/add the information that is available to your view. Meaning, if there are properties on the domain model that the view does not need, then don't make them part of the view model.
Now, your controller method would be
public void PaymentConfirmation(PaymentConfirmationViewModel model)
{
//do stuff
}
The only other item you would need to change is your view, in that your Html Helpers would need a slightly different lambda expression (random example).
#Html.LabelFor(x=>x.FirstName)
would become
#Html.LabelFor(x=>x.Customer.FirstName)
If you are manually creating your input fields in raw HTML, the the following updates would occur.
<input type="text" id="FirstName" name="FirstName" />
would become (note the underscore in the ID attribute of the input field)
<input type="text" id="Customer_FirstName" name="Customer.FirstName" />
I've come across an interesting question during my development. Right now, I use a database-agnostic unit of work layer to abstract the access of data from the actual database dependencies in my ASP MVC 4 web application.
Each individual database project which implements the unit of work interfaces are aware of my business models (models that go directly to/from the database). I'm not too sure how I feel about this approach, but that's not the question I am going to ask.
Should I be using a solution like AutoMapper to convert my business models to/from domain models - models that are passed to the view and used for any work that shouldn't have access to database fields (i.e., IDs)?
For example, consider inside my BusinessModels project, I have the following classes
BusinessModels
/UserAccounts/
User.cs
- ID
- Username
- HashedPassword
- Salt
UserSettings.cs
- IsSubscribedToNewsletter
- AllowDirectEmails
Would it make any sense to bind these User, and UserSettings models into a single model using AutoMapper like so
MyProject
/DomainModels/
User.cs
- Username
- HashedPassword
- Salt
- IsSubscribedToNewsletter
- AllowDirectEmails
for the purpose of views?
This question also extends to non-MVC projects but I feel seeing as I am working on an MVC project it would make more sense to ask it in that tag.
TLDR is there any point in mapping business models/entities to view models or does that provide an unnecessary layer of abstraction? And if so, would the Repositories contain business models, or view models (which map automatically to business models under-the-hood)?
You can use view models for two different things:
rendering a new view (GET action), passing the view model object as the model for the view
receiving data back from the view, in a Post Action (POST action), using the view model as parameter
(I know, the second is arguable. But it's not strange to use the view models for this)
The model for the GET action needs all the properties neccessary to render the View:
the values of the entity you're showing/editing
extra values needed to render the view (for example SelectLists for drop down lists)
Suppose that you have a User which can belong to one UserGroup.
In this case, if you want to edit the user, the model needs:
the User data
a list of UserGroups
I'd use a model like this:
public class EditUserModel
{
public User User {get;set;}
public SelectList UserGroups {get;set;}
}
As you can see, I directly add the User as a property. But I don't add the list of categories as a property, because I don't need the whole list of categories, with all their properties in the view. Besides, if you unit test the controller you can verify that the SelectList is as expected (that couldn't be done if you created the User Groups list in the view)
But, what if you don't need all the properties of the user in the View? Is it worth removing the User property, and add individual properties for Name, Email, JoinedData, Active... ? I think the anser is NO. Imagine you add/remove or rename some of the User entity properties. If you had individual properties in the view model, you'd have to change them as well, before updating the View. And, if you rely on automatic mapping (auto mapper, value injecter) you would't even realized if you make some mistake.
I also said that the view model can be used for posting back data to the controller. So you could do this:
[HttpPost]
public ActionResult Edit(EditUserModel userModel)
If you do so, the model binder will populate the userModel with the values in the form controls. So you'lll get back a half empty model. In this case, the UserGroups list would be null, and, depending on how many of the User's properties you edit, the User could also have many null/non-initialized properties.
To avoid making errors, in some occasions is advisable to create a different model (and probably auxiliary classes) to make it clear what is expected to be posted to the model.
For example, if you have an action to show the whole user data, but which only allows to change its password, you could create a class with two properties: Password, and PasswordConfirmation.
In this case, the view model for the POST could only have the Password and PasswordConfirmation. And derive a model for the GET which has this inherited properties, and also the list of User Groups and the User.
Why inheriting and not using independent classes? Simply beacuse when you use something like Html.TextBoxFor(m => m.User.Name), the Model Binder will be able to set the Name property of the User property, only if the parameter for the post action has the same structure. I.e. if the view model for the get has this structure:
public ChangePasswordModel
{
public string Password {get;set;}
public string PasswordConfirmation {get;set;}
// extra properties, like the list of user groups, the user data...
}
And the model for the post has this structure:
public PostedChanegPasswordModel
{
public User User {get;set;}
}
The content of the input rendered by Html.TextBoxFor(m => m.EditedUser.Name) won't be bound to the User.Name of the PostedEditViewModel.
But if you make this:
public EditUserModel : PostedEditUserModel
{
// extra properties, like the list of user groups
}
the data will be bound without any problem.
In general you have to be careful with the models you use for posting and getting. And I recommend using as many different view models as neccesary.
When to use automatic property mapping to completely new view and different models?
You must have a very strong reason to have different view models. This could be a result of starting the application from outside in (i.e. design first) or because a team is developing the UI before or while the business logie is being implemented.
In this case you can find that the classes for the view models, and the views themselves are already defined, and are quite similart to your entities, but not exactly equal. This is one case when I think it can be good to use mappers.
The other reason to use different classes would be to decouple the interface from the logic. But this usually only happens in the previous case.
Regards viewmodels I treat them like a summary of the data you wish to work with.
So taking from your example, your viewmodel would contain data from both the User and UserSettings classes. Let's say you had a view named UserData.cshtml then I would code it up like so:
public class UserDataViewModel
{
public string Username { get; set; }
public bool AllowDirectEmails { get; set; }
// etc ...
}
public ActionResult UserData()
{
var viewModel = new UserDataViewModel();
viewModel.UserName = "Whatever";
viewModel.AllowDirectEmails = false;
// Or however you get the data for the user.....
return View(viewModel)
}
Hopefully you get the idea. So you are on the right track with merging information from externals classes into one viewmodel class. Bascially tie everything together in the viewmodel class.
I name the viewmodel class the same as the view that it's going to be used for. This can help documentation, as well as make it easier for devs new to the code to follow.
After doing some research I see that almost everyone maps its entities retrieved from the service to a (view) model in the Controller. In my opinion this gives a implementation problem. The controller is responsible for hiding/showing specific data instead of the Service/Business logic. For example, with a user object, the password field would be transferred from the service layer to the controller because it is in the entity and then the Controller has to enforce that it is hidden.
After some thoughts I came up with another way of doing it. The repository layer returns the entities. In the Service layer then the entity is mapped onto a model and for the ViewModels I make a separate partial class that extends the model to add metadata for MVC (for validation):
using System.ComponentModel.DataAnnotations;
[MetadataType(typeof(MyClassMetadata))]
public partial class MyClass
{
private class MyClassMetadata
{
[Required]
public int Id;
[Required]
[StringLength(100)]
public string Name;
}
}
Secondly, when an entity needs a relational entity, for example a City needs a reference to a Country before stored in the database, it is weird to send the City back to the Service without a Country attached. This makes that retrieving the Country is going to be in the Controller. Though, in my opinion this should be an action performed by the service (maybe in conjunction with another service or repository.)
Because above is not the general practice, I’m concerned in overlooking something? When I implement it like above, will I encounter (unforeseen) probleems?
I can answer your first question, but not second (regarding relation entity using ORM) since I lack experience with N-tier and ORM.
For your first question, it is intended to have some (view)model in the presentation layer. It is when you has UI-specific logic such as screen position, css style, etc where it is needed to be set, view model will be useful to hold those informations.
Say that you need to retrieve 1000 requests. From among those requests, there are unsorted 300 error requests, and 200 warning requests. You need to display those requests at grid, with customized styles (such as font color in red for error requests, etc).
One simplest way is to assign the css class into each requests, and use that class to determine the style of each requests.
For the second question, I believe providing different methods such as GetCity and GetCityWithCountry will fulfill the requirements for relationship entities. But it is just my 2 cents.
Whats the difference between Model and ViewModel? I should use both of them or I better skip one of them? who grabs the data from the database?
I wonder whats the best/right way to take my data from the database.
One option is to have a DAL (Data Access Layer) and instantiate it in every controller,
fill with it the viewmodels like:
var viewmodel = Dal.GetArticles();
Another option is to let the model itself grab the information from the Database:
var model = new ArticlesModel();
model.GetArticles();
public void GetArticles()
{
var context = new DbContext();
_articles = context.Articles
}
Another similar option is to have a static DAL so you can access it inside every model,
so each model will have a method to grab the data using the static DAL class (Which contain a DbContext class inside to access the Database)
public void GetArticles()
{
_articles = DAL.GetArticles();
}
So the general question is if the model itself needs to grab the data from the database or the controller itself can have access to the DAL.
While someone is writing a more useful answer, I will quickly address your points.
Model is the data you want to display.
More often than not, you will want to use object relational mapping so most of your business object classes correspond to database tables and you don't have to manually construct queries.
There are plenty of ORM solutions available, including Entity Framework, NHibernate and (now dying) LINQ to SQL.
There is also an awesome micro-ORM called Dapper which you may like if bigger frameworks feel unneccessarily bloated for your solution.
Make sure you learn about the differences between them.
DAL is more idiomatic in .NET than classes that “know” how to load themselves.
(Although in practice your solution will very likely be a mixture of both approaches—the key is, as usual, to keep the balance.)
My advice is to try keeping your models plain old CLR objects as long as your ORM allows it and as long as this doesn't add extra level of complexity to the calling code.
These objects, whenever possible (and sensible—there are exceptions for any rule!), should not be tied to a particular database or ORM implementation.
Migrating your code to another ORM, if needed, will be just a matter of rewriting data access layer.
You should understand, however, that this is not the main reason to separate DAL.
It is highly unlikely you'll want to change an ORM in the middle of the project, unless your initial choice was really unfit for the purpose or you suddenly gained a traction of 100,000 of users and your ORM can't handle it. Optimizing for this in the beginning is downright stupid because it distracts you from creating a great product capable of attracting even a fraction of hits you're optimizing for. (Disclaimer: I've walked this path before.)
Rather, the benefit of DAL is that you database access becomes always explicit and constrained to certain places where you want it to happen. For example, a view that received a model object to display will not be tempted to load something from the database, because in fact it is the job of controller to do so.
It's also generally good to separate things like business logic, presentation logic and database logic. Too often it results in better, less bug-ridden code. Also: you are likely to find it difficult to unit-test any code that relies on objects being loaded from the database. On the other hand, creating a “fake” in-memory data access layer is trivial with LINQ.
Please keep in mind that again, there are exceptions to this rule, like lazy properties generated by many ORMs that will load the associated objects on the go—even if called within a view. So what matters is you should make an informed decision when to allow data access and why. Syntaxic sugar might be useful but if your team has no idea about performance implications of loading 20,000 objects from ORM, it will become a problem.
Before using any ORM, learn how it works under the hood.
Choosing between Active Record-style objects and a DAL is mostly a matter of taste, common idioms in .NET, team habits and the possibility that DAL might eventually have to get replaced.
Finally, ViewModels are a different kind of beast.
Try to think of them like this:
You shouldn't have any logic in views that is more sophisticated than an if-then-else.
However, there often is some sophisticated logic in showing things.
Think pagination, sorting, combining different models in one view, understanding UI state.
These are the kinds of thing a view model could handle.
In simple cases, it just combines several different models into one “view-model”:
class AddOrderViewModel {
// So the user knows what is already ordered
public IEnumerable<Order> PreviousOrders { get; set; }
// Object being added (keeping a reference in case of validation errors)
public Order CurrentOrder { get; set; }
}
Models are just data, controllers combine the data and introduce some logic to describe data to be shown in view models, and views just render view models.
View model also serves as a kind of documentation. They answer two questions:
What data can I use in a view?
What data should I prepare in controller?
Instead of passing objects into ViewData and remembering their names and types, use generic views and put stuff in ViewModel's properties, which are statically typed and available with IntelliSense.
Also, you'll likely find it useful to create ViewModel hierarchies (but don't take it to extremes!). For example, if your site-wide navigation changes from breadcrumbs to something else, it's cool to just replace a property on base view model, a partial view to display it and the logic to construct it in the base controller. Keep it sensible.
A model represents the structure you like your data in and is not concerned about the view which may consume it. A model's intend is purely that of representing the structure.
A model may contain properties irrelevant to the view consuming it.
A view-model is designed with the view in mind. A view-model is intended for a 1-to-1 relationship to a view. A view-model only contains the basic fields and properties the view it is intended for requires.
In general you would have your controller contact a repository (In your example your DAL) obtaining the data and then populating either a model or view-model with the results, sending it down to the view.
Model (Domain Model): is the heart of the application, representing the biggest and most important business asset because it captures all the complex business entities, their relationships and their functionality.
ViewModel: Sitting atop the Model is the ViewModel:The two primary goals of the ViewModel are
1. to make the Model easily consumable by the View and
2. to separate and encapsulate the Model from the View.
Eg.
Model:
public class Product
{
...............
}
public class Category
{
...........
}
ViewModel:
public class ProductViewModel
{
public ProductViewModel(List<Product> products, List<Category> categories)
{
this.Products = products;
this.Categories = categories;
}
public List<Product> Products { get; set; }
public List<Category> Categories { get; set; }
}
i have got various custom datatypes in my web application to map some data from the database.
something like:
Person
Id
Name
Surname
and i need a List of persons in most of my application's pages
i was thinking to create a getter property that gets the list of persons from the database and store into cache in this way i do not have to call the database each time
something Like (pseudo code)
public List<Person> Persons
{
get { return if cache != null return List of Persons from cache else get from the database;}
}
Where shall i put this getter? in my Person class definition or into my base page( page from which all the others pages inherit)
Thanks
I think putting it in your base page would be better option.
Depending on your application architecture, putting process related code in your domain classes might be an issue. Some use it in DDD (domain-driven design) type applications though.
Better even, I usually try to hide those implementation details in a service class. You could have a PersonService class that would contain your above method and all person related operations. This way, any page requiring person information would simply call the PersonService; and you can concentrate your page code on GUI related code.
I don't think that you should put it in your Person class since it accesses the database and HttpContext.Current.Cache. Furthermore I think you should make it a method and not a property, to imply that this may be a "lengthy" operation. So, of the two options, I would put it on the base Page class.