UoW & Repository + Service Layer - asp.net-mvc

I'm using the following T4 to create my Repository & UoW:
http://blogs.microsoft.co.il/blogs/gilf/archive/2010/07/05/repository-and-unit-of-work-t4-template-for-entity-framework.aspx
Now I'm trying to add a Service Layer. I was able to accomplish something like this:
public ActionResult Index()
{
using (DataEntities context = new DataEntities())
{
UnitOfWork uow = new UnitOfWork(context);
//Service
ClientService cli = new ClientService(uow);
var col = cli.getActive();
//Map results to ViewModel
var list = AutoMapper.Mapper.Map<IEnumerable<Client>, IEnumerable<ClientListViewModel>>(col);
return View(list);
}
}
This works fine, but...
Is architecturally correct to pass the UoW instance to the Service Layer?
(I'm using IUnitOfWork in its ctor)
I tried to move the context & UoW inside the service layer, but the context is not available when I try to map the results to ViewModel in the controller.
Thanks!

I would argue no it isn't. Then again, I'm not a huge fan of unit of work -- I feel like it knows too much. I would pass the necessary repository(ies) to the service you create. Typically, I end up with special "GetService" or "CreateService" but this might work for you... (I'm writing this freehand so it might not build)
Public class DoSomethingCoolService : IDoSomethingCoolService
{
private IRepository<SomethingINeed> _neededRepository;
public DoSomethingCoolService(connectionOrContext)
{
//setup
}
public DoSomethingCoolService(IRepository<SomethingINeed> neededRepository)
{
_neededRepository = neededRepository;
}
public List<SomethingINeed> ReturnWhatIWant()
{
_neededRepository.Where(x => x.WhatIWant = true);
}
}
Personally, I don't like this. I prefer something more like this ...
public interface IGetService<T>
{
//usual get suspects here
}
public class GetService<T> : IGetService<T>
{
private IRepository<T> _repository;
GetService(IRepository<T> repository)
//use repository to call gets
}
now for the complicated-ish stuff...
public interface IGetClientService : IGetService<Client>
{
List<Client> GetClientsForSomething(int someId);
}
public class GetClientService : GetService<Client>, IGetClientService
{
private IRepository<Client> _repository;
GetClientService(IRepository<Client> repository) : base(repository)
public List<Client> GetClientsForSomething(int someId)
{
//some crazy cool business logic stuff here you want to test!
}
}
Then inside my controller, I just have a dependency on the IGetClientService, and use it where necessary. Easy to test, easy to make another that isn't dependent on it.
Does this make any sense?

Related

Unit Testing a Controller - How Do I Handle the Connection String?

I can make it work, but I want to know what the best practice is and why. I have a Controller, a Model, and a Repository and now I want to Unit Test the Controller. I am just writing a simple test to ensure that the correct view is being returned.
This is my method in the controller:
public ActionResult Selections(SelectionsViewModel model)
{
for (int i = 0; i < model.Sends.Count; i++)
{
Send send = new Send(new SendService(new Database().GetConnectionString()))
{
SendID = model.Sends[i].SendID,
Title = model.Sends[i].Title,
Subject = model.Sends[i].Subject,
SentDate = model.Sends[i].SentDate,
TimesViewed = model.Sends[i].TimesViewed,
Include = model.Sends[i].Include,
Exclude = model.Sends[i].Exclude
};
send.UpdateIncludeExclude();
}
return View(model);
}
Here is my GetConnectionString() method in the Database class that is being sent via my SendService constructor.
public string GetConnectionString()
{
return System.Configuration.ConfigurationManager.ConnectionStrings["DEVConnectionString"].ToString();
}
And lastly, my unit test:
[Test]
public void TestAssignmentSelections()
{
var obj = new AssignmentController();
var actResult = obj.Selections() as ViewResult;
NUnit.Framework.Assert.That(actResult.ViewName, Is.EqualTo("Selections"));
}
Now, my unit test fails, and I get why. My unit test project has no access to the web.config of the project I am testing where my connection string resides.
I've done some research, and apparently just adding a web.config to my unit test project and putting the connection string in there as well will make it work.. but that seems like a hack.
What's the best way to go about this? Is there another way to write my code to accommodate for this?
You want to make your controller unit testable ? Don't do this.
new SendService(
With this code,you are hardcoding your concrete service implementation & your data access code implementation. In your unit test, you should not be really accessing the data from your database. Instead you should be providing a mock data access implementation.
Here comes interfaces, you need to create an interface for your SendService.
public interface ISendService
{
void SomeMethod();
}
now your SendService will be a concrete implementation of this interface
public class SendService : ISendService
{
public void SomeMethod()
{
// Do something
}
}
Now update your controller to have a constructor where we will inject an implementation of ISendService.
public class YourController : Controller
{
private ISendService sendService;
public YourController(ISendService sendService)
{
this.sendService = sendService;
}
public ActionResult YourActionMethod()
{
// use this.sendService.SomeMethod();
}
}
And you may use some dependency injection frameworks to tell the MVC framework which implementation of the interface to use when the code runs. If you are using MVC6,It has an inbuilt dependency injection provider you can use. So go to your Startup class and in your ConfigureServices method, you can map an interface to a concrete implementation.
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<ISendService, SendService>();
}
}
If you are in a previous version of MVC, You may consider DI frameworks like Unity,Ninject etc. You can do the same approach for your Data access later / Service layers. ie: Create an interface for data access and inject that to your SendService.
public Interface IDataAccess
{
string GetName(int id);
}
and an implementation which uses your specific data access code/ORM
public class EFDataAccess : IDataAccess
{
public string GetName(int id)
{
// return a string from db using EF
}
}
So now your Service class will be
public class SendService : ISendService
{
private IDataAccess dataAccess;
public SendService(IDataAccess dataAccess)
{
this.dataAccess=dataAccess;
}
// to do : Implement methods of your ISendService interface.
// you may use this.dataAccess in those methods as needed.
}
In your unit tests, you can create a mock implementation of your interfaces which returns static data instead of accessing the database.
For example, If you are using Moq mocking framework, you can do this.
var m = new Mock<IDataAccess>();
var m.Setup(s=>s.GetName(It.IsAny<int>())).Returns("Test");
var s = new SendService(m);
var result= s.SomeMethod();

Unit of Work pattern implementation

I am creating an application with ASP.NET MVC and Entity framework code first. I am using repository and unit of work pattern with influence of from following link.
http://www.asp.net/mvc/tutorials/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
Here I have question about the implementation of Unit Of Work in that link unit of work is implemented via directly writing entities in class itself like.
public class UnitOfWork : IDisposable
{
private SchoolContext context = new SchoolContext();
private GenericRepository<Department> departmentRepository;
public GenericRepository<Department> DepartmentRepository
{
get
{
if (this.departmentRepository == null)
{
this.departmentRepository = new GenericRepository<Department>(context);
}
return departmentRepository;
}
}
}
Do you think that implementation is good enough because every time I add/remove entities I need to change my Unit of work class. I believe that Unit of work should not be dependent on entities. Because in my application based on Client feedback we are going to frequently add/remove entities.
I may sound stupid but let me know your views on that.
The Unit of Work pattern is already implemented in Entity Framework.
The DbContext is your Unit of Work.
Each IDbSet is a Repository.
using (var context = new SchoolContext()) // instantiate our Unit of Work
{
var department = context.Departments.Find(id);
}
There are a few flavors of the UnitOfWorkPattern. The one you are describing is a show everything, there is a hide everything approach as well. In the hide approach the unit of work references the DbContext.SaveChanges() method and nothing else; sounds like what you want.
public YourContext : DbContext, IContext{}
public interface IUnitOfWork{
void Commit();
}
public UnitOfWork : IUnitOfWork{
private readonly IContext _context;
//IOC should always inject the same instance of this, register it accordingly
public UnitOfWork(IContext context){
_context = context;
}
void Commit(){
// try catch the validation exception if you want to return the validations this
// way if your confident you've already validated you can put a void here or
// return the intfrom save changes make sure you handle the disposing properly,
// not going into that here you also may be doing other stuff here, have multiple
// "contexts" to save in a single transaction or we have contextProcessors that
// do stuff based on items in the context
_context.SaveChanges();
}
}
This leaves the issue of how you get your repositories into the classes that need them if you are not taking them from the UnitOfWork. This is best handled by an IOC framework. Again here there are a couple options. Once is to register the UnitOfWork as a single instance per request and have it injected into your custom Repository class.
public interface IRepository<T>
{
IQueryable<T> Records();
//other methods go here
}
public Repository : IRepository<T>
{
private IContext _context;
// same instance of context injected into the unit of work, this why when you Commit
// everything will save, this can get tricky if you start adding Add, Update and stuff
// but EF does have the support needed.
public Repository(IContext context)
{
_context = context;
}
public Records()
{
return _context.Set<T>();
}
}
public class SomeService : ISomeService{
private readonly _myObjectRepository;
public SomeService(IRepository<MyObject> myObjectRepository){
_myObjectRepository = myObjectRepository;
}
}
Personally I consider the IDbSet an sufficient abstraction so I no longer create repositories. In
order to inject the IDbSets from the context though you need to register them as instances that you
extract from the context in your IOC setup. This can be complex and depending on your skills you
could find yourself in the situation where you have to register each IDbSet which I know you are trying to avoid.
What's nice about using the IDbSet is you have access to simple methods like Add and can avoid some of the more complex parts of working with Entity and DbEntity in a generic sense.
public class SomeService : ISomeService {
private readonly _myObjectSet;
// requires specialized IOC configurations because you have to pull this instance from
// the instance of the context, personally don't know how to do this with a single
// registration so this has the same problem as having to add each new repository to the
// unit of work. In this case each new Entity I add to the context requires I add an IOC
// registration for the type.
public SomeService(IDbSet<MyObject> myObjectSet){
_myObjectSet= myObjectSet;
}
}
Try passing the SchoolContext to the GenericRepository:
public GenericRepository<T>
{
private SchoolContext _context;
public GenericRepository(SchoolContext context)
{
_context = context;
}
public Get(int id)
{
return _context.Set<T>().Find(id);
}
}
And use:
using(var context = new SchoolContext())
{
var departmentRepository = new GenericRepository<Department>(context);
var department = departmentRepository.Get(1);
}

Dependency on a service layer with Ninject and MVC

I've got a problem with a bog standard three tier project using MVC that I'm trying to use Ninject with. I've got a MemberRepository:
public class MemberRepository : IMemberRepository{
public bool Save(Member member){
//saves member
}
}
I then have my Service Layer:
public class MemberService : IMemberService{
public bool Register(string email){
//Do Stuff & Populate Member Object
_repo.Save(member);
}
}
Given I'll be using Ninject what is the best way of me setting up my AccountController. Should I pass in the MemberService to the constructor like so:
public class AccountController : Controller
{
IMemberService _memberService;
public AccountController(IMemberService memberService)
{
_memberService = memberService;
}
}
Or pass in the repository:
public class AccountController : Controller
{
IMemberService _memberService;
public AccountController(IMemberRepository memberRepo)
{
_memberService = new MemberService(memberRepo);
}
}
Or Both?
I originally had just a repository (no service layer) but I've had to implement a service layer and I'm not sure how I'd handle the 'dependency' when registering the kernal in my NinjectWebCommon.cs file. Which was originally just this:
kernel.Bind<IMemberRepository>().To<SqlMemberRepository>();
But now I'm wondering if I need to register the IMemberService and have the repo as some kind of parameter.
:s Feeling kind of lost. Hope I'm making sense and someone can help out.
I've never used Ninject, I've been using Unity, but the same principles exist so hopefully this might help.
The service layer is the thing that is exposed to the controller - the controller needs to know nothing about the underlying repository. The flow is as follows, and each layer doesn't know about the layers above it:
Controller -> Service > Repository
So I would go with option 1, and then inject the repository into the constructor of the service.
public class MemberService : IMemberService {
private readonly IMemberRepository _repo;
[Inject]
public MemberService (IMemberRepository repo){
this._repo = repo;
}
public bool Register(string email){
//Do Stuff & Populate Member Object
_repo.Save(member);
}
}
and
public class AccountController : Controller
{
private readonly IMemberService _memberService;
[Inject]
public AccountController(IMemberService memberService)
{
_memberService = memberService;
}
}
That example obviously uses constructor injection but you can use property/field injection if you want instead. When you register your dependencies, you'll have to register both:
kernel.Bind<IMemberRepository>().To<SqlMemberRepository>();
kernel.Bind<IMemberService>().To<MemberService>();

Automapper + EF4 + ASP.NET MVC - getting 'context disposed' error (I know why, but how to fix it?)

I have this really basic code in a MVC controller action. It maps an Operation model class to a very basic OperationVM view-model class .
public class OperationVM: Operation
{
public CategoryVM CategoryVM { get; set; }
}
I need to load the complete list of categories in order to create a CategoryVM instance.
Here's how I (try to) create a List<OperationVM> to show in the view.
public class OperationsController : Controller {
private SomeContext context = new SomeContext ();
public ViewResult Index()
{
var ops = context.Operations.Include("blah...").ToList();
Mapper.CreateMap<Operation, OperationVM>()
.ForMember(
dest => dest.CategoryVM,
opt => opt.MapFrom(
src => CreateCatVM(src.Category, context.Categories)
// trouble here ----------------^^^^^^^
)
);
var opVMs = ops.Select(op => Mapper.Map<Operation, OperationVM>(op))
.ToList();
return View(opVMs);
}
}
All works great first time I hit the page. The problem is, the mapper object is static. So when calling Mapper.CreateMap(), the instance of the current DbContext is saved in the closure given to CreateMap().
The 2nd time I hit the page, the static map is already in place, still using the reference to the initial, now disposed, DbContext.
The exact error is:
The operation cannot be completed because the DbContext has been disposed.
The question is: How can I make AutoMapper always use the current context instead of the initial one?
Is there a way to use an "instance" of automapper instead of the static Mapper class?
If this is possible, is it recommended to re-create the mapping every time? I'm worried about reflection slow-downs.
I read a bit about custom resolvers, but I get a similar problem - How do I get the custom resolver to use the current context?
It is possible, but the setup is a bit complicated. I use this in my projects with help of Ninject for dependency injection.
AutoMapper has concept of TypeConverters. Converters provide a way to implement complex operations required to convert certain types in a separate class. If converting Category to CategoryVM requires a database lookup you can implement that logic in custom TypeConverter class similar to this:
using System;
using AutoMapper;
public class CategoryToCategoryVMConverter :
TypeConverter<Category, CategoryVM>
{
public CategoryToCategoryVMConverter(DbContext context)
{
this.Context = context;
}
private DbContext Context { get; set; }
protected override CategoryVM ConvertCore(Category source)
{
// use this.Context to lookup whatever you need
return CreateCatVM(source, this.Context.Categories);
}
}
You then to configure AutoMapper to use your converter:
Mapper.CreateMap<Category, CategoryVM>().ConvertUsing<CategoryToCategoryVMConverter>();
Here comes the tricky part. AutoMapper will need to create a new instance of our converter every time you map values, and it will need to provide DbContext instance for constructor. In my projects I use Ninject for dependency injection, and it is configured to use the same instance of DbContext while processing a request. This way the same instance of DbContext is injected both in your controller and in your AutoMapper converter. The trivial Ninject configuration would look like this:
Bind<DbContext>().To<SomeContext>().InRequestScope();
You can of course use some sort of factory pattern to get instance of DbContext instead of injecting it in constructors.
Let me know if you have any questions.
I've found a workaround that's not completely hacky.
Basically, I tell AutoMapper to ignore the tricky field and I update it myself.
The updated controller looks like this:
public class OperationsController : Controller {
private SomeContext context = new SomeContext ();
public ViewResult Index()
{
var ops = context.Operations.Include("blah...").ToList();
Mapper.CreateMap<Operation, OperationVM>()
.ForMember(dest => dest.CategoryVM, opt => opt.Ignore());
var opVMs = ops.Select(
op => {
var opVM = Mapper.Map<Operation, OperationVM>(op);
opVM.CategoryVM = CreateCatVM(op.Category, context.Categories);
return opVM;
})
.ToList();
return View(opVMs);
}
}
Still curious how this could be done from within AutoMapper...
The answer from #LeffeBrune is perfect. However, I want to have the same behavior, but I don't want to map every property myself. Basically I just wanted to override the "ConstructUsing".
Here is what I came up with.
public static class AutoMapperExtension
{
public static void ConstructUsingService<TSource, TDestination>(this IMappingExpression<TSource, TDestination> mappingExression, Type typeConverterType)
{
mappingExression.ConstructUsing((ResolutionContext ctx) =>
{
var constructor = (IConstructorWithService<TSource, TDestination>)ctx.Options.ServiceCtor.Invoke(typeConverterType);
return constructor.Construct((TSource)ctx.SourceValue);
});
}
}
public class CategoryToCategoryVMConstructor : IConstructorWithService<Category, CategoryVM>
{
private DbContext dbContext;
public DTOSiteToHBTISiteConverter(DbContext dbContext)
{
this.dbContext = dbContext;
}
public CategoryVM Construct(Category category)
{
// Some commands here
if (category.Id > 0)
{
var vmCategory = dbContext.Categories.FirstOrDefault(m => m.Id == category.Id);
if (vmCategory == null)
{
throw new NotAllowedException();
}
return vmCategory;
}
return new CategoryVM();
}
}
// Initialization
Mapper.Initialize(cfg =>
{
cfg.ConstructServicesUsing(type => nInjectKernelForInstance.Get(type));
cfg.CreateMap<Category, CategoryVM>().ConstructUsingService(typeof(CategoryToCategoryVMConstructor));
};

Questions about the Service Layer as Validation in asp.net mvc

I am a bit confused about the service layer and using it validation.
So I am looking through this tutorial: http://www.asp.net/learn/mvc/tutorial-38-cs.aspx
First if you look at List 3
using System.Collections.Generic;
using System.Web.Mvc;
namespace MvcApplication1.Models
{
public class ProductService : MvcApplication1.Models.IProductService
{
private ModelStateDictionary _modelState;
private IProductRepository _repository;
public ProductService(ModelStateDictionary modelState, IProductRepository repository)
{
_modelState = modelState;
_repository = repository;
}
protected bool ValidateProduct(Product productToValidate)
{
if (productToValidate.Name.Trim().Length == 0)
_modelState.AddModelError("Name", "Name is required.");
if (productToValidate.Description.Trim().Length == 0)
_modelState.AddModelError("Description", "Description is required.");
if (productToValidate.UnitsInStock < 0)
_modelState.AddModelError("UnitsInStock", "Units in stock cannot be less than zero.");
return _modelState.IsValid;
}
public IEnumerable<Product> ListProducts()
{
return _repository.ListProducts();
}
public bool CreateProduct(Product productToCreate)
{
// Validation logic
if (!ValidateProduct(productToCreate))
return false;
// Database logic
try
{
_repository.CreateProduct(productToCreate);
}
catch
{
return false;
}
return true;
}
}
public interface IProductService
{
bool CreateProduct(Product productToCreate);
IEnumerable<Product> ListProducts();
}
}
They same interface just with a different name basically why not just use one?
public interface IProductRepository
{
bool CreateProduct(Product productToCreate);
IEnumerable<Product> ListProducts();
}
public interface IProductService
{
bool CreateProduct(Product productToCreate);
IEnumerable<Product> ListProducts();
}
In my book though(the author who I think wrote this tutorial) has changed it to have IProductRepository to void. So that confuses me even more.
So can someone explain why I need 2 interfaces that seems to do the same thing?
My next questions is my repository has a delete function. Do I put this one in my Service layer too(I guess mandatory if you use one Interface but if you use 2 like about then it could be optinal).
So what would I have in my service layer? Would it just call delete function in the repository? Should it just be a void method or should it return bool? I don't think for this method any validation would need to be done?
So I am not sure if a bool would be needed.
From the tutorial you are reading:
So, application flow control logic
belongs in a controller and data
access logic belongs in a repository.
In that case, where do you put your
validation logic? One option is to
place your validation logic in a
service layer.
A service layer is an additional layer
in an ASP.NET MVC application that
mediates communication between a
controller and repository layer. The
service layer contains business logic.
In particular, it contains validation
logic.
EDIT:
I'm not sure if I can explain it to you in a clear way('cause I'm not fluent in English), but I will try:
A service layer is an additional layer in an ASP.NET MVC application that mediates communication between a controller and repository layer, in that you can handle both validation and application businness. Sometimes you service will need to work with two or more methods of its correspondent repository layer so it doesnt need to have the same interface.
A basic example, let's think you have a register form.
you will have the following interfaces
public interface IUserService
{
bool Register(User mUser);
bool Validate(User mUser);
}
public interface IUserRepository
{
User FindUserByEmail(string Email);
bool Insert(User mUser);
}
so you will end up with two class that will do something like:
public class UserRepository: IUserRepository{
User FindUserByEmail(string Email)
{
//do a ninja search and return an user or null
}
bool Insert(User mUser);
{
//Insert user into db
}
}
public class UserService: IUserService
{
public bool Validate(User mUser)
{
//validate user
}
IUserRepository _respository = new UserRepository();
bool Register(User mUser)
{
if(Validate(mUser);
var hasUser = _respository.FindUserByEmail(User.Email);
if(hasUser==null)
return _respository.Insert(mUser);
return false;
}
}
I think you've made an argument for a single interface in this limited case, but the service and repositories perform two very different functions and you may run into issues down the road if they shared a single interface.
What if the CreateProduct() or ListProducts() needed to have different method signatures in either the service or repository?
What if ValidateProduct() should be defined in the interface? The repository certainly shouldn't have to implement that.
As you've pointed out, there's no need for two interfaces that define the same thing in this particular example, but I assume the author's assumption is that down the road they would be different and therefore necessary.

Resources