Creating new repositories with each controller - asp.net-mvc

I've been reading up on Dependency Incection, UnitOfWork and IRepository patterns, and I intend to implement them all as I go along. But it's all a lot to take in at once. Right now I just want to make sure about some basic things, and that I'm not missing anything crucial that could impact my application.
The application is rather small and there will be no more than 10 simultaneous users at any given point.
The AdressRegDataContext is the dbml generated (using Visual Studio Add -> Linq to SQL classes).
My question concern the adding of the second controller below:
Are there any problems creating a new repository in each controller like this?
To me it feels like two users would have two different contexts if they are using the application at the same time. Or do the datacontext handle that for me? A singleton repository makes sense theoretically, but I've read that that's a big nono so I won't do that.
I have a repository that I use:
Repository
namespace AdressReg.Models
{
public class AdressRegRepository
{
private AdressRegDataContext db = new AdressRegDataContext();
// Return person by id
public Person GetPerson(int id)
{
return db.Persons.SingleOrDefault(p => p.id == id);
}
// Return student by id
public Student GetStudent(int id)
{
return db.Students.SingleOrDefault(s => s.id == id);
}
}
}
So far I've only been using the one controller:
HomeController
namespace AdressReg.Controllers
{
public class HomeController : Controller
{
AdressRegRepository repository = new AdressRegRepository();
// GET: /Home/Person
public ActionResult Person(int id)
{
PersonView view = new PersonView();
view.person = repository.GetPerson(id);
return View(view);
}
}
}
But I was planning on adding another:
EducationController
namespace AdressReg.Controllers
{
public class EducationController: Controller
{
AdressRegRepository repository = new AdressRegRepository();
// GET: /Education/Student
public ActionResult Student(int id)
{
StudentView view = new StudentView();
view.student = repository.GetStudent(id);
return View(view);
}
}
}

