Let's say that I have a Domain assembly that describes the domain model, and it has a class called product:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
I have also another assembly that is the web application running with this domain model. Now I want to create a form to create new products and have some validation on the attributes. The easiest way to do this is to use DataAnnotations on the class. However this results in that the domain model now contains metadata about form validation, which is not a very clear separation of concerns.
It is possible to have the MetadataType attribute for the class but I see this as no better. Suddenly your domain model class has a dependency on the form validation metada class.
Another way is to create a CreateProductForm class and add the required attributes there, and do mapping between the classes. However this creates some overhead as you need to maintain these classes seperately and changes in one might break the other. It might be desirable in some scenarios to do that, but in some others it might just create extra work (imagine that you have an Address class, for example).
UPDATE: some people have suggested that I use AutoMapper for this, which I'm already aware of. AutoMapper just makes mapping simpler and easier, does not actually solve the problem of having to maintain two separate classes which will be almost identical. My preference would be to only create the form classes when there is a distinct need for it.
Is there a straightforward to declare the annotations within the web assembly, without creating unnecessary dependencies for the domain assembly?
If you don't want to introduce coupling between your domain model and your views, you should go for the CreateProductForm class way.
Depending on your project size/requirements, you're going to have to separate your view model from your domain sooner or later. Suppose you're using the DisplayName attribute : are you going to tag your domain entities ?
Using a tool like AutoMapper simplifies greatly the mapping process.
Why wouldn't you have DataAnnotations on your domain classes. If there is something that is Required, then I think it's perfectly valid to mark it as required in the domain.
Other DataAnnotations such as StringLength, Range etc, all to me perfectly valid things to decorate your domain entities with.
Implementing IValidableObject is also a perfectly acceptable thing for domain object to do IMHO.
I wouldn't go putting UI stuff on them such as UIHint though or annoations describing the formatting of the property. That would be bad.
Normally I avoid displaying domain classes on the user interface, and use ViewModel classes with a mapping tool such as AutoMapper etc to map from one to the other. The ViewModel class has the annoations of the domain class with perhaps additional UI specific annotations.
As mathieu and XHalent state you should use a CreateProductForm (or a CreateProductFormViewModel) along with Automapper and create attribues that automap the model to the viewmodel for the action.
That way all the form validation goes on your view model and all the data validation (related to the database) goes in your domain model.
In Silverlight and WPF it is called the MVVM pattern and a lot of people who do asp.net mvc recommend it.
In my current project I am also using it with Automapper. All my views have an associated view model that is a flattened version of the domain model specific to that view.
I think this was the example I used (It's the one I still have bookmarked anyway. but this one linked in the first one seems better.)
Using the attribute means that you return the domain object from your action in the controller and the automap attribute maps the domain object to your viewmodel automatically.
Doing this should give you the seperation you are looking for.
Related
I am making a little API in asp.net. It is coupled with an MVC webapp. I intend for the webapp to use it's own API instead of creating 2 backends that do the same thing.
I am struggling a little to try and keep my duplicate code to a minimum when it comes to creating a model to use in the API for both "incoming" (Post, Put) and "outgoing" (get) actions.
I have a class called Event, it contains properties that are easy to serialize to JSON plus a few complex types. I created a model called EventViewModel (is it appropriate to still call it a view model in API?) with some extra properties to get the Names out of the complex types.
Ideally, I'd like to re-use this Model for everything, but when it comes to defining[Required] tags, my logic breaks down...
I first thought of using [Bind(Include() Exclude()] on each of the API actions. Does this sound like a viable solution?
What other solutions have people used?
Thanks!
Here are some thoughts.
I would use separate controllers for view (Controller) and api (ApiController) since we are talking about two different presentations of data. I would not use the controller as an api, since both return different types. An api controller uses statuscodes in a different way. E.g. ApiController.Delete returns statuscode 204 No Content, while Controller returns statuscode 200 Ok with a view.
You can call the models for Controller ViewModels and for ApiController DTO's. In either case, they are just simple objects. Don't put any logic in those objects except for validation (which you can test with the ModelState) and don't use entity objects.
Do not use models / dto's for multiple purposes for the reason you've already encountered. Just use simple objects and use those only once, keep it simple. In that case, if you want to change something you know it is not going to break your application.
You can save code by using base classes that you can inherit. This will also give you the advantage of writing extensions once for different objects.
But if you insist in reusing objects, you can decide not to use ModelState.Validate in Api's. I think in that case the [required] tag is ignored, but I am not sure. As for the objects, I would not use JsonIgnore / Xmlignore but set default values instead. In that case these properties are omitted on serialization. Makes it easy to use objects for both POST and GET.
[DefaultValue(0)]
public int Id { get; set; } = 0;
Use repositories. You can call the repositories in both the controller as in the api controller. This is where you can really save code.
For Api's (not CRUD) I prefer to write specialized linq queries that return anonymous objects and select those into the dto. This gives multiple advantages. Sometimes I use extensions (on IQueryable) to save code.
You may want to consider using something like automapper to save code, but I wouldn't recommend this.
I have my POCO objects in a separate class, with each one implementing interfaces etc, which i believe perfectly fine to do with a POCO object.
I read all over the place that it is bad practice to add Entity Framework attributes to your POCO objects, so instead i use the fluent API. Again i believe this to be correct.
I gather that if you need to apply a custom attribute against a POCO object, then this is not bad practice is it? I guess its just like adding the object to an interface. Or have i got it all completely wrong?
Using code first approach
POCO objects have not dependencies on external libraries. These dependencies could come with the necessity to use external attributes or to derive from external class/interface.
So, nothing wrong with attributes in themselves, it's more about keeping your models clear from external dependencies. If you depend on external libraries in your models, you have to pull them with your models every time: e.g. when you decide to move your models in separate project, or when you decide to write Unit-tests that touch your models etc.
I agree with Ben Robinson that it is a design choice, but if you have chance to use clear models I think you should use it(with EF you have that chance). And if you were talking about your own custom attributes, then it's OK whatsoever.
Bit per bit, I am undestanding and becoming more proficient with ASP.NET MVC4. However I'm still failing to be clear in my mind concerning this very important point. Let us say that I have a model :
public class WorkPaper
{
public int WorkPaperID { get; set; }
public string name { get; set; }
public string description {get ; set; }
public bool verified {get; set;}
public DateTime dateAdded {get; set;}
}
I use this model with Entity Framework code first approach and I have the following DB Context :
public class NicodemeContext : DbContext
{
public DbSet<WorkPaper> Workpapers { get; set; }
}
What I don't understand is : what is the Model Layer and what is the Data Access Layer. To me the WorkPaper class tends to be part of the DAL since I designed it and choosed my properties names and types (navigations property etc...) to fit the EF pattern. But the problem is that if i'm right, I really don't see where I should put the business logic.
In that specific case, if I want to add a rule saying that a Workpaper cannot be sent if it hasn't been verified and an other rule saying that if it's been added more than 2 weeks ago it can't be submitted (strange rules but that's just an example). Where should I add them ? Do I have to create an other class, but then where should I put it and what should it contain ? Isn't it going to be very redundant with the class I already have ? But in the other hand, since that class is "database oriented", wouldn't it be messy to add business rules there ?
My point is really in understanding where I have to put my business logic and to understand the difference between the DAL and the model. I have difficulties to identify the DAL and the Model Layer since their look very similar to me. I would like to do things the correct way.
(Basically, I don't know where to code "my program" with MVC ! I'm not comfortable as soon as I want to code the functionality I'm actually interested in. I feel like i'm not doing the things right)
There is no single "right" way to do this. There are probably a number of "wrong" ways, but as with most things much of it is "it depends".
You will find a lot of opinions on this. And much of that depends on how you are approaching it. For instance, #Tarzan suggests using your model for both business logic and data layer entities. Others, suggest creating separate Entity objects, business objects, and view model objects.
If you're making a relatively simple, CRUD type application then you can probably do as #Tarzan suggests and have few problems. However, in more complex applications you start to run into problems doing it this way. For instance, what happens when your business logic is different from your data logic? If you combine them into a single set of entities, then you are forced to make the logic the same everywhere, or spend a lot of time retrofitting.
The most flexible approach is to keep your Presentation, Business, and Data layers completely separate. In this way, the requirements of (for example) the UI don't need to match the other layers. (Here's a simple example, imagine that for some kinds of objects, a particular field is allowed to be null, but not for others. Your data layer would only know that the field is nullable, while your business layer would know that certain objects can't be null).
However, that approach can have a lot of overhead, and require what seems like duplicate code in each layer... creating a lot of extra effort, which is often times not worth it for small or simple applications.
One key thing to remember is that MVC is a Presentation pattern. That means it ONLY concerns itself with the user interface. The "model" is typically considered to be a "view model", which is the model the view uses. This model is customized for the views requirements. For instance, by using Data Attributes that you would not put on a data model.
If you consider MVC to be strictly presentational, then MVC doesn't care what kind of data access you're using, nor does it care what kind of business layer you're using. It could be a service layer, or a repository, or a business objects library (such as CSLA).
A common pattern in MVC applications is to use a service layer of some type, or a repository if you're simply doing CRUD operations. There is typically some kind of mapping system between each layer, using technologies like AutoMapper or custom build mapping classes.
The point here is simply this. MVC doesn't concern itself with business and data, so don't get yourself all worked up over how these fit into an MVC application. They don't, or at least they don't other than with very basic interfacing.
Your application is a collection of objects, in what can be considered an architecture. This architecture is made up of different layers. MVC, Service, Data, etc.. MVC may be the primary user interface, but that doesn't mean everything else is also MVC.
You can put the NicodemeContext class in the DAL and the WorkPaper class in the Model Layer.
The Model Layer is where you define your business domain. This is where your business logic goes.
The Data Access Layer is where you read and write to the database and populate the objects from your Model Layer.
A useful technique is to use partial classes in the Model. In one partial class keep everything that might be written by a code generator and everything handwritten in the other partial class. For example, if you use a tool to generate a partial WorkPaper class it will usually contain all of the properties and associations. In the handwritten partial class you can place your business logic. If something changes with your domain, this allows you to run the class generator again and again without fear of losing your business logic. I know that you said you are using code-first but still, partial classes can be useful.
Models are where you put business logic, and communicate with the Data Access Layer which saves & retrieves data. Your views are for presenting the user interface. The controllers are for passing information between views and models. It takes awhile to get the feel of MVC, but you are asking the right questions and are on the right track.
Hope this helps. Cheers.
I've been reading too much probably and am suffering from some information overload. So I would appreciate some explicit guidance.
From what I've gathered, I can use VS2010's T4 template thingy to generate POCO classes that aren't tied directly to the EF. I would place these in their own project while my DAL would have an ObjectContext-derived class, right?
Once I have these classes, is it acceptable practice to use them in the UI layer? That is, say one of the generated classes is BookInfo that holds stuff about books for a public library (Title, edition, pages, summary etc.).
My BLL would contain a class BooksBLL for example like so:
public class BooksBLL
{
ObjectContext _context;
public void AddBook(BookInfo book) { ... }
public void DeleteBook(int bookID) { ... }
public void UpdateBook(int bookID, BookInfo newBook) { ... }
//Advanced search taking possibly all fields into consideration
public List<BookInfo> ResolveSearch(Func<BookInfo, bool> filter) { ... }
//etc...
}
So, my ViewModels in my MVVM UI app will be communicating with the above BLL class and exchanging BookInfo instances. Is that okay?
Furthermore, MVVM posts on the Web suggest implementing IDataErrorInfo for validation purposes. Is it okay if I implement said interface on the generated POCO class? I see from samples that those generated POCO classes contain all virtual properties and stuf and I hope adding my own logic would be okay?
If it makes any difference, at present, my app does not use WCF (or any networking stuff).
Also, if you see something terribly wrong with the way I'm trying to build my BLL, please feel free to offer help in that area too.
Update (Additional info as requested):
I'm trying to create a library automation application. It is not network based at present.
I am thinking about having layers as follows:
A project consisting of generated POCO classes (BookInfo, Author, Member, Publisher, Contact etc.)
A project with the ObjectContext-derived class (DAL?)
A Business Logic Layer with classes like the one I mentioned above (BooksBLL, AuthorsBLL etc)
A WPF UI layer using the MVVM pattern. (Hence my sub-question about IDataErrorInfo implementation).
So I'm wondering about stuff like using an instance of BooksBLL in a ViewModel class, calling ResolveSearch() on it to obtain a List<BookInfo> and presenting it... that is, using the POCO classes everywhere.
Or should I have additional classes that mirror the POCO classes exposed from my BLL?
If any more detail is needed, please ask.
What you're doing is basically the Repository pattern, for which Entity Framework and POCO are a great fit.
So, my ViewModels in my MVVM UI app will be communicating with the above BLL class and exchanging BookInfo instances. Is that okay?
That's exactly what POCO objects are for; there's no difference between the classes that are generated and how you would write them by hand. It's your ObjectContext that encapsulates all the logic around persisting any changes back to the database, and that's not directly exposed to your UI.
I'm not personally familiar with IDataErrorInfo but if right now your entities will only be used in this single app, I don't see any reason not to put it directly in the generated classes. Adding it to the T4 template would be ideal if that's possible, it would save you having to code it by hand for every class if the error messages follow any logical pattern.
Also, if you see something terribly wrong with the way I'm trying to build my BLL, please feel free to offer help in that area too.
This isn't terribly wrong by any means, but if you plan to write unit tests against your BLL (which I would recommend), you will want to change your ObjectContext member to IObjectContext. That way you can substitute any class implementing the IObjectContext interface at runtime (such as your actual ObjectContext), which will allow you to do testing against an in-memory (i.e. mocked) context and not have to hit the database.
Similarly, think about replacing your List<BookInfo> with an interface of some kind such as IList<BookInfo> or IBindingList<BookInfo> or the lowest common denominator IEnumerable<BookInfo>. That way you're not tied directly to the specific class List<T> and if your needs change over time, which tends to happen, it will reduce the refactoring necessary to replace your List<BookInfo> with something else, assuming whatever you're replacing it with implements the interface you've chosen.
You don't need to do anything in particular... as Mark said, there is no "right" answer. However, if your application is simple enough that you would simply be duplicating your classes (e.g. BookInfoUI & BookInfoBLL), then I'd recommend just using the business classes. The extra layer wouldn't serve a purpose, and so it shouldn't exist. Eric Evans in DDD even recommends putting all your logic in the UI layer if you app is simple and has very little business logic.
To make the distinction, the application layer should have classes that model what happens within the application, and the domain layer should have classes that model what happens in the domain. For example, if you have a search page, your UI layer might retrieve a list of BookSearchResult objects from a BookSearchService in the application layer, which would use the domain to pull a list of BookInfo.
Answers to your questions may depend on the size and complexity of your application. So I am afraid there will be valid arguments to answer your questions with Yes and No as well.
Personally I will answer your two main questions both with Yes:
Is it acceptable practice to use POCO (Domain) classes in the UI layer?
I guess with "UI layer" you don't actually mean the View part of the MVVM pattern but the ViewModels. (Most MVVM specialists would argue against letting a View directly reference the Model at all, I believe.)
It is not unusual to wrap a POCO from your Domain project as a property into a ViewModel and to bind this wrapped POCO directly to the View. The big Pro is: It's easy. You don't need additional ViewModel classes or replicated properties in a ViewModel and then copy those properties between the objects.
However, if you are using WPF you must take into account that the binding engine will directly write into your POCO properties if you bind them to a View. This might not always be what you want, especially if you are working with attached and change-tracked entities in a WPF form. You have to think about cancellation scenarios or how you restore properties after a cancellation which have been changed by the binding engine.
In my current project I am working with detached entities: I load the POCO from the data layer, detach it from context, dispose the context and then work with that copy in the ViewModel and bind it to the View. Updating in the data layer happens by creating a new context, loading the original entity from the DB by ID and then updating the properties from the changed POCO which was bound to the View. So the problem of unwished changes of an attached entity disappears with this approach. But there are also downsides to work with detached entites (updating is more complex for instance).
Is it okay if I implement the IDataErrorInfo interface on the generated POCO class?
If you bind your POCO entities to a View (through a wrapping ViewModel) it is not only OK but you even must implement IDataErrorInfo on the POCO class if you want to leverage the built-in property validation of the WPF binding engine. Although this interface is mainly used together with UI technologies it is part of System.ComponentModel namespace and therefore not directly tied to any UI namespaces. Basically IDataErrorInfo is only a simple contract which supports reporting of the object's state which also might be useful outside of a UI context.
The same is true for the INotifyPropertyChanged interface which you also would need to implement on your POCO classes if you bind them directly to a View.
I often see opinions which would disagree with me for several architectural reasons. But none of those opinions argue that another approach is easier. If you strictly would want to avoid to have POCO model classes in your ViewModel layer, you need to add another mapping layer with additional complexity and programming and maintenance effort. So I would vote: Keep it simple as long as you do not have a convincing reason and clear benefit to make your architecture more complex.
I'm trying to determine how best to architect a .NET Entity Framework project to achieve a nice layered approach. So far I've tried it out in a browse-based game where the players own and operate planets. Here's how I've got it:
Web Site
This contains all the front end.
C# Project - MLS.Game.Data
This contains the EDMX file with all my data mappings. Not much else here.
C# Project - MLS.Game.Business
This contains various classes that I call 'Managers' such as PlanetManager.cs. The planet manager has various static methods that are used to interact with the planet, such as getPlanet(int planetID) which would return an generated code object from MLS.Game.Data.
From the website, I'll do something like this:
var planet = PlanetManager.getPlanet(1);
It returns a Planet object from from the MLS.Game.Data (generated from the EDMX). It works, but it bothers me to a degree because it means that my front end has to reference MLS.Game.Data. I've always felt that the GUI should only need to reference the Business project though.
In addition, I've found that my Manager classes tend to get very heavy. I'll end up with dozens of static methods in them.
So... my question is - how does everyone else lay out their ASP EF projects?
EDIT
After some more though, there's additional items which bother me. For example, let's say I have my Planet object, which again is generated code from the wizard. What if a time came that my Planet needed to have a specialized property, say "Population" which is a calculation of some sort based on other properties of the Planet object. Would I want to create a new class that inherits from Planet and then return that instead? (hmm, I wonder if those classes are sealed by the EF?)
Thanks
You could try the following to improve things:
Use EF to fetch DTOs in your Data layer, then use these DTOs to populate richer business objects in your Business layer. Your UI would only then need to reference the Business layer.
Once you have created the rich business objects, you can begin to internalise some of the logic from the manager classes, effectively cleaning up the business layer.
I personally prefer the richer model over the manager model because, as you say, you end up with a load of static methods, which you inevitibly end up chaining together inside other static methods. I find this both too messy and, more importantly, harder to understand and guarantee the consistency of your objects at any given point in time.
If you encapsulate the logic within the class itself you can be more certain of the state of your object regardless of the nature of the external caller.
A good question by the way.
IMHO, your current layout is fine. It's perfectly normal for your UI to reference the 'Data' layer as you are calling it. I think that perhaps your concern is arising due to the terminology. The 'Data' you have described more often referred to as a 'business objects' (BOL) layer. A common layout would then be to have a business logic layer (BLL) which is your 'Managers' layer and a data access layer (DAL). In your scenario, LINQ to Entites (presuming you will use that) is your DAL. A normal reference pattern would then be:-
UI references BLL and BOL.
BLL refences BOL and DAL (LINQ to Entites).
Have a look at this series of articles for more detail.
As for your second question (after the EDIT) if you need or want to add features to your EF objects you can use partial classes. Right click the EDMX file and select view code.
Or if this isn't enough for you can ditch the designer and write your own EF enabled classes.
There is a (brief) discussion of both options here -
http://msdn.microsoft.com/en-us/library/bb738612.aspx
As for your second question in the "EDIT" section:
If I'm not mistaken, the classes generated by EF are not sealed, and they are PARTIAL classes, so you could easily extend those without touching the generated files themselves.
The generated class will be:
public partial class Planet : global::System.Data.Objects.DataClasses.EntityObject
{
...
}
so you can easily create your own "PlanetAddons.cs" (or whatever you want to call it) to extend this class:
public partial class Planet
{
property int Population {get; set;}
...
}
Pretty neat, eh? No need to derive and create artificial object hierarchies....
Marc
I'm no expert, but that sounds pretty good to me. That similar to what I have in my solutions, except I just merge the EF project with the business project. My solutions aren't that big, and my objects don't require a lot of intelligence, so its fine for me. I too have a ton of different methods for each of my static helper classes.
If you don't want the presentation layer knowing about the data access layer, then you have to create some intermediary classes, which would probably be a lot of work. So whats the problem with your current setup?
Your layout looks ok.
I would have added a Utility/Common layer
Web UI
Business Layer
Dataobjects
Utilities layer
I would add DTOs to your Business layer that are "dumb object" representations (i.e. only properties) of the Entities in your data layer. Then your "Manager" classes can return them, such as:
class PlanetManager
{
public static PlanetDTO GetPlanet(int id) { // ... }
}
and your UI can only deal with the BLL layer via POCOs; the Manager (what I would call a "Mapper" class) handles all the translating between the objects and the data layer. Also if you need to extend the class, you can have a "virtual" property on the DTO object and have the Manager translate that back to its components.