How to access user data within service layer? - asp.net-mvc

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.

Related

On Which Tier should user authentication should exist in n-tier website

I went through different Architecture books such as this one: Microsoft Application Architecture Guide, 2nd Edition
And now I am building a new n-tier website with ASP.Net MVC as Presentation layer.
My question is, If I will use the asp.net Identity, on which tier/layer should I implement the user authentication?
I thought it should be in the Cross Cutting Concerns, because I will need to check if user is authorized or authenticated to access some functions plus I may use the user name on many tiers, such as the Business, Services and Presentation layer.
and also thought it will be better to put it in the Presentation layer specially because the presentation layer is MVC and it will be easy to deal with ASP Identity from there and will allow me to user [Authorize] and [AllowAnonymous] easily.
I know that this question answer depend on many other factors but I am trying here to achieve the most best practice, so need to get your point of view and discuss it.
There are quite a few similar questions here on stackoverflow, and just many answers. Here my view on the matter.
You have to separate the abstraction from the implementation.
The abstraction (an interface) defines the questions you need to able to ask to the authentication service. This interface is used by all other parts of your application that are going to use your authentication service. This means that your abstraction must be defined somewhere that can be referenced by the other parts of your application. My suggestion would be to put this in the business layer, since the methods in the interface (in other words the 'questions that you want to ask to the service') are usually business related. Another suggestion is to put it in a Core layer (if you have one).
That leaves us with the implementation of the interface. I would implement this in the easiest place that you can that works. Can you do it in the business layer, fine. Do you need to use the identity classes from MVC, good too, place it there. It doesn't really matter where you put it, since it isn't used directly.
Of course, to make this all work you do need to use a little Dependency Injection, to register your implementation for the interface.
I have found that this is usually a pretty straightforward answer if you separate the concern of authentication from authorization. Authentication always ends up having to sit in front of presentation. It's a layer in front of the presentation layer. It really has to be.
After authentication occurs, passing that authenticated identity down into the other layers is just another model object, and should be treated as such. Binding authentication/authorization to all the different layers as a cross cutting concern makes your code much harder to reuse in different contexts. Also makes it much harder to test.

should i expose repository to controller when using service?

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.

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.

Should a service layer return view models for an MVC application?

