I recently read this blog entry by Hadi Hariri: That dreaded M in ASP.NET MVC. Hadi surveyed fellow ASP.NET MVC developers about the types of models they use in the applications. One of his survey questions read:
If you bind to Domain Model, how do you deal with extra data such as country list?
And one person wrote select Other and wrote in: "conventions." Following that, Hadi wrote:
I've actually found another way to solve this problem, partially based on conventions.
And then later says:
Maybe we should take the concept of conventions more seriously than just what folders our Views, Controllers and Models reside in. Maybe we should push conventions to the limit and see if we actually reduce this friction.
What does he mean by using "conventions" to solve this problem? I'm not familiar with the term in this context.
Thanks
Convention in this context could mean many things. Loosely it is just a solution to the problem that is not built in but looked up using names.
An example of this already in MVC is that a route to a controller named "Home" is mapped to a class named "HomeController". Extending this idea to the selected country and country list problem you can think of many solutions.
One example would be given a model:
public class UploadModel
{
public string Country {get; set;}
}
We may define options for this model via a convention on the naming where it looks for a model with the word "Options" after its name and then matches the property on the model with a like named property on the options model.
public class UploadModelOptions
{
public IList<string> Country {get;set;}
}
This may not be a great convention but is an acceptable example of what the author may be talking about.
Related
What's the most preferred way to work with Entity Framework and DTOs?
Let's say that after mapping I have objects like:
Author
int id
sting name
List<Book> books
Book
int id
string name
Author author
int authorID
My DTOs
AuthorDTO
int id
sting name
BookDTO
int id
string name
int authorID
Since author can have a lot of books I don't want to retrieve all of them, when for example I'm only interested in authors.
But sometimes I might want to get few authors and filtered books or all books.
I could go with multiple queries AuthorDTO GetAuthor(int id) List<BookDTO> GetBooks(int authorID). But that means several accesses to database.
The ways I see it:
If I had in AuthorDTO field List<BookDTO> books the job could be done. But sometimes I would keep this list empty, if for example I listed only authors. And that means some unconsistency, mess and a lot of details to remember.
Return Tuple<AuthorDTO, List<BookDTO>> it might be a bit confusing.
Define new DTO.
AuthorAndBooksDTO
AuthorDTO author
List<BookDTO> books
The problem with sticking to a sinlge AuthorDTO and selectively filling the List is that you are now forced to keep track of where that DTO came from. Is the list of Books not hydrated, or does this Author simply have no books? Do I have to go back to my controller and call a different method to get a different state of the same DTO? This lacks clarity from the consumer's standpoint.
In my experience, I've leaned the way of more DTOs instead of trying to re-use a set of basic DTOs to represent multiple different sets of data. It requires a bit more "boilerplate", having to set up a whole bunch of similar DTOs and mappings between DTO and Entity, but in the end the specificity and clarity makes the codebase easier to read and manage.
I think some clarification of the issues involved will actually solve your confusion here.
First and most importantly, your entity classes are DTOs. In fact, that's all they are. They're classes that represent a table structure in your database so that data from queries Entity Framework makes can be mapped on to them. In other words, they are literally objects that transfer data. The failing of Microsoft and subsequently far too many MVC developers is to conflate them with big-M Models described by the MVC pattern.
As a result, it makes absolutely zero sense to use Entity Framework to return one or more instances of an entity and then map that to yet another DTO class before finally utilizing it in your code. All you're doing is creating a pointless level of abstraction that adds nothing to your application but yet another thing to maintain.
As far as relationships go, that's where Entity Framework's lazy/eager loading comes in. In order to take advantage of it, though, the property representing the relationship must follow a very specific convention:
public virtual ICollection<Book> Books { get; set; }
If you type it as something like List<Book>, Entity Framework will not touch the relationship at all. It will not ever load the related entities and it will not persist changes made to that property when saving the entity back to the database. The virtual keyword allows Entity Framework to dynamically subclass your entity and override the collection property to add the logic for lazy-loading. Without that, the related entities will only ever be loaded if you explicitly use Load from the EF API.
Assuming your property is defined in that way, then you gain a whole world of abilities. If you want all books belonging to the author you can just interact with author.Books directly (iterate, query, whatever). No queries are made until you do something that requires evaluation of the queryset. EF issues just-in-time queries depending on the information you're requesting from the database. If you do want to load all the related books at the same time you retrieve the author, you can just use Include with your query:
var author = db.Authors.Include(m => m.Books).SingleOrDefault(m => m.Id == id);
My first question would be to ask why you are creating DTO's in the first place? Is there a consumer on the other end that is using this data? Is it a screen? Are you building DTO's just to build DTO's?
Since you tagged the question as MVC i'm going to assume you are sending data to a view. You probably want a ViewModel. This ViewModel should contain all the data that is shown on the View that uses it. Then use entity framework to populate the view model. This may be done with a single query using projections or something complex.
So after all that blathering. I would say you want option 3.
Just like the others said, for clarity reasons, you should avoid creating "generic" DTO's for specific cases.
When you want to sometimes have authors and some of their books then model a DTO for that.
When you need only the authors then create another DTO that is more suited for that.
Or maybe you don't need DTOs, maybe a List containing their names is enough. Or maybe you could in fact use an anonymous type, like new { AuthorId = author.Id, AuthorName = author.Name }. It depends on the situation.
If you're using ASP.NET MVC the DTO you'll want is in fact a ViewModel that best represents your page.
Based on what you've described, you're view model could be something like this
public class BookViewModel{
public int Id {get;set;}
public string Name {get;set;}
}
public class AuthorViewModel{
public int Id {get;set;}
public string Name {get;set;}
public List<BookViewModel> Books {get;set;} = new List<BookViewModel>();
}
public class AuthorsViewModel
{
public List<AuthorViewModel> Authors {get;set;} = new List<AuthorViewModel>();
//add in this class other properties, like the filters used on the page...
public void Load(){
//here you can retrieve the data from your database.
//you could do like this:
//step 1: retrieve data from DB via EF
//step 2: fill in the Authors view models from the data at step 1
}
}
//and in your controller you're calling the Load method to fill you're viewmodel with data from db.
public class AuthorsController{
public ActionResult Index(){
AuthorsViewModel model = new AuthorsViewModel();
model.Load();
return View(model);
}
}
With ServiceStack, I'm looking for ways to access related services by composing the URLs in a manner similar to OData.
An OData example would be a URL like
http://localhost:8080/owind.svc/Categories(2)/Products
This would find all the Products related to Category 2.
An equivalent example with ServiceStack seems to be that you would create a Request DTO for a ProductService and set up Routes something like this:
[Route("/Products")]
[Route("/Products/{Id}")]
[Route("/Categories/{Category}/Products")]
public class Products
{
public string Id { get; set; }
public string Category { get; set; }
}
(Ignore the separations of concerns issues mentioned here, the above attributes at least give a clear idea what I'm asking.)
And then in the ProductService you'd support finding Products either via the primary or foreign key. I see something along these lines used in the Northwind.ServiceModel.Operations.Orders class of the ServiceStack.Northwind.ServiceModel sample project.
So I'm wondering, is this the best and most scalable way that exists to do this sort of thing in ServiceStack, or is there some shortcut I'm missing? Thinking on a scale of creating services supporting hundreds of tables, if there existed some sort of shortcut, and if it didn't come with strings attached, it could be helpful.
I can imagine a system where you could automatically generate routes based on anything in a DTO, though you'd need to do some mapping from DTO property name (usually singular) to route (often plural).
No idea if it would be conceivable to carry this beyond one level either...for example
.../Employee/1/Orders/Customers
which would get you every Customer who has had an Order with Employee #1. The notion of implementing this manually on a large scale seems prohibitive. Not sure if there are SOA arguments to be made for or against, but that would be nice to know as well.
Just to be clear, there should be no assumption of the underlying data store or access libraries.
I am working on a new project, and, after seeing some of the difficulties of previous projects that didn't provide enough separation of view from their models (specifically using MVC - the models and views began to bleed into each other a bit), I wanted to use MVVM.
I understand the basic concept, and I'm excited to start using it. However, one thing that escapes me a bit - what data should be contained in the ViewModel?
For example, if I am creating a ViewModel that will encompass two pieces of data so they can be edited in a form, do I capture it like this:
public PersonAddressViewModel {
public Person Person { get; set; }
public Address Address { get; set; }
}
or like this:
public PersonAddressViewModel {
public string FirstName { get; set; }
public string LastName { get; set; }
public string StreetName { get; set; }
// ...etc
}
To me, the first feels more correct for what we're attempting to do. If we were doing more fine grain forms (maybe all we were capturing was FirstName, LastName, and StreetAddress) then it might make more sense to go down to that level. But, I feel like the first is correct since we're capturing ALL Person data in the form and ALL Address data. It seems like it doesn't make sense (and a lot of extra work) to split things apart like that.
Appreciate any insight.
If you are using all the fields of the Person object, then there's nothing wrong with using a complex view model. However, if you are only using a field here or there, then it's much better to build your viewmodel with only those values you are using.
You can do your view models any way you like, but the whole point of having them is that a view model should be customized to the view it's representing.
It can also be a lot easier to use the first method if you're using something like AutoMapper to map to business or domain models, because the objects should have similar definitions.
You're not using MVVM. You're defining ViewModels, classes for only view purposes in order to avoid to break the Model classes. In that case you can define the properties you want for your best profit. In the example I will go for the second solution but it's up to you.
I'm working on a big project with many developer providers. In that case the customer let us to define the ViewModels that we want keeping the Models (Business Entities as they call) for their concern. Because we are different groups no one is worried about another ViewModels so you can even use one class for one view, no matter if another view is different a little bit from the first one. That's one of the advantages of ViewModels instead of pure Model using.
I prefer to define the ViewModels in client-side through JSON objects for the sake of data binding. With this you can truly use MVVM through knockoutjs, angularjs, backbonejs, etc....
If you want to use MVVM check knockoutjs. It's very easy and pleasant to use
Using Model classes directly or wrapping them (as in your 1st example) in your ViewModel class can be a potential security issue if your Model classes have some sensitive properties (i.e. IsAdmin in the User class).
Say your controller actions takes a PersonAddressViewModel input parameter:
public ViewResult someAction(PersonAddressViewModel personAddress)
{
//save it
}
A malicious user can basically set any property in your PersonAddressViewModel composite object even if your UI does not provide such capabilitiy.
This is made possible by the default binding mechanism of the MVC.
To avoid this, either don't wrap sensitive model classes or use the Bind attribute
More on this here: Pro ASP.NET MVC 3 Framework 3rd Edition By Steven Sanderson , Adam Freeman (Chapter 17)
If you're using that view model to render a form, I would vote for the second approach, since you're combining all the view data required for the form.
I'm trying to learn ASPNET MVC. I've built a DbModel starting from DB structure so, under Models, I have the .edmx file that can be used to access data.
I've read that it could be good to have ViewModels classes to act between the View and the Model (useful also for single fields formatting) but I don't' understand if this is right and in which way it's better to build them. If they reproduce classes in my model I believe it is a little bit redundant, isn't it? If this is the right way, is there a way to generate automatically ViewModel classes?
A ViewModel in MVC is a model of your view. It is a property bag containing, usually of primitive types. It may seem redundant, but you are protecting yourself from future problems by decoupling your code.
As an example, given a Person object in your domain model:
public class Person
{
public string FirstName {get; set;} // John
public string LastName {get; set;} // Doe
public DateTime Birthdate {get; set;} // 01/01/1965
}
In your view, you may want to represent this in a view as a full name, age and birthday. Your ViewModel would be similar to:
public class PersonViewModel
{
public string FullName {get; set;} // John Doe
public int Age {get; set;} // 46
public int Birthday {get; set;} // January 1
}
Somewhere in your pipeline, you need to convert from domain model to the viewmodel. I have used either projection queries from the persistence layer or object-to-object mapping frameworks, such as AutoMapper.
By structuring your data this way, you can keep logic and formatting rules out of your view markup. By using a framework, such as AutoMapper, you can also standardize string formatting of dates and times, and do convention-based mappings.
Also, I generally advise having one ViewModel per View. If you need to share View/ViewModel structures or apply conditional view information, those should be separated into partial views.
If you are just starting out I would avoid trying to incorporate every best practice you can find into your early applications. It becomes very easy to try and do everything everyone says is the best practice and you lose track of just learning the fundamentals.
View Models are obviously a great way of seperating the presentation layer and the domain layer, but they serve other purposes. If you are just starting out and your applications are not terribly complicated, I would recommend keeping it simple and use your domain classes as your view model where your views are simple. This will allow you to focus more on the application.
Also, by doing this you will come across views where the simple domain model will not cut it and you will find yourself needing a ViewModel. Which will allow you to incorporate the more specific information you need for your view page (such as multiple domain objects).
By practicing without using View Models for everything, you can gain an appreciation for their benefits and decide what works best for you and your code.
A "view model" (model for a view rather than domain model) helps you separate the domain model from what is bound to the page. Is it always necessary? No, but it is useful if you have some common data shapes used on multiple views where the view will also have some additional data. Another good use is removing certain data from certain types of views (your customer should not know your margin, but your management should?). IT is not mandatory.
I've created a one table contact DB, which has only 3 columns (Id, Name, and Phone). I've then created the ContactsDataContext using my table Contacts in the model folder. Finally, I create a partial class still in the model folder (public partial class Contact).
now when I write this
public partial class Contact
{
public string MyContact
{
get
{
string name = this.Name ?? String.Empty;
}
// ... Other lines omitted
}
}
I get the following error :"'ContactsManager.Models.Contact' does not contain a definition for 'Name' and no extension method 'Name' accepting a first argument of type 'ContactsManager.Models.Contact' could be found (are you missing a using directive or an assembly reference?)"
Is something wrong??? Even the Intellisense in not showing the properties from my DataContext class. Yet, I've written some partial classes in the past with no problem.
Thank you.
Are namespaces the same on the two partials?
Chris Roden,
Yes, I've resolve it. In fact, I've asked the above question many months ago when I started learning ASP.NET MVC. I bought a book called "ASP.NET MVC - The Beer House/Nick Berardi/Wrox." Is a god book, but it's not recommendable for beginners. Generaly, things are thrown like that without telling where they come from.
The response came from applying the definition of a partial class. Among others, partial classes must:
have the same name
be preceded by 'partial' keyword,
be defined in the same namespace,
etc.
If you miss any of the above criteria, then you'll be in trouble because those criteria, ll be used to merge all the partial classes into a unique one.
In my case, I created a table called ContactDB. After I've created the datacontext class, I've dropped the ContactDB table on the Linq2Sql editor. As you must know, that creates the following class:
public partial class ContactDB
{
//All the columns in the table become properties in this class
}
The partial keyword allow me to write this:
public partial class ContactDB
{
//I can reference members of the above partial class... using this keyword
//After all, the 2 constitute one class.
}
After reading the definition of partial classes, I found out that I failed one of the criteria. I called my other partial class "Contact" which's different from ContactDB. That was enough to make me go crazy for 3 days until I read the definition. Moreover, if you defines the partial class with the right name but you put it in a different namespace, you'll get in trouble as well.
So, if the above answer doesn't work for you (I don't know exactly your problem), check the definition of the partial class.Don't forget to read the ScottGu's series on Linq2Sql.
Hope it helps.