I'm trying to understand how to separate concerns in my application and I have used Repository pattern before,
Problem is that i don't understand where the service comes in.
Let's say i have a simple CreateModel
public class CreateModel : PageModel
{
private readonly IGenericRepository _genereicRepository;
public CreateModel(IGenericRepository genericRepository)
{
_genereicRepository = genericRepository;
}
[BindProperty]
public Entity Entity { get;set; }
public void OnGet()
{
var entities = _genericRepository.GetEntities();
}
public void OnPost()
{
_genereicRepository.AddEntity(Entity);
_genereicRepository.SaveChanges();
}
}
and the rest is up to the repository to do the database calls.
Now why would i need a service in here and what would it exactly handle or abastract even more since there is nothing else to abstract?
You may not need services, it all depends on how complex your system is. If all your controller methods do is done with one object and one repository call, I wouldn't add a service.
I add services when the operations the controllers want to perform are getting too complicated to keep them in the controller. For instance, if one controller method updates multiple objects and requires some logic (sometimes this group of objects is updated, sometimes that group) - I put that logic in a service.
Related
I'm working on a backend project, building a RESTful API for a number of entities. Right now, the task is to build out your basic CRUD abilities for each one of the current entities in the design. Later on, I'll get more sophisticated, but for now all I need to do is create API endpoints that let you get, create, update or delete from the repository for each entity.
Since I want to apply the same types of operations to a variety of different entity types, I thought to use a generic controller class. This let me avoid having to write in the boilerplate (method names, HTTP verbs specified for each, etc.) for each entity's controller. That looks something like this:
public class EntityCRUDController<TService, TDetail, TSummary> : ApiController
where TService: IEntityCRUDService<TDetail, TSummary>
{
protected readonly TService _service;
public EntityCRUDController(TService service)
{
_service = service;
}
[HttpGet]
[Route("")]
public async Task<TSummary> GetAll()
{
return await _service.GetAll();
}
[HttpGet]
[Route("{entityId}")]
public async Task<TDetail> GetSpecific(Guid entityId)
{
return await _service.GetSpecific(entityId);
}
[HttpPost]
[Route("")]
public IHttpActionResult Create([FromBody]TDetail entityDetail)
{
_service.Create(entityDetail);
return Ok();
}
[HttpPut]
[Route("{entityId}")]
public IHttpActionResult Update(Guid entityId, [FromBody]TDetail entityDetail)
{
_service.Update(entityDetail);
return Ok();
}
[HttpDelete]
[Route("{entityId}")]
public IHttpActionResult Delete(Guid entityId)
{
_service.Delete(entityId);
return Ok();
}
}
So that actually works quite well. It's extensible too, so I can still add any additional endpoints beyond the CRUD boilerplate that I need. But then I thought, if I can make the controllers generic, why not make the services generic too?
Each controller is injected with a service, which lets the controller perform these CRUD operations. Each service, in turn, is injected with a repository which knows how to actually interact with the infrastructure layer.
The problem comes with trying to implement the generic service object inside the generic service class. I'm trying to use an abstract class to have each service object inherit from. That abstract class will contain the main CRUD methods, since those are basically the same operation for each entity.
I've tried a variety of ways of implementing this but haven't been able to make it work. Every time I do I just go around in circles and confuse myself. Either I can't get it to compile, or it does compile and I can't get the generic service to inject correctly into the controller.
So how would you do it if you wanted to reuse as much code as possible? I want to have reusable generic methods for the standard CRUD operations, but then the option to add additional methods unique to each entity type. I can make it work just fine with only generic controllers, but then I'm consigned to duplicating the main CRUD code inside each service.
Assuming that you are using EF, it is an easy task by using repository pattern. A generic class named Repository which has methods for create, read, update and delete. You can optionally introduce an interface to a better dependency injection:
Public interface IRepository
{
Public void Add(T entity);
//....
}
Public class Repository: IRepository
{
Public Repository(/* inject DI here */)
{}
Public void Add(T entity)
{
_dbSet.Add(entity);
}
//.....
}
I asked a question about ASP.NET MVC Generic Controller and this answer shows a controller like this:
public abstract class GenericController<T>
where T : class
{
public virtual ActionResult Details(int id)
{
var model = _repository.Set<T>().Find(id);
return View(model);
}
}
Which can be implemented like this.
public class FooController : GenericController<Foo>
{
}
Now when someone requests /Foo/Details/42, the entitiy is pulled from the _repository's Set<Foo>(), without having to write anything for that in the FooController.
The way he explain that is good but think i want to develop a generic controller for product and customer where i will not use EF to load product & customer model rather use MS data access application block.
public abstract class GenericController<T>
where T : class
{
public virtual ActionResult Details(int id)
{
//var model = _repository.Set<T>().Find(id);
var model =customer.load(id);
or
var model =product.load(id);
return View(model);
}
}
So when request comes like /Customer/Details/42 or /product/Details/11 then generic controller's details method will call but how we can detect that request comes from which controller and accordingly instantiate right class to load right model.
If request comes for Customer then I need to load customer details from detail action method or if request comes for Product then I need to load Product details from detail action method of generic controller.
How do I use generics to get the dataset of type T with the Entity Framework Data block?
You may create a set of repositories for working with your entities, like CustomerRepository, ProductRepository from base interface like
public interface IBaseRepository
{
T Get<T>(int id);
void Save<T>(T entity);
}
and then extend your base controller class with repository type and its instance with any of DI frameworks
public abstract class GenericController<T, TRepo>
where T : class
where TRepo : IBaseRepository, new()
{
private IBaseRepository repository;
public GenericController()
{
repository = new TRepo();
}
public virtual ActionResult Details(int id)
{
var model =repository.Get<T>(id);
return View(model);
}
}
Example for CustomerController
public class CustomerController : GenericController<Customer, CustomerRepository>
{
}
where CustomerRepository:
public class CustomerRepository : IBaseRepository
{
public T Get <T>(int id)
{
// load data from DB
return new Customer();
}
}
I don't think it's wise to place data-access and business logic like this in controllers when your application's size and complexity grows beyond a certain point. You should create repositories which handle the data-access and abstract the technology (EF, plain ADO.NET, etc.) away from the consumers. You could use these repositories in your controller, but that would mean that your controllers still contain business logic which you don't want. Controllers should be thin.
What I did was creating a service layer between my repositories and controllers which contain the business logic and delegate data-access to the repositories. I use these services in my controllers to fetch my domain models where I map them to view models. You're gonna want an Inversion of Control container to 'glue' the layers together and to provide loose coupling between them.
A search for 'c# mvc repository and service pattern' will result in loads of examples. I found this post a good one, except for the fact that he returns view models from his services rather than domain models.
This is just my 2 cents, please keep in mind that all of the above only counts when your have a 'mid-range' application and not a typical tutorial/try-out website.
Given my disclaimers in the other question and my comments here explaining why this isn't an ultimate solution, I'll try to give a more concrete implementation:
public abstract class GenericController<T> : Controller
where T : class
{
protected YourEFContext _dataSource;
public GenericController()
{
_dataSource = new YourEFContext();
}
public virtual ActionResult Details(int id)
{
var model = _dataSource.Set<T>().Find(id);
return View(model);
}
}
public class CustomerController : GenericController<Customer>
{
}
This is all code that is needed to let /Customers/Details/42 load customer with ID 42 be loaded from the Entity Framework context. The "generic" part is solved by Entity Framework's DbContext.Set<T>() method, which returns the DbSet<TEntity> for the appropriate entity, in this case DbSet<Customer> which you can query.
That being said, there are many problems with actually using this code:
You don't want to let your controller know about your data access. As you see, a YourEFContext property is used in the controller, tightly coupling it with Entity Framework. You'll want to abstract this away in a repository pattern.
You don't want your controller to instantiate its data access, this should be injected.
You don't want your controller to return database entities. You're looking for ViewModels and a Mapper.
You don't want your controller to do data access. Move the data access in a service layer that also contains your business logic, abstract it again through a repository pattern.
Now your question actually is "Does the Enterprise Library Data Block have a method like GetDataSet<T>", so you don't have to refer to customer and product in your generic controller, but unfortunately I can't find that as I haven't used EntLib for a few years. It would help if you show the code you currently use to access your database.
The ultimate goal you're looking for:
[ MVC ] <=> [ Service ] <=> [ Repository ]
View ViewModel Controller BusinessModel BusinessLogic DataModel Database
Your controller only talks to your service to Create/Read/Update/Delete BusinessModels, and performs the mapping between ViewModels and BusinessModels (at <=>). The service contains the business logic and business model (DataContacts when using WCF) and in turn maps (<=>) to and from DataModels and talks to your repository to persist your models.
I understand this can be a bit much to grasp at once, and that's probably why most ASP.NET MVC tutorials start with all three tiers in one application. Take a look at ProDinner for a more proper approach.
I love the Unity and Ninject framework with dependency injection for C#.NET into the controllers with repository interfaces etc, but I am trying to think up an alternative in PHP and am struggling.
I have:
class User
{
//..
}
interface IUserRepository
{
public function Repository(); // This can't work as a variable, should I abstract?
}
class UserRepository implements IUserRepository
{
public function Repository()
{
$users = // DAO gets users and returns them..
// But how does the IUserRepository help me at all? Even if I had ninject or
// Unity creating some new link between the UserRepo and IUserRepo?
return $users;
}
public function GetAllUsers()
{
// errr.. I'm confused
}
}
// Something has to say if the AdminController is called,
// inject into its construct, a new IUserRepository
class AdminController extends Controller
{
private $repository;
public function __Construct( $repository )
{
$this->repository = $repository;
}
public function ActionResult_ListUsers()
{
$users = $repository->GetAllUsers();
// Do some clever View method thing with $users as the model
}
}
The real question is PHP and repository approach. How does that work? You can see I'm blotching this a bit and really want to get it right!
EDIT::
Even more simple question. What is the benefit of the interface keyword? How does declaring an interface with some methods undefined and then making a new class that implements those methods to extend them, help when you cannot create a new interface like a class that then is filled in with the proper class that defines them?
Kind of a broad question but I'll take a shot. Symfony 2 is a modern php framework built around an excellent dependency injection container. Symfony 2 supports Doctrine 2 which is a modern orm persistence layer in which repositories are supported.
Skim through here: http://symfony.com/doc/current/book/doctrine.html
Skip all the details on setting things up and instead look for:
Creating an Entity Class
Persisting Objects to the Database
Fetching Objects from the Database
The fetching section is where repositories come into play. This gives you a broad overview of one way to implement repositories on php. You might decide to research more on Symfony 2/Doctrine 2 or you may go another route entirely. But this will give you a starting point.
As far as interfaces go, I hate to say it but that is a real real real basic question. Might want to go through some OOP tutorials? A one or two sentence explanation is probably not going to make much sense.
====================================================
This may help a bit:
class User
{
//..
}
interface IUserRepository
{
public function getAllUsers();
}
class UserRepository extends DoctrineRepository implements IUserRepository
{
public function getAllUsers()
{
return $this->findAll();
}
}
class AdminController extends Controller
{
private $repository;
public function __Construct(IUserRepository $repository )
{
$this->repository = $repository;
}
public function ActionResult_ListUsers()
{
$users = $this->repository->getAllUsers();
// Do some clever View method thing with $users as the model
}
Your User and IUserRepository would reside in what is known as a domain layer.
The actual UserRepository implementation would be in a service layer. You might have multiple implementations. One talking to a sql database. Perhaps another talking to MongoDB or maybe just a file.
You controller lives in yet another layer. It expects to receive an object the implements an IUserRepository and thus has a getAllUsers method. Your controller does not care how the repository is actually implemented. All it knows is what is exposed via the interface.
It's up to your application to wire things up using dependency injection such that the controller gets the correct repository.
I have an UnitOfWork attribute, something like this:
public class UnitOfWorkAttribute : ActionFilterAttribute
{
public IDataContext DataContext { get; set; }
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.Controller.ViewData.ModelState.IsValid)
{
DataContext.SubmitChanges();
}
base.OnActionExecuted(filterContext);
}
}
As you can see, it has DataContext property, which is injected by Castle.Windsor. DataContext has lifestyle of PerWebRequest - meaning single instance reused for each request.
Thing is, that from time to time I get DataContext is Disposed exception in this attribute and I remember that ASP.NET MVC 3 tries to cache action filters somehow, so may that causes the problem?
If it is so, how to solve the issue - by not using any properties and trying to use ServiceLocator inside method?
Is it possible to tell ASP.NET MVC to not cache filter if it does cache it?
I would strongly advice against using such a construct. For a couple of reasons:
It is not the responsibility of the controller (or an on the controller decorated attribute) to commit the data context.
This would lead to lots of duplicated code (you'll have to decorate lots of methods with this attribute).
At that point in the execution (in the OnActionExecuted method) whether it is actually safe to commit the data.
Especially the third point should have drawn your attention. The mere fact that the model is valid, doesn't mean that it is okay to submit the changes of the data context. Look at this example:
[UnitOfWorkAttribute]
public View MoveCustomer(int customerId, Address address)
{
try
{
this.customerService.MoveCustomer(customerId, address);
}
catch { }
return View();
}
Of course this example is a bit naive. You would hardly ever swallow each and every exception, that would just be plain wrong. But what it does show is that it is very well possible for the action method to finish successfully, when the data should not be saved.
But besides this, is committing the transaction really a problem of MVC and if you decide it is, should you still want to decorate all action methods with this attribute. Wouldn't it be nicer if you just implement this without having to do anything on the Controller level? Because, which attributes are you going to add after this? Authorization attributes? Logging attributes? Tracing attributes? Where does it stop?
What you can try instead is to model all business operations that need to run in a transaction, in a way that allows you to dynamically add this behavior, without needing to change any existing code, or adding new attributes all over the place. A way to do this is to define an interface for these business operations. For instance:
public interface ICommandHandler<TCommand>
{
void Handle(TCommand command);
}
Using this interface, your controller would look like this:
private readonly ICommandHandler<MoveCustomerCommand> handler;
// constructor
public CustomerController(
ICommandHandler<MoveCustomerCommand> handler)
{
this.handler = handler;
}
public View MoveCustomer(int customerId, Address address)
{
var command = new MoveCustomerCommand
{
CustomerId = customerId,
Address = address,
};
this.handler.Handle(command);
return View();
}
For each business operation in the system you define a class (a DTO and Parameter Object). In the example the MoveCustomerCommand class. This class contains merely the data. The implementation is defined in a class that implementation of the ICommandHandler<MoveCustomerCommand>. For instance:
public class MoveCustomerCommandHandler
: ICommandHandler<MoveCustomerCommand>
{
private readonly IDataContext context;
public MoveCustomerCommandHandler(IDataContext context)
{
this.context = context;
}
public void Handle(MoveCustomerCommand command)
{
// TODO: Put logic here.
}
}
This looks like an awful lot of extra useless code, but this is actually really useful (and if you look closely, it isn't really that much extra code anyway).
Interesting about this is that you can now define one single decorator that handles the transactions for all command handlers in the system:
public class TransactionalCommandHandlerDecorator<TCommand>
: ICommandHandler<TCommand>
{
private readonly IDataContext context;
private readonly ICommandHandler<TCommand> decoratedHandler;
public TransactionalCommandHandlerDecorator(IDataContext context,
ICommandHandler<TCommand> decoratedHandler)
{
this.context = context;
this.decoratedHandler = decoratedHandler;
}
public void Handle(TCommand command)
{
this.decoratedHandler.Handle(command);
this.context.SubmitChanges();
}
}
This is not much more code than your UnitOfWorkAttribute, but the difference is that this handler can be wrapped around any implementation and injected into any controller, without the controller to know about this. And directly after executing a command is really the only safe place where you actually know whether you can save the changes or not.
You can find more information about this way of designing your application in this article: Meanwhile... on the command side of my architecture
Today I've half accidently found the original issue of the problem.
As it is seen from the question, filter has property, that is injected by Castle.Windsor, so those, who use ASP.NET MVC know, that for that to work you need to have IFilterProvider implementation, which would be able to use IoC container for dependency injection.
So I've started to look at it's implementation, and noticed, that it is derrived from FilterAttributeFilterProvider and FilterAttributeFilterProvider has constructor:
public FilterAttributeFilterProvider(bool cacheAttributeInstances)
So you can control to cache or not your attribute instances.
After disabling this cache, site was blown with NullReferenceExceptions, so I was able to find one more thing, that was overlooked and caused undesired side effects.
Thing was, that original filter was not removed, after we added Castle.Windsor filter provider. So when caching was enabled, IoC filter provider was creating instances and default filter provider was reusing them and all dependency properties were filled with values - that was not clearly noticeable, except the fact, that filters were running twice, after caching was disabled, default provider was needed to create instances by it self, so dependency properties were unfilled, that's why NullRefereceExceptions occurred.
I am near the end of a new ASP.NET MVC application I have been developing, and I have realised that I am not 100% on what should be goning on in my controller methods.
Is it better for an action method to decide which services/methods are called and in what order like so:
AccountService _accountService;
BillingService _billingService;
InvoiceService _invoiceService;
...
public ActionResult UpgradeAccountPackage(PackageType packageType, int accountId)
{
_accountService.UpgradeAccountPackage(packageType, accountId);
_billingService.BillForAccountUpgrade(packageType, accountId);
_invoiceService.CreateAccountUpgradeInvoice(packageType, accountId);
}
Or is it better to stick to a single method call to one service and allow this method to call the other services/support method it needs?
public ActionResult UpgradeAccountPackage(PackageType packageType, int accountId)
{
// account service upgrades account then calls the BillingService and InvoicService
// methods called above within this method
_accountService.UpgradeAccountPackage(packageType, accountId);
}
I have tended to go for the second example here, as it seemed originally like the first method would constitute logic in some way, and means the acion method would have to intrinsically know about how the account upgrade process works within my application, which seems like a bad thing.
However, now my application is almost finished it has a large service layer and this approach has led to almost every service having a strong dependency on numerous other services, and there is no centralised place which decides the flow of business transactions such as the one mentioned above, you have to dig around a bit in service methods to discover the processes.
I am considering refactoring to more closesly resemble the second method above, or introducing a new layer in between the controller and service layer which controls the flow of processes.
Do people tend to use the first or second method? What are peoples opinions?
I prefer the second method - much easier to test (using mocks), and the logic is there for reuse. You end up with Facades to your actual business logic, but that's not bad thing.
I don't understand why your service layer is full of concrete dependencies though...
The thing to remember is that you want classes to rely on interfaces, not implementation. (and then string it all together with a Dependancy Injection tool)
In C#, we can have one class implement many interfaces. So your service implementations can implement many interface, and yet the caller need only know about the part they need.
For example, you might have an AccountTransactionService that imlpements IDepositor and IWithdrawer. If you implement double-entry accounting, then that could depend on IDepositor and IWithdrawer, which, in actual fact, just uses the same instance of AccountTransactionService, but it doesn't have to, and the implementation details could be changed afterwards.
In general, the less one class knows about the other classes in the system, the better.
I more closely use the first method. Let the controller control what happens. Let the services decide how that happens.
If you add a second layer to control the flow of processes would that leave your ActionMethods only making the one call? If so, it seems unnecessary at that point.
You could have a service layer which depends on multiple repositories (not other services) and which defines the business operations:
public class MyService: IMyService
{
private readonly IAccountRepository _accountRepository;
private readonly IInvoiceRepository _invoiceRepository;
private readonly IBillingRepository _billingRepository;
public MyService(IAccountRepository accountRepository, IInvoiceRepository invoiceRepository, IBillingRepository billingRepository)
{
_accountRepository = accountRepository;
_invoiceRepository = invoiceRepository;
_billingRepository = billingRepository;
}
public void UpgradeAccountPackage(PackageType packageType, int accountId)
{
...
}
}
and then have your controller take IMyService as dependency:
public class HomeController: Controller
{
private readonly IMyService _service;
public HomeController(IMyService service)
{
_service = service;
}
public ActionResult UpgradeAccountPackage(PackageType packageType, int accountId)
{
_service.UpgradeAccountPackage(packageType, accountId);
...
}
}
I define simple CRUD operations with the entities on the repositories and the service aggregates those multiple operations into one business transaction.