should i expose repository to controller when using service? - asp.net-mvc

I currently developing asp mvc using unit of work, generic repository and service patterns. I get a little confused on how the design should work in the controller.
Should i expose the repository to the controller? or should the controller know only the service?
The controller need repository to retrieve entities for the combobox list.
The problem to exposing repository is that it has save and delete method and should only be called by the service.
can someone help me on this problem?

The repository pattern is used to abstract away the data source.
There is no need to abstract away the abstraction. So I would use the repository.
However, as soon as you start to get business logic inside the presentation layer you should extract that and put it in a service.

It depends on the requirement for any business logic in front of the persistence layer (Repository). The moment you have any, it will end up in the Controller. This might be acceptable for a very simple system, but the moment you expand (REST APIs, Admin/Support app, Offline/Batch Processing) the system beyond the toy state, you will want to push that logic to a shared tier, indeed, the Service layer. Just put in the abstraction now, and save yourself some refactoring later. This also keeps the Controllers in the business they were meant to be in, directing traffic and calling services to get/put data.

Related

How to access user data within service layer?

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.

Where should I add a List All Users function when using MVC?

I'm aware that in model-view-controller, the Model is the class part.
If I have a User class and instantiate an object, the object must refer to a single user from the database.
So I'll have the CRUD methods on the user, for that specific user.
But if I need a function to run a SELECT * FROM Users, should I create a function within the User class? Or a function in a helper file? Or in the controller? Where should it go, in order to respect the MVC pattern?
I mean, it makes no sense to instantiate a User object just to run a function to display the Users table.
I'm not sure if this will raise "primarily opinion based" flags. I just don't know where those functions should go. If you guys consider the question worth closing, it's ok. But tell me in the comments in which stack community I should ask this.
Back up a bit. Let's go foundational for a moment.
In the MVC pattern
The model is your state (in simple terms), meaning a representation of the data important to the business functionality you are working with
The view is a way of presenting the state to the user (NOTE user here could be another system, as you can use MVC patterns for service endpoints)
The controller ensures the model gets to the view and back out of the view
In a system designed with good separation of state, business functions are not present in the model, the view or the controller. You segregate business functionality into its own class library. Why? You never know when the application will require a mobile (native, not web) implementation or a desktop implementation or maybe even become part of a windows service.
As for getting at data, proper separation of concerns states the data access is separate not only from the model, view and controller, but also from the business functionality. This is why DALs are created.
Before going on, let's go to your questions.
should I create a function within the User class? This is an "active record" pattern, which is largely deprecated today, as it closely couples behavior and state. I am sure there are still some instances where it applies, but I would not use it.
Or a function in a helper file? Better option, as you can separate it out. But I am not fond of "everything in a single project" approach, personally.
Or in the controller? Never, despite Scott Gu's first MVC examples where he put LINQ to SQL (another groan?) in the controller.
Where should it go, in order to respect the MVC pattern?
Here is my suggestion:
Create a DAL project to access the data. One possible pattern that works nicely here is the repository pattern. If you utilize the same data type for your keys in all/most tables, you can create a generic repository and then derive individual versions for specific data. Okay, so this one is really old, but looking over it, it still has the high level concepts (https://gregorybeamer.wordpress.com/2010/08/10/generics-on-the-data-access-layer)
Create a core project for the business logic, if needed. I do this every time, as it allows me to test the ideas on the DAL through unit tests. Yes, I can test directly in the MVC project (and do), but I like a clean separation as you rarely find 0% business rules in a solution.
Have the core pull the data from the DAL project and the MVC project use the core project. Nice flow. Easy to unit test. etc.
If you want this in a single project, then separate out the bits into different folders so you can make individual projects, if needed, in the future.
For the love of all things good and holy, don't use the repository pattern. #GregoryABeamer has a great answer in all respects, except recommending you create repository instances to access your entities. Your ORM (most likely Entity Framework) covers this, and completely replaces the concepts of repositories and unit of work.
Simply, if you need something from your database, hit your ORM directly in your controller. If you prefer, you can still add a level of abstraction to hide the use of the ORM itself, such that you could more easily switch out the data access with another ORM, Web Api, etc. Just don't do a traditional unit of work with tens or hundreds of repository instances. If you're interested, you can read a series of posts I wrote about that on my blog. I use the term "repository" with my approach, but mostly just to contrast with the typical "generic" repository approach you find scattered all over the interwebs.
I'd use some kind of 'Repository' layer. Then, my controller calls the UserRepository GetAll method and sends the data to View layer.

Using Repositories and service references in MVC controllers

I'm having some trouble with deciding on a solution for my mvc application.
Background.
We have an EF model which we perform operations on via WCF Services (not data services).
I have an MVC application which has a number of Repositories that talk directly to the Services and return WCF types back to a controller which is calling the repository method, a type called for example WCFUserEntity (it's not actually prefixed with WCF).
Inside the controller I plan to automap the WCFUserEntity to a ViewModel entity.
What is bugging me about this solution is that because i'm returning WCFUserEntity to the controller I have to have a reference to the WebService proxy in my controller which doesn't sit well with me, i'd like my controllers to know nothing of where the repository has got the data from. So another option for me is to do the automapping inside of the repository and return the ViewModel entity to the controller, i can't find much around which supports this idea though, so really what i'm looking for is validation of this 2nd solution or help with a 3rd.
thanks, Dom
You may want to consider a third option.
The use of ViewModelBuilders.
in your controller they would work like this:
var myViewModel = myViewModelBuilder.WithX().WithY().Build();
WithX and WithY would be methods that would add stuff to your viewmodel internally (within the builder, for example WithCountriesList() if you want to add a dropdown showing the countries in your view) and the Build method would return the internal viewmodel after adding all the bits with the WithXXX methods. This is so because most of the time you may want to add lists for dropdowns and things that are not part of your original model (your userEntity in this case).
This way, your controller doesn't know anything about how to build the viewmodel, your repository is also agnostic of viewmodels. All the work is done in the Builder. On the downside, you need to create a ViewModelBuilder for each ViewModel.
I hope this helps.
How I would approach this might require some architecture changes, but I would suggest you approach your WCF API to return ViewModels instead of entities.
For starters, think about bandwidth issues (which would be an issue if you are hosting the WCF in Azure or the cloud). If your ViewModel is only using a few specific properties, why waste the bandwidth returning the other data? In high traffic scenarios, this could cause a waste of traffic that could end up costing money. For example, if your view is only display a user and his questions, there's no reason to send his email, answers, point count, etc.. over the wire.
Another issue to think about is eager loading. By having the WCF service return a ViewModel, you know you have all the data (even when it pertains to related entities) required from the view in one trip to the WCF service. You do not need to get the WCFUserEntity and then ask WCF for WCFDocumentEntities that are related to that specific user.
Finally, if your WCF API is built around ViewModels then you have a MUCH clearer understanding of the business processes involved. You know that this specific request (and view in the system) will give you this specific information, and if you need different information for a different view then you know that it's a completely different business request that has different business requirements. Using stack overflow as an example, it makes it trivial to see that this business process is asking for the current user with his related questions, while this business process is requesting the current user with his related answers.
Using ViewModels in your data retrieval WCF API means that your frontend layers do not necessarily know where the data came from, it just knows that it called a business process and got the data it needs. As far as it knows the data layer connected to the database directly instead of WCF.
Edit:
After re-reading, this actually looks like your 3rd option. Most research on the net don't talk about this option, and I don't know why, but after having some similar frustrations you are having (plus others listed in this post) this is the way I have gone with my business layer. It makes more sense and is actually (imho) easier to manage.

What is the correct layer to configure your IoC container when using a service layer?

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.

Should service layer have access to HttpContext?

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!

Resources