Yes they are. First of all that's not a 'true' repository, that is a useless abstraction on top of EF, you can ditch it. A repository should return busines or app objects not EF entities. For querying purposes it should return at least some bits (if not all ) of the view model. So, it should return a PersonView or a StudentView. These are guideliness not the absolute truth or rules, but you really need to be aware of the purpose of a design pattern, in this case the Repository. And your code shows you haven't understood it yet.
In your app, the repo doesn't do anything useful, so use the ORM directly, it's much simpler.
Your controllers are tightly coupled to a specific concrete repository. The point is you should define an abstraction and pass that as a dependency in the constructor. Something like
// a better name is needed, this would be a query repository
public interface IAddressesRegRepository
{
StudentView Get(int it);
}
public class MyController:Controller
{
IAddressesRegRepository _repo;
public MyController(IAddressesRegRepository repo)
{
_repo=repo;
}
public ActionResult Student(int id)
{
StudentView view = _repo.GetStudent(id);
return View(view);
}
}
As you see, the controller now depends on an abstraction, the DI Container will inject a concrete implementation when the controller is created. It will allow you to mock repositories and to have multiple implementations. Same approach is for everything you want to use in the controller.
About repositories, I do prefer to have different business/ query repositories (though nowadays I'm using query handlers) i.e I don't put querying behaviour on a domain repository unless it's needed by the business layer itself.
For strictly querying, it's much straight forward to use EF or if your queries are ugly or want to change implementation later, use a query object/ repository/service/handler (call it however you want) that will construct the view model from persistence. The point is to keep the persistence details (ORM, EF Entites) in the DAL, your UI shouldn't know about them. In your example, the UI knows about EF entites.
Once again, what I've said are guidelines, when you get more experienced you'll know when to bend (break) them without nasty side effects.

Related

Entity framework 6 providing repositories and UoW out of the box

But how do you use it?
I have a Code First project set up, and trying out some stuff with this new EF6. Reading all kinds of posts/blogs from at least 2 years old about EF4/5. But nothing whatsoever about EF6.
Let's say I have these entities:
public DbSet<Person> Persons { get; set; }
public DbSet<Order> Orders { get; set; }
public DbSet<Invoice> Invoices { get; set; }
Do I still need to create repositories for each entity? Or would a class suffice with some methods to do some custom calculations aside from CRUD?
I know that this line:
kernel.Bind<MyDbContext>().ToSelf().InRequestScope();
Would suffice for DI, and that it will inject via constructor to upper layer classes where applicable.
The project has a class library and a web project asp.net-mvc. Where the class lib project contains my entities and has Migrations enabled.
Any light on this matter is really appreciated.
I've added a Repository layer on top of EF (which utilizes both Repository and UoW patterns inherently in its construction) in a couple of projects, and I've done that with one class that utilizes generics so that I only needed one file for all of my entities. You can decide if you want to do it or not, but I've found it useful in my projects.
My repositories have typically started out like what I've shown below, following up with more extension methods if/when I come across a need for them (obviously I'm not showing all of them, that's up for you to decide how to implement your repository).
public class Repository<T> : IRepository<T> where T : class
{
protected IDbContext Context;
protected DbSet<T> DbSet { get { return Context.Set<T>(); } }
public Repository(IDbContext context = null)
{
Context = context ?? new DbContext();
}
public void Add(T newRecord)
{
DbSet.Add(newRecord);
}
public void Update(T record)
{
var entry = Context.Entry(record);
DbSet.Attach(record);
entry.State = EntityState.Modified;
}
public void Remove(T record)
{
Context.Entry(record).State = EntityState.Deleted;
DbSet.Remove(record);
}
public IQueryable<T> Where(Expression<Func<T, bool>> predicate)
{
return DbSet.Where(predicate);
}
public bool Contains(Expression<Func<T, bool>> predicate)
{
return DbSet.Count(predicate) > 0;
}
public int Count(Expression<Func<T, bool>> predicate)
{
return DbSet.Count(predicate);
}
public int Save()
{
return Context.SaveChanges();
}
}
I've used repositories for 2 main reasons:
Unit testing. Doing this pattern allows me to fake the underlying data without having to have bad data in my database. All I need to do is simply create another implementation of IRepository that uses an in-memory list as its data source, and I'm all set for my pages to query that repository.
Extensibility. A fair number of times I've put in some methods into my repository because I found myself constantly doing the same logic with queries in my controllers. This has been extremely useful, especially since your client-side code doesn't need to know how it's doing it, just that it is doing it (which will make it easier if you need to change the logic of one file vs. multiple files).
This not all of it, obviously, but that should be enough for this answer. If you want to know more on this topic, I did write a blog post on it that you can find here.
Good luck on whatever you decide to do.
Entity Framework in itself can be considered a Repository. It facilitates work with data, in this case a database. This is all that a Repository does.
If you want to build another Repository on top of what EF provides, it is completely up to you - or to your business rules.
Many complex projects uses 2-3 layers of repositories with web services between. The performance is lower but you gain on other plans like security, resilience, separation of concerts, etc.
Your company might decide that it's in their best interest to never access data directly from front-end projects. They might force you to build a separate web-service project, which will be accessible only from localhost. So you will end up having EF as Repository in the webservice project. On the front-end side you will obviously need to build another Repository which will work with the web-service.
It also depends a lot of your project. If it's a small project it really it's overkill to build a second Repository on top of EF. But then again, read above. Nowadays security matters a lot more than performance.
To be politically correct I'm including the comment made by Wiktor Zychla:
"DbSet is a repository and DbContext is a Unit of Work. "Entity Framework is a Repository" could lead to unnecessary confusion."

Ninject factory management

I'm using Ninject.Extensions.Factory to control the lifecycle of the repository layer. I want to have a single point of reference from which I can get a reference to all repositories and have them lazily available. Ninject Factory approach seems like a good solution but I'm not too sure about my solution:
public class PublicUow : IPublicUow
{
private readonly IPublicRepositoriesFactory _publicRepositoriesFactory;
public PublicUow(IPublicRepositoriesFactory publicRepositoriesFactory)
{
_publicRepositoriesFactory = publicRepositoriesFactory;
}
public IContentRepository ContentRepository { get { return _publicRepositoriesFactory.ContentRepository; } }
public ICategoryRepository CategoryRepository { get { return publicRepositoriesFactory.CategoryRepository; } }
}
The problem lies in the PublicRepositories class.
public class PublicRepositoriesFactory : IPublicRepositoriesFactory
{
private readonly IContentRepositoryFactory _contentRepositoryFactory;
private readonly ICategoryRepositoryFactory _categoryRepositoryFactory;
public PublicRepositoriesFactory(IContentRepositoryFactory contentRepositoryFactory, ICategoryRepositoryFactory categoryRepositoryFactory)
{
_contentRepositoryFactory = contentRepositoryFactory;
_categoryRepositoryFactory = categoryRepositoryFactory;
}
public IContentRepository ContentRepository { get { return _contentRepositoryFactory.CreateContentRepository(); } }
public ICategoryRepository CategoryRepository { get { return _categoryRepositoryFactory.CreateCategoryRepository(); } }
}
I'm worried that this will become hard to manage as the number of repositories increases, this class might at some point need to have around 20-30 constructor arguments with the current implementation.
Is there an approach I can take to reduce the number of ctr arguments, like passing an array/dictionary of interfaces or something similar?
I've thought about using property injection in this scenario but most articles suggest avoiding property injection in general.
Is there maybe a more general pattern that would make this easier to manage?
Is this in general a good approach?
It has become rather common practice to use a repository interface like
public interface IRepository
{
T LoadById<T>(Guid id);
void Save<T>(T entity);
....
}
instead of a plethora of specific repositories like IContentRepository, ICategoryRepository,..
specific repositories are only ever useful in case of having specific logic to the entity type and an operation, for example verifying that it's valid. But such operations are rather an "aspect" or a cut-through-concern which you should model as such. Managing/doing validation on save should not be implemented x-times but only once. The only thing you should specifically implement are the exact validation rules (DRY). But these should be implemented in separate classes and used by composition, not inheritance.
Also, for stuff like retrieving an entity or multiple entities "based on a use case", you should use specific query classes, and not put methods on a repository interface (SRP, SOC). An example would be GetProductsByOrder(Guid orderId). This should be neither on the Products nor the Order Repository but rather in a separate class itself.
Taking things a step further, it does not seem a good idea to use a factory to late create all repositories. Why?
makes software more complex (thus harder to maintain and extend)
usually negligible performance gain
deteriorates testability
also see Mark Seeman's blog post Service Locator is an anti pattern, where he's also talking about the disadvantages of late-creation vs. the composition of the entire object graph in one go.
I'm not trying to say that you should never use factory/lazy, but only when you've got a really good reason to :)
Example of a query
I'm not very familiar with EntityFramework. I know NHibernate a whole lot better, so behold.
public class GetParentCategoriesQuery : IGetParentCategoriesQuery
{
private readonly EntityFrameworkContext context;
public GetParentCategories(EntityFrameworkContext context)
{
this.context = context;
}
public IEnumerable<Category> GetParents(Category child)
{
return this.context.Categories.Where(x => x.Children.Contains(child));
}
}
So basically the only thing you change is extracting the GetParentCategoriesQuery into it's own class. The DbContext instance must be shared with the other query and repository instances. For web projects, this is done by binding the DbContext .InRequestScope(). For other applications you may need to use another machanism.
The usage of the query would be quite simple:
public class CategoryController
{
private readonly IRepository repository;
private readonly IGetParentCategoriesQuery getParentCategoriesQuery;
public CategoryController(
IRepository repository,
IGetParentCategoriesQuery getParentCategoriesQuery)
{
this.repository = repository;
this.getParentCategoriesQuery = getParentCategoriesQuery;
}
public void Process(Guid categoryId)
{
Category category = this.repository.LoadById(categoryId);
IEnumerable<Category> parentCategories =
this.getParentCategoriesQuery(category);
// so some stuff...
}
}
An alternative to the scoping is to have the repository instantiate the the query type and pass the DbContext to the query instance (this can be done using the factory extensions):
public TQuery CreateQuery<TQuery>()
{
return this.queryFactory.Create<TQuery>(this.context);
}
which would be used like:
IEnumerable<Category> parents = repository
.CreateQuery<GetParentCategoriesQuery>()
.GetParents(someCategory);
But please note that this alternative will again only late-create the query and thus result in less testability (binding issues may be remain undetected for longer).
The GetParentCategoriesQuery is part of the repository layer, but not part of the repository class.

