In my solution I have two projects.
Project 1 (Core)
Mapping SQL to DTO using Dapper
Project 2 (WebUI - ASP.NET MVC 4)
Here I use a ViewModel per View.
Examples of a Controller
[HttpGet]
public ActionResult Edit(int id)
{
// Get my ProductDto in Core
var product = Using<ProductService>().Single(id);
var vm = new ProductFormModel(product);
return View(vm);
}
Examples of a ViewModel
public class ProductFormModel : BaseViewModel, ICreateProductCommand
{
public int ProductId { get; set; }
public int ProductGroupId { get; set; }
public string ArtNo { get; set; }
public bool IsDefault { get; set; }
public string Description { get; set; }
public string Specification { get; set; }
public string Unit { get; set; }
public string Account { get; set; }
public decimal NetPrice { get; set; }
public ProductFormModel(int productGroupId)
{
this.ProductGroupId = productGroupId;
}
public ProductFormModel(ProductDto dto)
{
this.ProductId = dto.ProductId;
this.ProductGroupId = dto.ProductGroupId;
this.ArtNo = dto.ArtNo;
this.IsDefault = dto.IsDefault;
this.Description = dto.Description;
this.Specification = dto.Specification;
this.Unit = dto.Unit;
this.Account = dto.Account;
this.NetPrice = dto.NetPrice;
}
public ProductFormModel()
{
}
}
Explanation:
I'll get my DTOs in my controller using a service class in the project (Core).
Then i create my ViewModel and pass the DTO to the constructor in ViewModel.
I can also use this view to add a new Product because my ViewModel can take a empty constructor.
Does anyone have experience of this. I wonder if I am in this way will have problems in the future as the project gets bigger?
I know this has nothing to do with Dapper. But I would still like a good way to explain my solution.
I think you will be fine using your current approach. More importantly, start out like this and refactor if you start to encounter problems related to your object mapping code (instead of thinking too much about it beforehand).
Another way to organize mapping logic that I use sometimes is to employ extension methods. That way, the mapping code is kept separate from the view model itself. Something like:
public static class ProductMappingExtensions
{
public static ProductFormModel ToViewModel(this ProductDto dto)
{
// Mapping code goes here
}
}
// Usage:
var viewModel = dto.ToViewModel();
Yet another approach would be to use a mapping framework like AutoMapper - this is a good fit in particular if your mapping logic is simple (lots of 1:1 mappings between properties).
But again, start simple and refactor when you need to.
I realize that this is a little bit late answer, but maybe it will help someone in the future.
This way of doing mapping between objects breaks the 'S' of the SOLID principles, because the responsibility of the ViewModel is to prepare data in its properties to be ready to use by the view and nothing else, therefore, mapping objects should not be on it's responsibilities.
Another drawback of this way is that it also breaks the 'Loose Coupling' OO principle as you ViewModel is strongly coupled with your DTO.
I think, even when we are in the very first step of the project, there are some importants OO principles that we should never break, so using mapper classes, either auto (AutoMapper, ValueInjecter ...) or manual, is definitely better.
Related
Consider this simple one to many relationship in Entity Framework. One organisation holds many products.
public class Product
{
public int Id { get; set; }
[StringLength(20)]
public string Title { get; set; }
[StringLength(300)]
public string Description { get; set; }
public float Price { get; set; }
public DateTime CreationDate { get; set; }
public virtual Organisation Organisation { get; set; }
public Product()
{
CreationDate = DateTime.Now;
}
}
public class Organisation
{
public int Id { get; set; }
[StringLength(20)]
public string Title { get; set; }
[StringLength(400)]
public string Description { get; set; }
public DateTime CreationDate { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
If I have a (post) api call, accepting raw data in the body (json formatted text), which allows the user to create an organisation and as many products as they want, in the same call. How do I correctly save these data into the database using Entity Framework?
As far as I know I am using lazy loading (due to virtual keywords when setting relations in the models), so shouldn't it handle relations automatically? If I save the data like in the controller action below (the controller action for the post call). Will it work? And if it doesn't, what is the appropriate/best practice method for saving a model that contains a list of another model using Entity Framework.
public IHttpActionResult CreateOrganisation(Organisation org)
{
db.Organisations.Add(org);
db.SaveChanges();
return Ok(org);
}
Really can't seem to find this in the docs?
Well, i didn´t have time to try it, but looking at your code i see that there are some suggestions that i may point to you if you are looking for the best practices even if these don´t anwser your question:
Make your Web API Controller using the Async Task pattern to avoid dead locks:
public async Task<IHttpActionResult> CreateOrganisation(Organisation org)
Make the caller method, the business logic of your ef, as the same pattern above. In this case use the SaveChangesAsync() method. Don´t forget to use also the keyword await when calling any method as the example above within your controller.
Make the use of the separation of concerns. Apply the BL out of your Controller class.
Apply the SOLID principle. Dependency of inversion, letter D, for example using the Microsfot Unity IOC container, make the classes loosely coupled using abstract classes, interfaces, so after that apply the dependency of injection.
Try to use a View Model to valide the model instead of the domain class generated by the datafirst model or the code first model by the EF.
Last but not least, strongly typed!!!!
I hope these suggestions would help you.
Since you asked for "best practices", I'll tell you about a technique I had to work with back when EF's handling of object graphs was a little, shall we say "iffy"?
First, each physically stored entity has a corresponding DTO object. Part of the ViewModel (MVVM-speak) was the necessary DTO object(s) for that View. There were additional fields added to communicate State (what the UI did) for each entity. It looked something like this:
public class ProductDTO {
// Same fields, mostly
public string Action { get; set; } // A, C, D
}
public class OrganizationDTO {
// Same fields except children
public ICollection<ProductDTO> Products { get; set; }
public string Action { get; set; }
}
Based on non-blank Action in the top level DTO, POST, PUT or DELETE (A,C,D). UI sets the states of each entity. A modification to children counts as a "change" to the parent.
Then in my CRUD methods on the backend ... Admittedly, this is the sledgehammer approach.
public class OrganizationRepository : whatever interfaces {
public void Add (OrganizationDTO newOrg) {
if (newOrg.Action != "A") // Why are you here?
throw an exception (bad request)
context.Organizations.Add(Map DTO to entity here);
foreach (var item in newOrg.Products) {
switch (item.Action)
case "A":
ProductRepository.Add(item,newOrg.Id);
break;
case "C":
ProductRepository.Update(item,newOrg.Id);
break;
case "D":
ProductRepository.Delete(item);
break;
}
context.SaveChanges();
}
public void Update (OrganizationDTO oldOrg) {
if (newOrg.Action != "C") // Why are you here?
throw an exception (bad request)
context.Organizations.Attach(Map DTO to entity here);
foreach (var item in newOrg.Products) {
switch (item.Action)
case "A":
ProductRepository.Add(item,newOrg.Id);
break;
case "C":
ProductRepository.Update(item,newOrg.Id);
break;
case "D":
ProductRepository.Delete(item);
break;
}
context.SaveChanges();
return Ok();
}
}
This is not working/tested code. Just rough off-the-cuff. Have to handle FKs on adds. Add your mapping technique. Handle collisions, Try/Catch, etc.
I think your code is not well self-explaining.
If I'm a developer that looks at the method you posted here, I would simply not understand that i have the possibility to send nested-data.
I would make an iteration over the Products collection of the object "org" and add them to their EF collection, then late add the Organisation to its own.
Then, obviously, SaveChanges().
This would clearly distinguish this method that accept nested object, from another ipothetical that doesn't and simply saves my new empty Organisation.
Suppose I have a model with 20 fields, and in my index page, I want to list all models that are stored in my database.
In index page, instead of listing all fields of the model, I only to list 3 fields.
So, I make two class:
class CompleteModel {
public int Id { get; set; }
public string Field01 { get; set; }
public string Field02 { get; set; }
public string Field03 { get; set; }
public string Field04 { get; set; }
public string Field05 { get; set; }
...
public string Field20 { get; set; }
}
now, in my Controller, I can use:
await _context.CompleteModel.ToListAsync();
but I feel that it does not seem to be the right way to do it, because I'm getting all fields and using only 3 fields.
So, I made this code:
class ViewModel {
public string Field02 { get; set; }
public string Field04 { get; set; }
public string Field08 { get; set; }
}
var result = _context.CompleteModel.Select(
x => new {
x.Field02,
x.Field04,
x.Field08
}).ToListAsync();
var listResults = new List<IndexViewModel>();
if (result != null)
{
listResults.AddRange(results.Select(x => new IndexViewModel
{
Field02 = x.Field02,
Field04 = x.Field04,
Field08 = x.Field08
}));
}
I think this is a lot of code to do this.
First, I selected all the fields that I want, then, copied everything to another object.
There's a "more directly" way to do the same thing?
Like:
_context.CompleteModel.Select(x => new IndexViewModel { Field02, Field04, Field08 });
You could use AutoMapper to reduce the boiler plate so you're not manually copying field values over.
If you include the AutoMapper NuGet package then you'd need to have the following in your startup somewhere to configure it for your classes:
Mapper.Initialize(cfg => cfg.CreateMap<CompleteModel, ViewModel>());
You could then do something like the following:
var results = await _context.CompleteModel.ToListAsync();
var viewModelResults = results.Select(Mapper.Map<ViewModel>).ToList();
There are a lot of configuration options for the package so do take a look at the documentation to see if it suits your needs and determine the best way to use it if it does.
In my view this is one of the weaknesses of over abstraction and layering. The VM contains the data that is valuable to your application within the context of use (screen, process etc). The data model contains all the data that could be stored that might be relevant. At some point you need to match the two.
Use EF Projection to fetch only the data you need from the database into projected data model classes (using the EF POCO layer to define the query, but not to store the resultant data).
Map the projected classes onto your VM, if there is a naieve mapping, using Automapper or similar. However unless you are just writing CRUD screens a simple field by field mapping is of little value; the data you fetch from your data store via EF is in its raw, probably relational form. The data required by your VM is probably not going to fit that form very neatly (again, unless you are doing a simple CRUD form), so you are going to need to add some value by coding the relationship between the data store and the View Model.
I think concentrating on the count of lines of code would lead to the wrong approach. I think you can look at that code and ask "is it adding any value". If you can delegate the task to Automapper, then great; but your VM isn't really pulling its weight other than adding some validation annotation if you can consistently delegate the task of data model to VM data copying.
I am new to IoC and Repository Pattern. I was able to do some test project and it works. But, I am not so sure if what I implemented is a good practice. The test project I have created have all the repositories in place as well as a working interface with a dummy data. But what I want is that my project should not be able to know the concrete types of my models because the initial version should be implemented using MSSQL, and the second version would be a mix of MSSQL and NoSQL(for reads and logging). The models might have different properties or structures from MSSQL to NoSQL (or whatever i might use in the future)
So I tried to create an interface for each model:
public interface ISearchResult
{
string Id { get; set; }
string Name { get; set; }
string Description { get; set; }
string Url { get; set; }
}
And here's the repository:
public interface ISearchRepository<T> where T: class, ISearchResult
{
IEnumerable<T> Search<T>(string keyword, IEnumerable<string> regions, IEnumerable<string> industries,IEnumerable<string> countries, IEnumerable<string> cities, int offset);
}
And here's the service:
public interface ISearchService
{
IEnumerable<T> Search<T>(string keyword, IEnumerable<string> regions, IEnumerable<string> industries,IEnumerable<string> countries, IEnumerable<string> cities, int offset);
}
Because I want to have a working GUI even without MSSQL or NoSQL entities, I have created a View Model that inherited the ISearchResult:
public class SearchResultViewModel : ISearchResult
{
[Display(Name="Reference Id")]
public string Id { get; set; }
[Display(Name = "Company")]
public string Name { get; set; }
[Display(Name = "Description")]
public string Description { get; set; }
[Display(Name = "Website")]
public string Url { get; set; }
}
And here's how it looks on my controller:
[SearchQueryFilter]
[GeoTargetFilter]
public ActionResult Query(SearchQueryModel searchQuery)
{
searchQuery.Results = this._searchService.Search<SearchResultViewModel>(searchQuery.Keyword,searchQuery.Region, new List<string>() { searchQuery.Industries }, new List<string>() { searchQuery.Countries}, new List<string>() {searchQuery.City}, searchQuery.Offset)
.ToList<ISearchResult>();
return View(searchQuery);
}
And my view would look like this:
#foreach (SearchResultViewModel result in Model.Results)
{
//code to display
}
My question is: Is it fine to use this approach? I don't want my web application to be dependent on my data entities so that's why I came up of making my view models inherit an interface. And because I was new to IoC and Repository Pattern and only have a test project, I don't know if my solution would be more of a problem in the long run.
Any advise is highly appreciated.
You shouldn't need to implement an interface in your view model in order to create a separation between your web application and your data entities. Your view model should belong to your web application and should itself be independent of your data entity.
So, instead of:
_searchService.Search<SearchResultViewModel>(x);
You should have, in your controller:
var result = _searchService.Search<SomeEntity>(x);
var model = new SearchResultsViewModel
{
Name = result.Name,
Desc = result.Desc,
Url = result.Url
};
return View(model);
The view model belongs to the web application and is responsible for containing the data passed from controller to view (and back) - it should have nothing to do with your service layer (or any other layer of your application).
SomeEntity is a concrete class, in the form of whatever your search service exposes. Your controller will consume this in the same way as any other application would and then compile a view model for passing to and from views. You might even find that SomeEntity is more or less identical to SearchResultsViewModel initially; however, they are still distinct entities as the requirements of the view might change independently of the search service.
I am new to MVC programming. In normal OOP, where I have my class, I would just initiliaze and load data from database. In MVC, we have modules, how do I load up records from it?
Here is my current code for type UserAcount:
[Table("UserAccount")]
public class UserAccount {
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public string userName { get; set; }
public string email { get; set; }
public int companyID { get; set; }
}
Say that I have an user with name "testUser", how do I initialize on this record and get it's information? How do I do this:
UserAccount user = new UserAccount("tesetUser");
How and where shoulud I use this?
user = user.SingleOrDefault(u => u.userName.ToLower() == User.Identity.Name.ToLower());
You need to read up on Entity Framework. This is the default ORM that MVC uses. Simply:
If you don't have a project context, yet, create one:
public class MyProjectContext : DbContext
{
public MyProjectContext()
: base("name=ConnectionStringNameHere")
{
}
}
Add your models to your project context:
public class MyProjectContext : DbContext
{
...
public DbSet<SomeModel> SomeModels { get; set; }
public DbSet<SomeOtherModel> SomeOtherModels { get; set; }
# etc.
}
Update your database using Package Manager Console (TOOLS > Library Package Manager > Package Manager Console):
> update-database
(hit ENTER after typing that)
Now, to use your context in your controllers:
public class MyAwesomeController : Controller
{
private MyProjectContext db = new MyProjectContext();
public ActionResult Index()
{
var someModels = db.SomeModels;
return View(someModels);
}
public ActionResult GetSomeModel(int id)
{
var someModel = db.SomeModels.Find(id);
return View(someModel);
}
# other actions
}
In the simplest case, you should do this logic in your controller, which will pass the data to the view. However, MVC is meant for UI separation of concerns, so theoretically you should be doing this in your domain layer, which is called from your controller.
Here is a decent article from Jeff Atwood, however I disagree that the controller is the brains of the application. It is more of the brains of the UI...but that depends on how complex your code is. Dont create a domain layer if it is stupidly simple
In the MVC model, Controllers are responsible for processing HTTP requests.
Typically you would load your entity (e.g. UserAccount) in a controller action.
If you want to edit / update an entity, typically you would map the relevant fields to a model that reflects the UserAccount. A separate model is suggested because the needs of the UI are often somewhat different than the needs of the entity model. Having separate classes for each concern avoids polluting the entity model to satisfy the needs of the view.
I am learning MVC 3 and I have not found people using some logic codes inside a property of a data model class.
They do the data model class as follows (for example):
public class Customer
{
public int CustomerId {get;set;}
//other properties without any logic code.
}
Is it ok to have logic codes inside a property as follows?
public class Customer
{
private int customerId;
public int CustomerId {
get{return customerId;}
set
{
customerId=value;
// some logic codes go here.
}
}
//other properties go here.
}
Edit 1:
This is my real scenario:
Child table data model:
namespace MvcApplication1.Models
{
public class Choice
{
public int ChoiceId { get; set; }
public string Description { get; set; }
public bool IsCorrect { get; set; }
public QuizItem QuizItem { get; set; }
}
}
Parent table data model:
namespace MvcApplication1.Models
{
public class QuizItem
{
public int QuizItemId { get; set; }
public string Question { get; set; }
private IEnumerable<Choice> choices;
public IEnumerable<Choice> Choices
{
get { return choices; }
set
{
choices = value;
foreach (var x in choices)
x.QuizItem = this;
}
}
}
}
Consumer:
namespace MvcApplication1.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
var data = new List<QuizItem>{
new QuizItem
{
QuizItemId = 1,
Question = "What color is your hair?",
Choices = new Choice[]{
new Choice{ ChoiceId=1, Description="Black.", IsCorrect=true},
new Choice{ ChoiceId=2, Description="Red.", IsCorrect=false},
new Choice{ ChoiceId=3, Description="Yellow.", IsCorrect=false}
}
},
new QuizItem
{
QuizItemId = 2,
Question = "What color is your noze?",
Choices = new Choice[]{
new Choice{ChoiceId=1, Description="Pink.", IsCorrect=false},
new Choice{ChoiceId=2, Description="Maroon.", IsCorrect=true},
new Choice{ChoiceId=3, Description="Navy Blue.", IsCorrect=false}
}
}
};
return View(data);
}
}
}
This calls for a method. Two reasons why:
I don't recommend setters for Collections
Property Usage Guidelines - Setting a property for each item in collection every time property is set is expensive and should not be in a property. A method is preferred instead.
Code (that you have in your case) in setter causes enough side-effects to disqualify use of property
Setters for collection type properties - A discussion on StackOverflow regarding setters for collections.
I suggest following:
public class QuizItem
{
public int QuizItemId { get; set; }
public string Question { get; set; }
private IEnumerable<Choice> choices;
public IEnumerable<Choice> Choices
{
get { return choices; }
}
public void SetChoices(IEnumerable<Choice> choices)
{
foreach (var x in choices)
x.QuizItem = this;
this.choices = choices;
}
}
I think this logic you should implement in controller. However I always define POCO classes in my model and use ViewModel to implement such simple logic.
This is more of a realm of philosophical approach. As such it is up to a debate.
Today by far the most prevalent approach is to use strict layered approach of separation of concerns where "model" objects are only responsible for containing data and if you want to apply any sort of business logic on top of that, you need to implement that on a separate "business logic" layer, which handles application of such concerns as validation/vewrification of the integrity of data, mutation of data according to a business processes, etc.
Another approach is to use model layer to actually model (as in verb) the business of the target domain. In this case, the model acts as a direct definition of the business rules and should just as rich as rules of the business require it to be. (this approach has been taken to extreme by Naked Objects, that basically keeps data structures as well as business logic in the model and generates ORM, controller logic and views from the same model)
Generally the question of "how smart can/should be my model objects" is one to ask from the frameworks you use. Some frameworks simply don't care either way (ASP.NET MVC), others want you to never worry about coding this stuff, as long as you provide enough metadata so that they can do their job for you (NHibernate, Entity Framework). Others yet encourage you to express all your business rules and logic in the domain object model (e.g. Naked Objects)
In my opinion, a data model should be doing logic related to data (value) as in "is this value a valid data to...?". Also when doing hidden logic like in this case "attaching a parent", naming the method to just "set" is also wrong.
A sample of a more complex data model:
https://learn.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-a-more-complex-data-model-for-an-asp-net-mvc-application