Say you have an ASP.NET MVC project and are using a service layer, such as in this contact manager tutorial on the asp.net site: http://www.asp.net/mvc/tutorials/iteration-4-make-the-application-loosely-coupled-cs
If you have viewmodels for your views, is the service layer the appropriate place to provide each viewmodel? For instance, in the service layer code sample there is a method
public IEnumerable<Contact> ListContacts()
{
return _repository.ListContacts();
}
If instead you wanted a IEnumerable, should it go in the service layer, or is there somewhere else that is the "correct" place?
Perhaps more appropriately, if you have a separate viewmodel for each view associated with ContactController, should ContactManagerService have a separate method to return each viewmodel? If the service layer is not the proper place, where should viewmodel objects be initialized for use by the controller?
Generally, no.
View models are intended to provide information to and from views and should be specific to the application, as opposed to the general domain. Controllers should orchestrate interaction with repositories, services (I am making some assumptions of the definition of service here), etc and handle building and validating view models, and also contain the logic of determining views to render.
By leaking view models into a "service" layer, you are blurring your layers and now have possible application and presentation specific mixed in with what should focused with domain-level responsibilities.
No, I don't think so. Services should care only about the problem domain, not the view that renders results. Return values should be expressed in terms of domain objects, not views.
As per the traditional approach or theory wise, ViewModel should be part of User interface layer. At least the name says so.
But when you get down to implementing it yourself with Entity Framework, MVC, Repository etc, then you realise something else.
Someone has to map Entity/DB Models with ViewModels(DTO mentioned in the end). Should this be done in [A] the UI layer (by the Controller), or in [B] the Service layer?
I go with Option B. Option A is a no no because of the simple fact that several entity models combine together to form a ViewModel. We may not pass unnecessary data to UI layer, whereas in option B, the service can play with data and pass only the required/minimum to the UI layer after mapping (to the ViewModel).
But still, let us go with option A, put ViewModel in the UI layer(and entity model in Service layer).
If the Service layer needs to map to the ViewModel, then the Service layer need to access ViewModel in UI layer. Which library/project? The Viewmodel should be in a separate project in the UI layer, and this project needs to be referenced by Service Layer. If the ViewModel is not in a separate project, then there is circular reference, so no go. It looks awkward to have Service layer accessing UI layer but still we could cope with it.
But what if there is another UI app using this service? What if there is a mobile app? How different can the ViewModel be? Should the Service access the same view model project? Will all UI projects access the same ViewModel project or they have their own?
After these considerations my answer would be to put the Viewmodel project in Service Layer. Every UI layer has to access the Service layer anyways! And there could be a lot of similar ViewModels that they all could use (hence mapping becomes easier for service layer). Mappings are done through linq these days, which is another plus.
Lastly, there is this discussion about DTO. And also about data annotation in ViewModels. ViewModels with data annotations(Microsoft.Web.Mvc.DataAnnotations.dll) cannot reside in service layer instead they reside in UI layer(but ComponentModel.DataAnnotations.dll can reside in service layer). If all projects are in one solution(.sln), then it doesn't matter which layer you put it. In enterprise applications, each layer will have its own solution.
So DTO actually is a ViewModel because mostly there will be one on one mapping between the two(say with AutoMapper). Again DTO still has the logic needed for the UI(or multiple applications) and resides in Service Layer. And the UI layer ViewModel(if we use Microsoft.Web.Mvc.DataAnnotations.dll) is just to copy the data from DTO, with some 'behavior'/attributes added to it.
[Now this discussion is about to take an interesting turn read on...:I]
And don't think data-annotation attributes are just for UI. If you limit the validation using System.ComponentModel.DataAnnotations.dll
then the same ViewModel can also be used for front-end & backend validation(thus removing UI-residing-ViewModel-copy-of-DTO). Moreover attributes can also be used in entity models. Eg: using .tt, Entity Framework data models can be autogenerated with validation attributes to do some DB validations like max-length before sending to the back end. This saves round-trips from UI to backend for validation. It also enables back-end to re-validate for security reasons. So a model is a self-reliant validator and you can pass it around easily. Another advantage is that if backend validation changes in DB then .tt (reads DB specifics and create the attribute for entity class) will automatically pick that up. This can force UI validation unit tests to fail as well, which is a big plus(so we can correct it and inform all UIs/consumers instead of accidentally forgetting and failing). Yes, the discussion is moving towards a good framework design. As you can see it is all related: tier-wise validation, unit test strategy, caching strategy, etc.
Although not directly related to the question. 'ViewModel Façade' mentioned in this must watch channel 9 link is also worth exploring. It starts exactly at 11 minutes 49 seconds in the video. Because this would be the next step/thought once your current question given above is sorted out: 'How to organize ViewModels?'
And Lastly, many of these model vs logic issues could be resolved with REST. Because every client can have the intelligence to query the data and get only the data that it needs. And it keeps the model in UI, there is no server/service layer model/logic. The only duplication then will be on the automated tests that each client need to perform. Also if there are changes in data then some clients fail if they do not adapt to the change. The question then is, are you removing service layer altogether(and the models they carry) or pushing the service layer up to your UI project(so model issue still persists) which calls the REST API. But in terms of the responsibility of Service layer, they are the same regardless.
Also in your example "_repository.ListContacts()" is returning a ViewModel from repository. This is not a mature way. Repositories should provide entity models or DB models. This gets converted to view models and it is this view model that is returned by the service layer.
This has come a bit of an "it depends" where I work - we have generally had a controller consuming some service(s) - then combining returned DTO's into a 'ViewModel' that would then get passed to the client - either via JSON result, or bound in the Razor Template.
Thing is, about 80% of the time - the mapping of DTO to ViewModel has been 1-1. We are starting to move towards 'Where needed, just consume the DTO directly, but when the DTO and what we need in our client/view don't match up - then we create a ViewModel and do the mapping between objects as needed'.
Although I'm still not convinced that this is the best or right solution - as it ends up leading to some heated discussions of 'are we just adding X to the DTO to meet the needs of the view?'
I suppose that depends on what you consider the "services" to be. I've never really liked the term service in the context of a single class; it's incredibly vague and doesn't tell you much about the actual purpose of the class.
If the "service layer" is a physical layer, such as a web service, then absolutely not; services in an SOA context should expose domain/business operations, not data and not presentation logic. But if service is just being used as an abstract concept for a further level of encapsulation, I don't see any problem with using it the way you desribe.
Just don't mix concepts. If your service deals with view models then it should be a presentation service and be layered over top of the actual Model, never directly touching the database or any business logic.
Hi I see very good answers here.
And for myself I do an other aproach.
I have to kinds of models , one is viewmodel and the other is shared models. The viewmodels stays on the UI layer and the shared models stays on a separate project.
The shared models can theoretically be used anyware because those are standalone.
This models provides some abstraction if you want to return specific data from your service layer or if you need something specific from your repository.
I don't really know if this is a good aproach but it works so well on my projects. For example
When I need to provide some information to create new objects to the database i can use the shared models directly to the service layer it saves me some complexity.
The shared models needs to be mapped sometimes , but you can ensure that your service is not leaking inesssary data to the UI.
You can see shared models as an extension but not to build your UI logic with it, you should have viewmodels to do that.
You can combine viewmodels with this shared models to save you time you can use inheritance.
The shared models has to be neutral and should not have any kind of logic.

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