I have created a service that allows me access a controllername,actionname & header values from HttpContext.Current
Its working currently however I am trying to test the service and discovering using HttpContext within the service might be a bad idea as my service layer needs to be fully aware of HttpContext
e.g.
public virtual string GetControllerName()
{
return HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString();
}
I then thought of passing the request through as a paramater but again this doesnt feel right.
public virtual string GetActionName(HttpRequest request)
{
return request.RequestContext.RouteData.Values["action"].ToString();
}
Can anyone provide and guidance on how my service should be setup to allow me to achieve what I need?
If your service class is "aware" that there is a controller and an action, then it knows it's being called during an HTTP request to a controller. If that's the case then it's not decoupled from the controller - in other words, that service can't function if it's not called while servicing a request. Because if it was, there couldn't be a controller or an action.
So from that point of view, it doesn't matter too much that the service is depending directly on the HttpContext, because it's coupled to it either way.
Does the service class actually need those specific values, or is it just performing some logging and you want to know what called it?
If it depends on those values then you could create an interface like
interface IControllerContextProvider
{
string ControllerName;
string ActionName;
}
Then have an implementation like
public class HttpContextControllerContextProvider : IControllerContextProvider
{
//implements the interface by returning values from HttpContext.Current
}
If the service itself doesn't need those values in order to function (maybe it's just logging) then you could use an interceptor (see PostSharp, Windsor, others) and when you inject your service into your controller, the interceptor "intercepts" the call, does your logging, and then continues with the original method call.
The interceptor is a class written for that specific purpose, so it makes sense for it to be coupled to your HttpContext. But the benefit is that if the details about the controller and action aren't really relevant to the main purpose of your service class then the interceptor provides a way to keep that code out of your service class.
That's done a lot with exception logging. If a class isn't going to actually handle exceptions then there's no need for it to contain code to log errors, since that's not the purpose of that class. Interceptors let us create those behaviors but keep them separate from classes that don't care about them.
Related
i am new to building API's, and right now i'm trying to build my first application. I would like to keep architecture of my application compliant with the design patterns as much as possible. I have a service layer, services are injected to the controllers, and are responsible for communication with the repositories. I would like to split some of my logic located in controllers to make my code more clean.
As an example i have a controller:
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
private readonly IUserService _userService;
public UsersController(IUserService userService) : base()
{
this._userService = userService;
}
[HttpPost("authenticate")]
public async Task<IActionResult> AuthenticateUserAsync(AuthenticationDTO authentication)
{
var user = await _userService.AuthenticateUserAsync(authentication.Username, authentication.Password);
var tokenString = .....
}
...
}
I would like to create a method responsible for generating authentication token. Where do i have to locate such a logic? Should i place it in UserService, or maybe write in in UsersController class? Can i write private methods in controller classes, or maybe Controllers should only contain methods exposed through an api interface?
Rest-Api - Think in resources.
This question is all about the way you think about your rest-api (if you are building one). There are differences between rest apis, web apis and SOAP, but I'll assume that you are building a rest-api.
In case of a generic web api, you'll have to decide the way to break down your application into multiple controllers.
Check Microsoft Rest-Api guide. The most important section out of this is:
Organize the API around resources
So in your example, let's assume that your resource is the user session. Then you can have a UserController with the appropriate verbs, where you can Create (POST) Update (PUT/PATCH) Delete (DELETE) or retrieve (GET) the User resource.
Now you need a session, don't you? Or a Token. Easy:
TokenController and the action is of course (POST) - Create token with username and password
SessionController - Create a token.
This way you will minimize the actions. As an extra, if the User has Accounts, then create a new controller called UserAccountsController that will be server by a rest url like users/1/accounts GET
Services layer
Having a services layer where you have all your business logic is the way to go. Keeping in mind the SRP (single responsibility principle), the one and only responsibility of the Controller, is to control the code flow for the Http response creation and coordinate the actions to do so.
The actual business logic should be implemented in a service layer. This way, you'll have controllers that even with multiple actions will be quite minimal (4/5 rows per action).
User inheritance
Common logic between the controllers can be achieved by using a MyApiController: ControllerBase that contains reusable code.
DON'T use Helper classes. It's an antipattern. Utility classes are evil is an excellent article on the matter.
Just place that kind of helper classes or methods into some folder called Infrastructure for example.
For this example, just create interface ITokenGenerator with Generate() method, create it's implementation class TokenGenerator and simply inject it in controller.
Technically, the compiler allows you to write private method in controller. It just like a normal class. However, you should put everything on service, so you de-couple the logic from controller. (For example, later, you can easily migrate your logic to different UI such as MVC instead of web API)
In your example, the token generating should not be in controller or userService. I think the best is to have TokenGenerator service.
I am working on an asp.net mvc application that does not have DI or unit testing yet. So I started to restructure the application to have unit tests by spliting the application into 3 layers: Controllers - Services - DataAccess.
Some of the controllers were using the Session and the Cookies to store and retrieve values. So I create an interface and a class that deals with saving and retrieving values from Session and Cookies.
I did this only by using unit testing and never run the application.
Since the application did not had DI I created on the contructor of the controller the ContextService by giving as an input parameter the HttpContext of the Controller.
However when I run the application the values were not retrieved or saved in the Session or Cookies. It seems that the HttpContext is null on contructor.
Question 1:
How should I deal with my ContextService. Should it use the static property HttpContext.Current in order to access the session and cookies (how will it be unit tested) or ...?
Question 2:
If you know another solution how should it be adapt in order to have also DI in the future.
I created on the contructor of the controller the ContextService by giving as an input parameter the HttpContext of the Controller.
By passing the HttpContext from the controller to the service, you make the controller responsible of the creation of that service. This tightly couples the controller with the service, while loose coupling is the goal.
hould it use the static property HttpContext.Current in order to access the session and cookies
how will it be unit tested
It won't. This is an important reason why we create abstractions. Some parts in our system can't be unit tested and we want to be able to replace them with fake implementations that we use under test.
The trick, however, is to make the replaced part as small as possible, and preferably don't mix it with business logic, since replacing that will also mean you won't be testing that logic.
You should hide access to the HttpContext.Current behind an abstraction. But when you do that, make sure that you define the abstraction in a way that suits your application best. For instance, take a close look at what it is that your ContextService wants. Does it really want to access cookies? Probably not. Or does it want to the name or ID of the currently logged in user? That's more likely. So you should model your abstractions around that.
As an example, define an abstraction that allows application code to access information about the logged in user using a IUserContext:
public interface IUserContext
{
string UserName { get; }
}
One possible implementation of this abstraction is one that retrieves this information from an HTTP cookie:
public class CookieUserContext : IUserContext
{
public string UserName => HttpContext.Current.Cookies["name"];
}
But you can easily imagine other implementations, for instance when that same application code needs to run outside the context of a web request, for instance as part of a background operation, or an isolated Windows service application. This is another important reason to introduce abstractions—whenever the same code needs to be able to run in different environments.
If you're interested, the book Dependency Injection in .NET, by Mark Seemann, goes into great detail about these kinds of patterns and principles, such as reasons for applying DI, preventing tight coupling. The second edition of this book, by Seemann and myself, even goes into more detail about the things you are struggling with, such as preventing leaky abstractions, how to separate behavior into classes, and designing applications using the SOLID principles. The book's homepage contains a download link for the first chapter, which is free to download.
I am using simple injector for my web api project. I have a service which requires a session token in order for it to instantiate.
public class CustomerService
{
public CustomerService(Auth auth, IRepositoryFactory repositoryFactory)
{
// make post call to another web api for validation
SomeWebApiCallToValidateAuth.vaildate(auth);
}
}
So for this service, it requires an auth token and a repositoryFactory. I want it to be able to inject the auth parameter (which comes from the http web request) and at the same time to resolve the repository factory with the specified implemented thats registered to the container.
But I am not sure how to register this with simple injector or if there is a way around it. Any help would be great. Thanks.
Your current approach has several downsides:
You inject runtime data into the constructor of your component, which can lead to complications.
You make use of an Abstract Factory, which is often not the best abstraction.
Your constructor invokes validation, while it should do nothing other than storing its incoming dependencies. This way you can compose your object graphs with confidence.
Concerning the factory: Inject an IRepository rather than an IRepositoryFactory. This might require you to hide the real repository behind a proxy, as explained here.
Concerning the Auth value, it depends on the need, but if the Auth value is an important part of the API of CustomerService, this justifies adding Auth as argument on the methods of CustomerService. If it is an implementation detail, inject an IAuthProvider abstraction of some sort that allows you to retrieve the value at runtime (after the object graph is built). Again, this all is described in this article.
I have a question about the standard way to perform a restful update.
We have a restful Api, with an update URL like the following :
put /jobs/{jobUid:guid}
The signature in the restful controller is:
UpdateJob(Guid jobUid, [FromBody] UpdateJobOperation job)
Our UpdateJobOperation class has all the same properties as our Job class except for the Id (Guid) is not in the UpdateJobOperation class.
Inside this update method, we map the UpdateJobOperation to our Job business object, then we call update on the service layer and pass in the job. The job object has a Guid Id property on it. So my question is the following :
should the signatures of our update on the service layer and our update on repository layer (service will do business logic then call update on repository) be like:
UpdateJob(Job job)
OR
UpdateJob(Guid jobUid, Job job)
If we use single Job parameter, obviously we need to set the JobUid property on the Job before calling UpdateJob on the service.
Obviously both methods work but I have been unable to find if there is a best practice on service/repo updates.
What are your recommendations?
Thanks!
Without risking a religious argument...
Strictly from a restful API point of view a PUT is for updating a resource that you have an id for. In this sense you API interface is fine. At your service layer I would be tempted to use the Update(Job job) signature as this can be re-used for you POST operation.
Your current implementation is correct. Especially, since if you were to get rid of the jobUid parameter you would end up with the end point put /jobs This could be mistook for an end point that updates multiple jobs as opposed to a single one.
An architectural question. I've got a nicely de-coupled MVC3 solution with a few projects that's working rather well.
Proj.Core - interfaces for data classes and services
Proj.Services - interfaces for model services
Proj.Data.NH - implementations of the data interfaces
Proj.Services.NH - implementations of the data / model services
Proj.Infrastructure - setting up Ninject and NHibernate
Proj.Tests - unit tests
Proj.Web - the MVC project
I've set up NHibernate to be session per request in the infrastructure project, so Proj.Web doesn't need to reference NHibernate (or Ninject, for that matter). I'm now introducing SignalR, which works really nicely for a quick chat app. I've put a SignalR hub in the web project. I now want to persist the chat messages in the database, which has confused me somewhat.
I want to use a service (let's call it PostService), so the SignalR hub doesn't have a dependency on NHibernate. My other services are injected into the controllers' constructors, and the session is injected into the services' constructors.
As the SignalR hub hangs around, unlike controllers, PostService (injected into the constructor as an IPostService) can't have a session injected into its constructor, as there won't be a session. If there was, it would hang around forever, which would be far too long a time for a transaction.
I could inject the session factory into the PostService, and each method could use a transaction, e.g.
private void WithTransaction(Action<ISession> action)
{
using (var session = _sessionFactory.OpenSession())
using (var tx = session.BeginTransaction())
{
action(session);
tx.Commit();
}
}
public IPost Post(string message)
{
WithTransaction(session =>
{
session.Save(new Post(message));
});
}
The hub will then call _postService.Post(message);
However, once the Post method does more things, I'll want to use some of my existing services to do the things, as they've already been written and unit tested. As the session is created in the method, I can't have the services injected into the PostService constructor, as they accept a session into their constructors.
So, I guess I have the following options, but I'm not sure if a) this is a complete list, or b) which is the best option:
I. Inject an IDependencyResolver into the PostService constructor, and create the services I need in the Post method, passing in the session to the constructor. There's an IDependencyResolver in System.Web.Mvc and in SignalR, so this would (depending on which project PostService resides) introduce a dependency on either library.
II. Modify the services so each method that uses a session has one passed in as a parameter. Overload this without the session parameter, and call the new one. The MVC service calls would use the first, and the PostService would use the second e.g.
public void SaveUser(IUser user)
{
Save(_session, user);
}
public void SaveUser(ISession session, IUser user)
{
session.Save(user);
}
III. Don't use the existing services. Have the PostService do it's own thing, even if there is a bit of duplication (e.g. getting user details etc.)
IV. Remove the ISession from the services' constructors, and pass it in to each method (and deal with the Controllers' accordingly.
V. Something else.
I guess I'm leaning towards the first one, but I'm not sure where PostService would live. If it goes in Proj.Services.NH, then I'd have to introduce a dependency on System.Web.Mvc or SignalR, which I don't want to do. If it lives in Proj.Web, then I'd have to introduce a dependency on NHibernate, which I also don't want to do. It doesn't belong in Proj.Infrastructure, as it is application code. Should it have it's own project with dependencies on everything, or is there a better way?
I would use some sort of auto factory for the additional services you need. So you would write your PostService constructor as:
public PostService( Func<INeededService1> factory1,Func<INeededService2> factory2 ...)
{
...
}
and then use this extension to have these factory automatically working ( by querying the container ).