Best architecture design using service layer and interacting services? - c#

I have several services that are currently highly decoupled. Now I have to extend them and they need to depend to access each other.
Let's say I have 4 services: EmailService, HouseService, UserService, PriceService. Each user has an email address and each user belongs to a house.
I want to send an email to each user about the price of the house that they are connected to. So in the EmailService I have SendEmailToAddress(string email, string text), in PriceService I have GetHousePrice(int id), in HouseService I have GetUsersInHouse(int id) and in UserService I have GetEmailOfUser(int id).
What would be the best approach to send an email to all the users from the HouseController? Should I just init all the services in the controller action and call each one in order or should I use the Mediator pattern? If I should use it, it would probably contain only one method so it seems a bit of an overkill. Also if I use it everywhere should I create different mediators for each service connection or should it be only one class that has all my services as private properties and then in the methods use only the once I need for a specific action? If I go with the Mediator pattern should I use it in every controller or should I stick with the bare services where they don't need to interact together (e.g. if I only need a list of houses I think it's probably best to just get them directly from the service object instead of the Mediator)?

Given that your services aren't actually needing to communicate with each other, you just need to call various methods on each and use the return values to complete a higher level task, I don't think the Mediator pattern is appropriate here.
For example, its not like you need the HouseService to manipulate the state of objects managed by the PriceService...you just need data from the PriceService that the HouseService provides input for:
var houseId = houseService.GetIdOfHouse(someCriteria);
var price = priceService.GetPriceOfHouse(houseId);
Instead, I think what you need to implement is the Facade pattern, which will:
Provide a unified interface to a set of interfaces in a subsystem. Façade defines a higher-level interface that makes the subsystem easier to use.
Good example of Facade pattern can be found on the dofactory.com site:
http://www.dofactory.com/net/facade-design-pattern
Here's what I would consider doing:
public class NotificationFacade
{
private IPriceService _priceService;
private IHouseService _houseService;
private IUserService _userService;
private IEmailService _emailService;
public NotificationFacade(IPriceService priceService, IHouseService houseService, IUserService userService, IEmailService emailService)
{
_priceService = priceService;
_houseService = houseService;
_userService = userService;
_emailSerice = emailSerice;
}
public void NotifyUsersAboutPriceForHouse(int houseId)
{
var price = _priceService.GetHousePrice(houseId);
var users = _houseService.GetUsersInHouse(houseId);
foreach(var user in users)
{
var emailAddress = _userService.GetEmailOfUser(user);
_emailService.SendEmailToAddress(emailAddress, "Your House Price is:" + price);
}
}
}
In your controller:
public HouseController
{
private NotificationFacade _notificationFacade;
public HouseController(NotificationFacade notificationFacade)
{
_notificationFacade = notificationFacade;
}
public void SomeActionMethod(int houseId)
{
_notificationFacade.NotifyUsersAboutPriceForHouse(houseId);
}
}
The dependencies should be resolved using Dependency Injection with a container such as Unity, Ninject, StructureMap or something similar...

You could create a workflow service that contains the actual logic to look up the information and send the mail using the existing services.
This service is then called from your HouseController. You could use the service directly as a class library or expose it as a WCF service; but it depends on your requirements.
This way your entity services remain loosely coupled, and all of your cross-service logic is in a dedicated component.

As I was looking for best practices since past couple of days in ASP.Net MVC and I concluded that our services should contain all business logic ( using repositories of different domain models) and expose public methods that are accessible by controller.
In your case you should create a new service and put the whole logic of calculation and sending email in a method of that service. So that your service will work like a black box. Other developers (who work on your project) don't need to know that how thing are managed in that method. All they need to know is to call that method with required parameter and handle response.

Just create HouseServiceFacade that contains the services you need. In this facade you can put all methods for the controller.

Related

Why do the clients create the repositories?