Difference between Repository and Service Layer?

In OOP Design Patterns, what is the difference between the Repository Pattern and a Service Layer?
I am working on an ASP.NET MVC 3 app, and am trying to understand these design patterns, but my brain is just not getting it...yet!!
Repository Layer gives you additional level of abstraction over data access. Instead of writing
var context = new DatabaseContext();
return CreateObjectQuery<Type>().Where(t => t.ID == param).First();
to get a single item from database, you use repository interface
public interface IRepository<T>
{
IQueryable<T> List();
bool Create(T item);
bool Delete(int id);
T Get(int id);
bool SaveChanges();
}
and call Get(id). Repository layer exposes basic CRUD operations.
Service layer exposes business logic, which uses repository. Example service could look like:
public interface IUserService
{
User GetByUserName(string userName);
string GetUserNameByEmail(string email);
bool EditBasicUserData(User user);
User GetUserByID(int id);
bool DeleteUser(int id);
IQueryable<User> ListUsers();
bool ChangePassword(string userName, string newPassword);
bool SendPasswordReminder(string userName);
bool RegisterNewUser(RegisterNewUserModel model);
}
While List() method of repository returns all users, ListUsers() of IUserService could return only ones, user has access to.
In ASP.NET MVC + EF + SQL SERVER, I have this flow of communication:
Views <- Controllers -> Service layer -> Repository layer -> EF -> SQL Server
Service layer -> Repository layer -> EF This part operates on models.
Views <- Controllers -> Service layer This part operates on view models.
EDIT:
Example of flow for /Orders/ByClient/5 (we want to see order for specific client):
public class OrderController
{
private IOrderService _orderService;
public OrderController(IOrderService orderService)
{
_orderService = orderService; // injected by IOC container
}
public ActionResult ByClient(int id)
{
var model = _orderService.GetByClient(id);
return View(model);
}
}
This is interface for order service:
public interface IOrderService
{
OrdersByClientViewModel GetByClient(int id);
}
This interface returns view model:
public class OrdersByClientViewModel
{
CientViewModel Client { get; set; } //instead of ClientView, in simple project EF Client class could be used
IEnumerable<OrderViewModel> Orders { get; set; }
}
This is interface implementation. It uses model classes and repository to create view model:
public class OrderService : IOrderService
{
IRepository<Client> _clientRepository;
public OrderService(IRepository<Client> clientRepository)
{
_clientRepository = clientRepository; //injected
}
public OrdersByClientViewModel GetByClient(int id)
{
return _clientRepository.Get(id).Select(c =>
new OrdersByClientViewModel
{
Cient = new ClientViewModel { ...init with values from c...}
Orders = c.Orders.Select(o => new OrderViewModel { ...init with values from o...}
}
);
}
}
As Carnotaurus said the repository is responsible for mapping your data from the storage format to you business objects. It should handle both how to read and write data(delete, update too) from and to the storage.
The purpose of service layer on the other hand is to encapsulate business logic into a single place to promote code reuse and separations of concerns. What this typically means for me in practice when building Asp.net MVC sites is that I have this structure
[Controller] calls [Service(s)] who calls [repository(ies)]
One principle I have found useful is to keep logic to a minimum in controllers and repositories.
In controllers it is because it helps keeping me DRY. It's very common that I need to use the same filtering or logic somewhere else and if I placed it in the controller I can't reuse it.
In repositories it is because I want to be able to replace my storage(or ORM) when something better comes along. And if I have logic in the repository I need to rewrite this logic when I change the repository. If my repository only returns IQueryable and the service does the filtering on the other hand, I will only need to replace the mappings.
For example I recently replaced several of my Linq-To-Sql repositories with EF4 and those where I had stayed true to this principle could replaced in a matter of minutes. Where I had some logic it was a matter of hours instead.
The accepted answer (and upvoted hundreds of time) has a major flaw. I wanted to point this out in the comment but it will just get buried down there in 30 something comments so pointing out here.
I took over an enterprise application which was built that way and my initial reaction was WTH? ViewModels in service layer? I did not want to change the convention because years of development had gone into it so I continued with returning ViewModels. Boy it turned into a nightmare when we started using WPF. We (the team of devs) were always saying: which ViewModel? The real one (the one we wrote for the WPF) or the services one? They were written for a web application and even had IsReadOnly flag to disable edit in the UI. Major, major flaw and all because of one word: ViewModel!!
Before you make the same mistake, here are some more reasons in addition to my story above:
Returning a ViewModel from the service layer is a huge no no. That's like saying:
If you want to use these services you better be using MVVM and here is the ViewModel you need to use. Ouch!
The services are making the assumption they will be displayed in a UI somewhere. What if it is used by a non UI application such as web services or windows services?
That is not even a real ViewModel. A real ViewModel has observability, commands etc. That is just a POCO with a bad name. (See my story above for why names matter.)
The consuming application better be a presentation layer (ViewModels are used by this layer) and it better understand C#. Another Ouch!
Please, don't do that!
Repository layer is implemented to access the database and helps to extend the CRUD operations on the database. Whereas a service layer consists of the business logic of the application and may use the repository layer to implement certain logic involving the database. In an application, it is better to have a separate repository layer and service layer. Having separate repository and service layers make the code more modular and decouple the database from business logic.
Usually a repository is used as scaffolding to populate your entities - a service layer would go out and source a request. It is likely that you would put a repository under your service layer.

MVC + EF4 + POCO - How to go about storing the Entity Context?

I'm making a start on an MVC project, having gone through the MvcMusicStore tutorial. I'm trying to get my head around how the POCO-generated data/entity context is intended to be stored.
In the samples, the controller generates a copy of the entity context, and all operations complete there:
MusicStoreEntities storeDB = new MusicStoreEntities();
//
// GET: /Store/
public ActionResult Index()
{
// Retrieve list of Genres from database
var genres = from genre in storeDB.Genres
select genre.Name;
[...]
If I'm to split my solution into layers, what is the standard practice (or key options) for retaining the context? Do I generate it in the controller, and pass it to the repository, or is it possible for the repository to keep a general-use copy?
I understand that the the above would be necessary to use the Unit of Work pattern.
My layers are:
Data (edmx file)
Entities (Generated from POCO)
Repository
Mvc web app
My other questions:
- What is the overhead of generating the context?
- As there is no .Close(), and it doesn't implement IDisposable, is the ObjectContext behind it generating individual connections, connection pooling, sharing a single instance?
- Is it possible to lock an ObjectContext if it's passed around between layers / operations too much?
Thanks in advance.
I don't want to go into too much detail/code here, so i'll just mention some points:
Your controller can work with multiple repositories
There should be one repository per aggregate root
Controller work amongst multiple repositories are made possible by Unit of Work
Use a DI container to handle lifetime management of Unit of Work (which is actually the context)
Do not use singletons for the Context, let the DI container instantiate/dispose of the context per HTTP request
I create a single repository for each controller and put my context in there. The rules I follow are that the repository handles anything that I might want to mock (not really the definition of repository, but it works for me). The repository can call other repositories if necessary, but the controller shouldn't have to know about it. The Context is an instance property of the repository and is created on demand (I haven't taken the leap into IOC yet). If the repository calls another repository, it passes the Context instance.
It looks a little like this...
public class MyController : Controller
{
public IMyControllerRepository Repository { get; set; }
public ActionResult MyAction(int id)
{
var model = Repository.GetMyModel(id);
return View(model);
}
}
public class MyControllerRepository : IMyControllerRepository
{
public MyContext Context { get; set; };
public MyModel GetMyModel(int id)
{
return (from m in Context.MyModels
where m.ID = id
select m).SingleOrDefault();
}
}

Fetching data within an ASP.NET MVC ViewModel class?

For those that create ViewModels (for use by typed views) in ASP.NET MVC, do you prefer to fetch the data from a service/repository from within the ViewModel, or the controller classes?
For example, we started by having ViewModels essentially being DTOs and allowing our Controllers to fetch the data (grossly oversimplified example assumes that the user can only change employee name):
public class EmployeeViewModel
{
public String Name; //posted back
public int Num; //posted back
public IEnumerable<Dependent> Dependents; //static
public IEnumerable<Spouse> Spouses; //static
}
public class EmployeeController()
{
...
public ActionResult Employee(int empNum)
{
Models.EmployeeViewModel model = new Models.EmployeeViewModel();
model.Name = _empSvc.FetchEmployee(empNum).Name;
model.Num = empNum;
model.Dependents = _peopleSvc.FetchDependentsForView(empNum);
model.Spouses = _peopleSvc.FetchDependentsForView(empNum);
return View(model);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Employee(Models.EmployeeViewModel model)
{
if (!_empSvc.ValidateAndSaveName(model.Num, model.Name))
{
model.Dependents = _peopleSvc.FetchDependentsForView(model.Num);
model.Spouses = _peopleSvc.FetchDependentsForView(model.Num);
return View(model);
}
this.RedirectToAction(c => c.Index());
}
}
This all seemed fine until we started creating large views (40+ fields) with many drop downs and such. Since the screens would have a GET and POST action (with POST returning a view if there was a validation error), we'd be duplicating code and making ViewModels larger than they probably should be.
I'm thinking the alternative would be to Fetch the data via the Service within the ViewModel. My concern is that we'd then have some data populated from the ViewModel and some from the Controller (e.g. in the example above, Name would be populated from the Controller since it is a posted value, while Dependents and Spouses would be populated via some type of GetStaticData() function in the ViewModel).
Thoughts?
I encountered the same issue. I started creating classes for each action when the code got too big for the action methods. Yes you will have some data retrieval in classes and some in the controller methods. The alternative is to have all the data retrieval in classes, but half the classes you won't really need, they will have been created for consistency sake or have all the data retrieval in the controller methods, but again, some of those methods will be too complex and needed to have been abstracted into classes... so pick your poison. I would rather have a little inconsistency and have the right solution for the job.
As for putting behavior into the ViewModel, I don't, the point of the ViewModel is to be a thin class for setting and extracting values from the View.
There have been cases where I've put conversion methods in the ViewModel. For instance I need to convert the ViewModel to the corresponding entity or I need to load the ViewModel with data from the Entity.
To answer your question, I prefer to retrieve data from with in the controller/action methods.
Typically with DropDowns, I create a dropdown service. DropDowns tend to be the same data that spans views. With the dropdowns in a service I can use them on other views and/or Cache them.
Depending on the layout, 40 plus fields could create a cluttered view. Depending the type of data, I would try to span that many fields across multiple views with some sort of tabbed or wizard interface.
There's more than that ;-) You can fetch in model binder or action filter. For the second option, check Jimmy Bogard's blog somewhere around here. I personally do it in model binders. I use ViewModel like this: My custom ASP.NET MVC entity binding: is it a good solution?. It is processed by my custom model binder:
public object BindModel(ControllerContext c, BindingContext b)
{
var id = b.ValueProvider[b.ModelName]; // don't remember exact syntax
var repository = ServiceLocator.GetInstance(GetRepositoryType(b.ModelType));
var obj = repository.Get(id);
if (obj == null)
b.ModelState.AddModelError(b.ModelName, "Not found in database");
return obj;
}
public ActionResult Action(EntityViewModel<Order> order)
{
if (!ModelState.IsValid)
...;
}
You can also see an example of model binder doing repository access in S#arp Architecture.
As for static data in view models, I'm still exploring approaches. For example, you can have your view models remember the entities instead of lists, and
public class MyViewModel
{
public MyViewModel(Order order, IEmployeesSvc _svc)
{
}
public IList<Employee> GetEmployeesList()
{
return _svc.GetEmployeesFor(order.Number);
}
}
You decide how you inject _svc into ViewModel, but it's basically the same as you do for controller. Just beware that ViewModel is also created by MVC via parameterless constructor, so you either use ServiceLocator or extend MVC for ViewModel creation - for example, inside your custom model binder. Or you can use Jimmy Bogard's approach with AutoMapper which does also support IoC containers.
The common approach here is that whenever I see repetative code, I look to eliminate it. 100 controller actions doing domain-viewmodel marshalling plus repository lookup is a bad case. Single model binder doing it in generic way is a good one.
I wouldn't be fetching data from the database in your ViewModel. The ViewModel exists to promote separation of concerns (between your View and your Model). Tangling up persistance logic in there kind of defeats the purpose.
Luckily, the ASP.NET MVC framework gives us more integration points, specifically the ModelBinder.
I've got an implementation of a generic ModelBinder pulling information from the service layer at:-
http://www.iaingalloway.com/going-further-a-generic-servicelayer-modelbinder
It doesn't use a ViewModel, but that's easily fixed. It's by no means the only implementation. For a real-world project, you're probably better off with a less generic, more customised solution.
If you're diligent, your GET methods don't even need to know that the service layer exists.
The solution probably looks something like:-
Controller action method:-
public ActionResult Details(MyTypeIndexViewModel model)
{
if( ModelState.IsValid )
{
return View(model);
}
else
{
// Handle the case where the ModelState is invalid
// usually because they've requested MyType/Details/x
// and there's no matching MyType in the repository
// e.g. return RedirectToAction("Index")
}
}
ModelBinder:-
public object BindModel
(
ControllerContext controllerContext,
BindingContext bindingContext
)
{
// Get the Primary Key from the requestValueProvider.
// e.g. bindingContext.ValueProvider["id"]
int id = ...;
// Get an instance of your service layer via your
// favourite dependancy injection framework.
// Or grab the controller's copy e.g.
// (controllerContext.Controller as MyController).Service
IMyTypeService service = ...;
MyType myType = service.GetMyTypeById(id)
if (myType == null)
{
// handle the case where the PK has no matching MyType in the repository
// e.g. bindingContext.ModelState.AddModelError(...)
}
MyTypeIndexViewModel model = new MyTypeIndexViewModel(myType);
// If you've got more repository calls to make
// (e.g. populating extra fields on the model)
// you can do that here.
return model;
}
ViewModel:-
public class MyTypeIndexViewModel
{
public MyTypeIndexViewModel(MyType source)
{
// Bind all the properties of the ViewModel in here, or better
// inherit from e.g. MyTypeViewModel, bind all the properties
// shared between views in there and chain up base(source)
}
}
Build your service layer, and register your ModelBinder as normal.
Here's another solution: http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/06/29/how-we-do-mvc-view-models.aspx
Main points there:
Mapping is done by a mediator - in this case it is AutoMapper but it can be your own class (though more to code). This keeps both Domain and ViewModel concentrated on the domain/presentation logic. The mediator (mapper) will contain (mostly automatic) logic for mapping, including injected services.
Mapping is applied automatically, all you do is tell the action filter the source/destination types - very clean.
(Seems to be important for you) AutoMapper supports nested mappings/types, so you can have your ViewModel combined of several independent view models, so that your "screen DTO" is not messy.
Like in this model:
public class WholeViewModel
{
public Part1ViewModel ModelPart1 { get; set; }
public Part2ViewModel ModelPart2 { get; set; }
}
you re-use mappings for specific parts of your View, and you don't write any new line of code, since there're already mappings for the partial view models.
If you don't want AutoMapper, you have have IViewModelMapper interfaces, and then your IoC container will help your action filter to find appropriate
container.Resolve(typeof(IViewModelMapper<>).MakeGenericType(mysourcetype, mydesttype))
and it will also provide any required external services to that mapper (this is possible with AutoMapper, too). But of course AutoMapper can do recursions and anyway, why write additional AutoMapper ;-)
Consider passing your services into the custom ViewModel on its constructor (ala Dependency Injection). That removes the model population code from your controller and allows it to focus on controlling the logical flow of the application. Custom ViewModels are an ideal place to abstract the preparation of things like SelectLists that your droplists will depend on.
Lots of code in the controller for things like retrieving data isn't considered a best practice. The controller's primary responsibility is to "control" the flow of the application.
Submitting this one late... Bounty is almost over. But...
Another mapper to look at is Automapper: http://www.codeplex.com/AutoMapper
And overview on how to use it: http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/01/22/automapper-the-object-object-mapper.aspx
I really like it's syntax.
// place this somewhere in your globals, or base controller constructor
Mapper.CreateMap<Employee, EmployeeViewModel>();
Now, in your controller, I would use multiple viewmodels. This enforces DRY by allowing you to reuse those viewmodels elsewhere in your application. I would not bind them all to 1 viewmodel. I would refactor to something like:
public class EmployeeController()
{
private IEmployeeService _empSvc;
private ISpouseService _peopleSvc;
public EmployeeController(
IEmployeeService empSvc, ISpouseService peopleSvc)
{
// D.I. hard at work! Auto-wiring up our services. :)
_empSvc = empSvc;
_peopleSvc = peopleSvc;
// setup all ViewModels here that the controller would use
Mapper.CreateMap<Employee, EmployeeViewModel>();
Mapper.CreateMap<Spouse, SpouseViewModel>();
}
public ActionResult Employee(int empNum)
{
// really should have some validation here that reaches into the domain
//
var employeeViewModel =
Mapper.Map<Employee, EmployeeViewModel>(
_empSvc.FetchEmployee(empNum)
);
var spouseViewModel =
Mapper.Map<Spouses, SpousesViewModel>(
_peopleSvc.FetchSpouseByEmployeeID(empNum)
);
employeeViewModel.SpouseViewModel = spouseViewModel;
return View(employeeViewModel);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Employee(int id, FormCollection values)
{
try
{
// always post to an ID, which is the employeeID
var employee = _empSvc.FetchEmployee(id);
// and bind using the built-in UpdateModel helpers.
// this will throw an exception if someone is posting something
// they shouldn't be posting. :)
UpdateModel(employee);
// save employee here
this.RedirectToAction(c => c.Index());
}
catch
{
// check your domain model for any errors.
// check for any other type of exception.
// fail back to the employee screen
RedirectToAction(c => c.Employee(id));
}
}
}
I generally try to stay away from saving multiple entities on a controller action. Instead, I would refactor the employee domain object to have AddSpouse() and SaveSpouse() methods, that would take an object of Spouse. This concept is known as AggregateRoots, controlling all dependancies from the root - which is the Employee() object. But, that is just me.

Resources