I'm building an application that roughly follows the repository pattern with a service layer on top, similar to early versions of Conery's MVC Storefront.
I need to implement a page that returns all users except for the current user. I already have GetUsers() methods on the repository and service layers, so the question is where to apply the "except for the current user."
Should the service layer be aware of HttpContext, thus applying this rule? I am tempted to just pass in the current user (id) from the controller to this service method, but it seems cleaner if the service layer was HttpContext-aware and could do this on its own.
One obvious alternative is to apply this rule directly within the Controller, but I'm just not hot on that idea...
Edit - just to comment on the answers: I see the issues with the reverse dependency problem, something I was completely overlooking. I'm marking Mehrdad's as the answer due votes, but everyone has really provided a valuable response worth reading!
Absolutely not. My mindset in designing these kind of things is like this: I assume I need to write a Windows based app along with the Web application and try to minimize dependency on Web specific stuff. Passing HttpContext directly will increase coupling of your service layer to your Web UI layer which is not ideal.
The answer is, no.
Not only should the Service Layer have no dependency on the current Presentation Layer, in my opinion it should have no dependency on the current application. For instance, I would not use a custom AppContext class as JonoW suggested here.
Instead, pass the current user as a parameter to the GetAllUsersExceptForTheCurrentUser method.That way, the service can be used by any application that needs to process users, not only the current application.
You should not create a reverse dependency between your service layer and the web tier. Consider what happens when you want to extend your service layer to work with a forms-based application or windows service. Now you've got to work around the web dependency to get your same methods to work or duplicate some (perhaps, small, but still duplicate) code. You would be better served to extract the user's identifier into something useful in the context of the service layer and use that value with the service layer. Handling the filtering on the web site is also acceptable, though if you do it more than once it would need to be refactored into a common place and the service layer is the natural spot for it.
I find it good practice to build a custom AppContext class which contains my current user object (as well as other contextual data). This class has no references to System.Web. Any service methods that need to be context aware should have an AppContext parameter (e.g. for checking security rights, or getting the current user as in your case). Populate this object in the web-tier and keep it in session if you need to. This way your service layer knows nothing about System.Web.
No. Doing so will make your code harder to test and re-use.
I tend to build an infrastructure interface for this sort of thing (call it IAuthentication or something) and expose a CurrentUser property on it. Then I'd inject this into my service via its a constructor. i.e. public MyService(IAuthentication auth)
Finally you'd can build an HttpContext aware implementation of IAuthentication (say WebAuthentication).
Now when you create your service you create its dependencies as well:
var myService = new MyService(new WebAuthentication());
var otherUsers = myService.GetAllOtherUsers();
If you are using an IoC container the ugly dependency can even go away!
Related
I am building an Asp.Net Core backend with the following layers:
Api layer
Data Access layer
Service layer
The service layer needs to filter results based on the user and its permissions. According to several articles, it is not a good idea to access the user via HttpContext inside the service layer because it should be independent of the presentation layer. The only alternative I am seeing is getting the current user inside the api controller and passing it to the service layer. Is this the only approach? I see it as quite tedious to always pass the user down to the service layer. I would appreciate some thoughts on this matter.
You do indeed want to get the user data out in the api controller (the presentation layer) and pass it down into the service layer. Not only will it keep your service independent of an HTTP context, it will also massively improve the testability of your code.
This will allow you to do things like use your service in an asynchronous context, or even push it out into a separate container/server.
Getting things out of HTTPContext is the modern-day equivalent of global variables. Convenient? Yes. Toxic? Yes! Will ultimately make your application a big ball of mud? Yes! Sticking with architecture is how you keep your programs clean and boring. Boring code is good code. Solve hard problems, not hard code.
I was wondering how far I should take my IoC implementation in terms of loosely coupling my application. I am using constructor injection in my MVC controller but wondered if I should also be resolving all my other dependencies in the controller instead of newing up objects. For example if I was to create a new User object within a controller method would I use?
var user = new User();
var user = myContainer.Resolve<IUser>();
I like the idea of breaking my dependency on User but is that going too far and could possible make my code harder to read?
This is a very good question, when you read and hear about DI it makes sense and this is the next natural conclusion.
First Steven's point is correct you should not pass the container around. If you need to construct IUser on the fly and it needs to be abstract you should rather inject an Abstract Factory.
Sebastian also posted a good link.
I actually wrote about this in an answer I posted here.
The bottom section of the post:
Not every object and dependency needs or should be dependency injected, first consider if what you are using is actually considered a dependency:
What are dependencies?
Application Configuration
System Resources (Clock)
Third Party Libraries
Database
WCF/Network Services
External Systems (File/Email)
Any of the above objects or collaborators can be out of your control and cause side effects and difference in behavior and make it hard to test. These are the times to consider an Abstraction (Class/Interface) and use DI.
What are not dependencies, doesn't really need DI?
List
MemoryStream
Strings/Primitives
Leaf Objects/Dto's
So in your particular case it really depends on what happens when IUser is constructed also whether you actually need to substitute it with different implementations. If this is not the case and User has only simple types with no external dependencies or side effects just new it up.
Consider what happens when you call new User(), look at the graph below, if it causes other objects to be created and looks like something in the graph below consider IoC.
A cascading dependency object graph:
In this example new on the object either requires or creates a whole bunch of other dependencies. It is most likely out of your control what those dependencies are or do.
When your object is a simple dto it doesn't suffer this problem and IoC is likely not so much required.
most of the time in the service code I would have something like this:
public SomeService : ISomeService
{
ISomeRepository someRepository;
public Do(int id)
{
someRepository.Do(id);
}
}
so it's kinda redundant
so I started to use the repositories directly in the controller
is this ok ? is there some architecture that is doing like this ?
You lose the ability to have business logic in between.
I disagree with this one.
If business logic is where it should be - in domain model, then calling repo in controller (or better - use model binder for that) to get aggregate root and call method on it seems perfectly fine to me.
Application services should be used when there's too much technical details involved what would mess up controllers.
I've seen several people mention using model binders to call into a repo lately. Where is this crazy idea coming from?
I believe we are talking about 2 different things here. I suspect that Your 'model binder' means using model simultaneously as a view model too and binding changed values from UI directly right back to it (which is not a bad thing per se and in some cases I would go that road).
My 'model binder' is a class that implements 'IModelBinder', that takes repository in constructor (which is injected and therefore - can be extended if we need caching with some basic composition) and uses it before action is called to retrieve aggregate root and replace int id or Guid id or string slug or whatever action argument with real domain object. Combining that with input view model argument lets us to write less code. Something like this:
public ActionResult ChangeCustomerAddress
(Customer c, ChangeCustomerAddressInput inp){
c.ChangeCustomerAddress(inp.NewAddress);
return RedirectToAction("Details", new{inp.Id});
}
In my actual code it's a bit more complex cause it includes ModelState validation and some exception handling that might be thrown from inside of domain model (extracted into Controller extension method for reuse). But not much more. So far - longest controller action is ~10 lines long.
You can see working implementation (quite sophisticated and (for me) unnecessary complex) here.
Are you just doing CRUD apps with Linq To Sql or trying something with real domain logic?
As You can (hopefully) see, this kind of approach actually almost forces us to move towards task based app instead of CRUD based one.
By doing all data access in your service layer and using IOC you can gain lots of benefits of AOP like invisible caching, transaction management, and easy composition of components that I can't imagine you get with model binders.
...and having new abstraction layer that invites us to mix infrastructure with domain logic and lose isolation of domain model.
Please enlighten me.
I'm not sure if I did. I don't think that I'm enlightened myself. :)
Here is my current model binder base class. Here's one of controller actions from my current project. And here's "lack" of business logic.
If you use repositories in your controllers, you are going straight from the Data Layer to the Presentation Layer. You lose the ability to have business logic in between.
Now, if you say you will only use Services when you need business logic, and use Repositories everywhere else, your code becomes a nightmare. The Presentation Layer is now calling both the Business and Data Layer, and you don't have a nice separation of concerns.
I would always go this route: Repositories -> Services -> UI. As soon as you don't think you need a business layer, the requirements change, and you will have to rewrite EVERYTHING.
My own rough practices for DDD/MVC:
controllers are application-specific, hence they should only contain application-specific methods, and call Services methods.
all public Service methods are usually atomic transactions or queries
only Services instantiate & call Repositories
my Domain defines an IContextFactory and an IContext (massive leaky abstraction as IContext members are IDBSet)
each application has a sort-of Composition Root, which is mainly instantiating a Context Factory to pass to the Services (you could use DI container but not a big deal)
This forces me to keep my business code, and data-access out of my controllers. I find it a good discipline, given how loose I am when I don't follow the above!
Here is the thing.
"Business Logic" should reside in your entities and value objects.
Repositories deal with AggregateRoots only. So, using your repositories directly in your Controllers kinda feels like you are treating that action as your "service". Also, since your AggregateRoot may only refer to other ARs by its ID, you may have to call one more than one repo. It really gets nasty very quickly.
If you are going to have services, make sure you expose POCOs and not the actual AggregateRoot and its members.
Your repo shouldn't have to do any operations other than creating, retrieving, updating and deleting stuff. You may have some customized retrieve based on specific conditions, but that's about it. Therefore, having a method in your repo that matches one in your service... code smell right there.
Your service are API oriented. Think about this... if you were to pack that service in a .dll for me to use, how would you create your methods in a way that is easy for me to know what your service can do? Service.Update(object) doesn't make much sense.
And I haven't even talked about CQRS... where things get even more interesting.
Your Web Api is just a CLIENT of your Service. Your Service can be used by another service, right? So, think about it. You most likely will need a Service to encapsulate operations on AggregateRoots, usually by creating them, or retrieving them from a repo, do something about it, then returning a result. Usually.
Makes sense?
Even with "rich domain model" you will still need a domain service for handling business logic which involves several entities. I have also never seen CRUD without some business logic, but in simple sample code. I'd always like to go Martin's route to keep my code straightforward.
In a multi-tenant ASP.NET MVC application based on Rob Conery's MVC Storefront, should I be filtering the tenant's data in the repository or the service layer?
1. Filter tenant's data in the repository:
public interface IJobRepository
{
IQueryable<Job> GetJobs(short tenantId);
}
2. Let the service filter the repository data by tenant:
public interface IJobService
{
IList<Job> GetJobs(short tenantId);
}
My gut-feeling says to do it in the service layer (option 2), but it could be argued that each tenant should in essence have their own "virtual repository," (option 1) where this responsibility lies with the repository.
Which is the most elegant approach: option 1, option 2 or is there a better way?
Update:
I tried the proposed idea of filtering at the repository, but the problem is that my application provides the tenant context (via sub-domain) and only interacts with the service layer. Passing the context all the way to the repository layer is a mission.
So instead I have opted to filter my data at the service layer. I feel that the repository should represent all data physically available in the repository with appropriate filters for retrieving tenant-specific data, to be used by the service layer.
Final Update:
I ended up abandoning this approach due to the unnecessary complexities. See my answer below.
#FreshCode, we do it in the repository, and we do not pass the tenant as a parameter. We use the following approach:
public IQueryable<Job> GetJobs()
{
return _db.Jobs.Where(j=>j.TenantId == Context.TenantId);
}
The context is a dependency the repository has and that is created in the BeginRequest where you determine the tenant based on the url for example.
I think in this way it's pretty transparent and you can avoid the tenantId parameter which may become a little bit disturbing.
Regards.
Update: Not going with a multi-tenant approach cost me hundreds of hours in technical debt. Four years down the line, I wish I took the time to implement a clean tenant approach first. Don't make the same mistake!
Old, out-dated answer:
I ended up stripping out all multi-tenant code in favour of using separate applications and databases for each tenant. In my case I have few tenants that do not change often, so I can do this.
All my controllers, membership providers, role providers, services and repositories were gravitating toward duplicate .WithTenantID(...) code all over the place, which made me realize that I didn't really need one Users table to access data that is specific to one tenant 99% of the time, so using separate applications just makes more sense and makes everything so much simpler.
Thanks for your answers - they made me realize that I needed a redesign.
I have a medium sized asp.net MVC app. It consumes a service layer that handles all the repository use, calling domain services, etc. My controller actions are very slim -- they basically call a service class, get a response and show that respose. Most components are interface based with some poor man's DI. The app is growing, needs better testing support, and starting to call out for an IoC container.
Everything I read (such as this SO question) states that I should configure the IoC at the application root. This makes sense to me if I were using repositories right from my controller actions and needed DI at the controller level, but I'm not. It seems like I'd want my composition root in my service layer. I keep thinking that I don't want my web.config (or another config) at the UI layer even mentioning/seeing/hearing about a repository, credit card processor, etc.
Am I thinking about this the right way or do I just need to get over it?
I have the same situation as you and I tackle it as follows.
The general rule I use is what ever has a global.asax or something similar, it needs to execute the code that registers the IoC components. Another way of putting it is that you need to run it one for each different process that is running (i.e. the website is in one process and the service is in another).
In my case I do this once for the mvc website global.asax and again for the server. In this case the registrations that get made would be different between the service and the website.
In addition I do one more thing. Due to the fact that I reuse components between the mvc app and the service (i.e. logging) I have a third core component that registers the core IoC components for the system and this component is called by the both the website and services registrations. Hence I anything that is common between the service and the website go into the core registration and then anything that is different goes into the 'interface' specific registration.
Hope that helps.
You just need to get over it :)
Having your Composition Root in the application root doesn't require you to have a lot of DI Container stuff in web.config. You can if you will, but it's optional. What is not optional when putting the Composition Root in the application root is that you need to have some DI code in Global.asax.
You may find it irrelevant because your Controllers are so thin, but that's not the real point. The actual point is that you (the abstract 'you') want to postpone coupling classes until the last responsible moment. The earlier you couple types, the less flexibility you have.
If you couple classes in the service layer, you make an irreversible decision at that point. If it later turns out that you need to compose those services differently, you can't - not without recompiling, that is.
If there was a major benefit of doing it, I can understand why you would want to, but there isn't. You may as well wait composing all components untill you absolutely must do so - and that's in the application's entry point.
Coming from a Java perspective, I use the Spring framework for my IoC container. With it, the container really is application-wide. Although you can have different configuration files for different layers (a persistence config file, a services config file, a controller config file, etc), all of objects (beans in Java lingo) go into the container.
I think this still ok though because there is no coupling between classes as you mentioned. A view does not need to know about a credit card processor, just because they are in the same IoC container. These classes will receive (by injection) only the dependencies they need, and are not concerned with other objects in the container.