Please see the code below, which I took from Jimmy Bogards Wicked domain models:
public class OfferAssignmentService
{
private readonly IMemberRepository _memberRepository;
private readonly IOfferTypeRepository _offerTypeRepository;
private readonly IOfferValueCalculator _offerValueCalculator;
private readonly IOfferRepository _offerRepository;
public OfferAssignmentService(
IMemberRepository memberRepository,
IOfferTypeRepository offerTypeRepository,
IOfferValueCalculator offerValueCalculator,
IOfferRepository offerRepository
)
{
_memberRepository = memberRepository;
_offerTypeRepository = offerTypeRepository;
_offerValueCalculator = offerValueCalculator;
_offerRepository = offerRepository;
}
public void AssignOffer(Guid memberId, Guid offerTypeId)
{
// Retreive
var member = _memberRepository.GetById(memberId);
var offerType = _offerTypeRepository.GetById(offerTypeId);
// Delegate to business objects
var offer = member.AssignOffer(offerType, _offerValueCalculator);
// Save
_offerRepository.Save(offer);
}
}
Why are the repositories injected into the service? Say I have an app, which has four clients (mobile; WPF; MVC4; Win Forms), then all these clients have to create instances of these repositories and pass them to the service. Why does the service not just create them i.e. in one place.
I am obviously missing something here.
Update
If I create the repositories in the Serivce layer then their are four dependencies i.e. one for _memberRepository; one for _offerTypeRepository; one for _offerValueCalculator and one for _offerRepository. If I create all these instances in the four clients then I am creating 16 dependencies i.e. 4*4. I realise I am missing something fundamental here.
Your individual clients shouldn't be responsible for knowing how to configure these dependencies in detail. If your client depends on OfferAssignmentService then it shouldn't be responsible for knowing about all of the dependencies for that class, like the repositories, and the dependencies of those repositories, etc. If that code is duplicated wherever OfferAssignmentService is used then that can be improved.
Ideally there would be a single configuration class which serves as the composition root for this service layer, and that class would be referenced and used by clients to configure the dependencies for your service. The specifics vary depending on the container you're using. For example, with Windsor I would create a class that inherits from AbstractFacility. My client would simply do this:
container.AddFacility<OfferAssignmentServiceFacility>();
That facility would handle configuring all of the dependencies with my container.
In Unity it would be a class that inherits from UnityContainerExtension, and very similar to Windsor, you would do
container.AddNewExtension<OfferAssignmentServiceExtension>();
What they have in common is that they pass the container to the configuration class, allowing that class to configure the container with the dependencies it needs.
If you don't mind your service being tightly coupled to a container framework you can put that code directly in your service library. I like to make my libraries container-agnostic (they don't need one particular brand of DI container to work.) So I'll put the facility or extension in a separate library.

What to prefer: abstract class or interface when using services (e.g. app42, facebook, google+ etc.) and IoC

Recently I discovered DI for myself and SOLID principles so now I started my project and it often uses social services so I want to follow that principles to create a good architecture.
Let's say, I have a login page where the user can login with social services credentials, or using login and password registered earlier. According to DI I must have an abstraction which 'promises' the needed functionality but for me the problem is that App42 login method requires login and password but some other service (e.g. facebook) don't or may not. I could possibly create separate interface for App42 and facebook but this is not the case because the more services I would like to use in future (e.g. Twitter) the more interfaces I would have and the links to them in login page would grow.
public interface ICredentialsAuthenticatable
{
void Login(string username, string password, Action<IUser> successCallback = null, Action<IServiceException> failCallback = null);
void Logout(string sessionId, Action<IServiceResponse> successCallback = null, Action<IServiceException> failCallback = null);
}
public interface IScopeAuthenticatable
{
void Login(string scope, Action callback = null);
void Logout();
}
Plus, different services should initialize themselves in different ways:
App42API.BuildUserService(); for App42 or FB.Init(); for facebook.
What should I use: abstract class or interfaces in this situation in order to follow SOLID principles and have only Authenticatable or IAuthenticatable type in login page?
How should I treat third party plugins here to adopt them to this architecture? Because I can't change their's source code.
Thank you.
First, you won't change implementations of other services. Instead, you will provide Adapters. Each adapter will implement your interface but internally will use another implementation.
Then, in case of any differences, you can introduce an object parameter:
void Login( LoginParameters parameters, ... )
and then have
public class LoginPasswordParameters : LoginParameters ...
public class SmartCardParameters : LoginParameters ...
or even just have your LoginParameters flexible enough
public class LoginParameters
{
public List<Tuple<string, string>> Parameters ...
so that instead of a class hierarchy, you have a class that holds key-value pairs of all possible login parameters.
When it comes to this specific activity, logging using common identity providers, you don't have to invent your own interfaces. This is because most providers implement the very same OAuth2 protocols and there are already implemented solutions where both abstractions and implementations are already available. Take a look at the DotnetOpenAuth library for example.

Dependency injection based on configuration?

I am working on an app which uses active directory to retrieve users. Sometimes I need to work on the app but AD is not available. I use a wrapper class to retrieve the AD user. I would like to inject a different class based on the configuration. I was thinking on using an appSetting that would tell me the current configutarion and decide what type to use when injecting. Is it possible to get the current configuration without using a Web.config transform? Is it possible to inject objects using Unity based on Web.config transformations? Can you recommend a better approach?
[UPDATE]
I have a user repository class that loads the users from AD. All I need is to be able to change the implementation of this repository class so that when AD is unavailable I can load the users a different way. This would only be used for development, production would always access AD and retrieve users.
You can use preprocessor directives:
#if DEBUG
// register fake repository
#else
// register AD repository
#endif
Well, Dependency Injection is incredibly powerful, agile, and creates a separation of concerns. The pitfall in your approach will come from validation. You see, with this approach you have to choose a concrete implementation.
So how will you call those two classes?
public class LogToText : ILogger
{
public void LogMessage(string message) { }
}
public class LogToEvent : ILogger
{
public void LogMessage(string message) { }
}
You have these two implementations, but when you pass the interface to:
public class AD
{
public AD(ILogger logger) { }
}
So the question will be do you feel that you can properly validate to choose the proper implementation effectively. Otherwise, Dependency Injection may not work well. We don't entirely know the usage or goal, so our advice may not be truly beneficial. Hopefully you see what I mean, because you'll have to see if you can't test a particular way.
You could use an Abstraction for this:
public interface IPersonService
{
IEnumerable<Person> Find(PersonSearchParameters searchParams);
Person GetByAccountName(string accountName);
[ETC...]
}
Then both your AD and Development implements this interface.
To make things easier, I suggest using StructureMap IoC, so you can easily do this:
x.For<IPersonService>.Use<ActiveDirectoryPersonService>(); //for production
or
x.For<IPersonService>.Use<MockPersonService>(); //for development
When using this you can, for instancce:
public class TestController : Controller
{
IPersonService _service;
public TestController(IPersonService service)
{
_service = service;
}
}
Instead of using an XML file for configuration in this case, I suggest using the Fluent code of Structure Map, it's better when refactoring and to avoid mistyping because it compiles.
StructureMap:
http://structuremap.net
Easy Installable via NuGET
A different approach would be to use the build configuration, read back from the assembly.
var buildConfiguration = typeof(Program).Assembly.GetCustomAttribute<AssemblyConfigurationAttribute>()?.Configuration;
if (buildConfiguration == "Debug")
{
// register fake repository
}
else
{
// register AD repository
}
Then it is safer to apply refactorings or automatic code clean up (e.g. ReSharper etc.). Depending on your current configuration, code cleanup can otherwise remove unused usings. What then leads to build issues if an other configuration is used.

Injecting host from HttpContext into Service layer

I need to apply filtering by requesting host name on all database calls in my Web API service.
This filtering works like so:
lookup the Site to profile against based on the requesting hostname
Apply Site.Id on all subsequent data access calls made in the request
Essentially a global filter so so that data returned by the API service is always contained to the host.
One solution would be to pass the host name in as an argument on all my service methods like so:
public IEnumerable<Profiles> GetProfiles ()
{
var host = HttpContext.Current.Request.ServerVariables["SERVER_NAME"];
return profilesService.Get(host);
}
But since this is a consistent rule on all requests I would like to come up with a more elegant way to handle this so my service calls are just profileSerivce.Get();
I think I need to inject a ISiteLocator into my service layer that has either the host name or even better the Id already retrieved from the database that I can then apply. But I'm struggling with this on how and where I can reference the HttpContext to get the host name and also if it was possible to optimise this using StructureMap lifecycles.
I think I need to inject a ISiteLocator into my service layer
It seems to me you are heading into the right direction.
I'm struggling with this on how and where I can reference the
HttpContext
This is really simple actually. Define the ISiteLocator in your business layer and define an AspNetSiteLocator implementation into your ASP.NET web application, preferably close to (or inside) your Composition Root. That implementation might look like this:
public class AspNetSiteLocator : ISiteLocator
{
private readonly ISiteRepository siteRepository;
public AspNetSiteLocator(ISiteRepository siteRepository)
{
this.siteRepository = siteRepository;
}
Site ISiteLocator.GetCurrentSite()
{
return this.siteRepository.GetById(CurrentHostName);
}
private static string CurrentHostName
{
get
{
return HttpContext.Current.Request
.ServerVariables["SERVER_NAME"];
}
}
}
that has either the host name or even better the Id already retrieved
from the database
Try to let your ISiteLocator return data in a way that is most convenient to the consumers of that locator. In my example I returned a Site entity (if you have such an entity in your domain). This is probably more convenient than the host name or the Id, since consumers possibly have to query for the site again thereselves. However, perhaps Id is the most convenient, but that's up to you to find out.
how [...] to optimise this using StructureMap lifecycles
The implementation above doesn't have any state, so it can be registered with any lifetime; singleton for instance. However, every call to ISiteLocator.GetCurrentSite() will result in a new request to the ISiteRepository, which can cause too much overhead. In that case you probably want an implementation that stores the Site in a private field and always returns that instance. In that case you shoud register that implementation on a 'Per Web Request' basis (since the SERVER_NAME will not change during the request).

Repository pattern for common items

Hi there i am new to the repository pattern. I would like to have feedback on the approach i am following.
Requirement : Build the menu for the user that is currently logged in.
My Solution :
I created a Service, that will be called by the controller to get the menu items.
public interface IApplicationHelperService
{
List<Menu> GetMenuForRoles();
}
The implementation for the service
public class ApplicationHelperService : IApplicationHelperService
{
private readonly IMenuRepository _menuRepository; //this fecthes the entire menu from the datastore
private readonly ICommonService _commonService; //this is a Service that contained common items eg. UserDetails, ApplicationName etc.
public ApplicationHelperService(IMenuRepository menuRepository,ICommonService commonService)
{
this._menuRepository = menuRepository;
this._commonService = commonService;
}
public List<Menu> ApplicationMenu
{
get
{
return _menuRepository.GetMenu(_commonService.ApplicationName);
}
}
List<Menu> IApplicationHelperService.GetMenuForRoles()
{
return ApplicationMenu.Where(p => p.ParentID == null && p.IsInRole(_commonService.CurrentUser.Roles)).OrderBy(p => p.MenuOrder).ToList();
}
}
Then the CommonService (used for common items needed in the Services eg. CurrentUser
public interface ICommonService
{
IUser CurrentUser { get; }
string ApplicationName { get; }
}
On the class the implements the ICommonService, i get the current user using the context, in other words my service layer does not know about the HttpContext, since there is a possibility that this might by used for another type of application in the future. So this way i can handle by Current User differently for all applications, but my Service Layer will not mind.
So what you should give feedback on is, is this approach to inject this kind of common service into all services a good approach or is there another way of doing this, the reason i ask, is at a later stage i will need the current user's details for auditing purposes or whatever reason presents itself.
Hope this makes sense to someone. :-)
We are using a similar approach. The difference is that, we do not have a CommonService object injected into each service.
We are using WCF and we have written an extension to OperationContext to store Username etc. The properties defined in this extension can be accessed using static method calls. It has an advantage over CommonService implementation; since you are employing IOC, there is not direct way to pass parameters into CommonService in each service call. For instance, if you are sending the username on the WCF calls, you need to set the value of CurrentUser in each constructor.
I do not know whether you are planning to use WCF; but the point is that: if you need to pass variables to your CommonService, you will endup with populating this values inside each constructor. If you are not planning to pass variables, then you can just create a base class for your services and force the developers to use this base class.
Also, you should set the lifetime manager of CommonService as UnityPerResolveLifeTimeManager, in order not to create a new instance in each constructor.Otherwise, you may endup with having different instances in each Service.

Categories