Domain Service that consumes external system - .net-core

I am trying to implement an Employee Management System using DDD approach. The system is built using .Net Core. I have several Projects created for this system (UI, Application, Domain, Infrastructure). Now inside my Domain Layer, I have an Employee entity (that's the Aggregate root of Employee aggregate). The business requirement is that whenever an Employee is created, I need to do a Credit Check, and based on the result I am supposed to update a property called "IsCreditCheckDone" for the Employee entity. The Credit Check service is basically an external Rest Service. I am thinking to create an Interface called ICreditCheckService inside Domain.Services.Interfaces folder. I am thinking to do the implementation of ICreditCheckService in the Infrastructure layer inside the service folder. Also, ICreditCheckService will be injected into the Employee class and the Dependency will be mapped inside the Startup class of the UI project.
My question is, is it the correct approach to handle the Domain Service when it consumes the external systems? Or should it be done differently?
EMS.Domain
Entities
Employee.cs
Services
Interfaces
ICreditCheckService.cs (This will be injected to Employee entity)
EMS.Infrastructure
Services
CreditCheckService.cs (this service will make an http call to external Rest API)

In general, I think your design is good.
Two points, however:
Terminologically, The service that invokes an external api is not considered to be a domain service (a domain service runs logic that involves several entities). It is more like a repository.
Repository services should be injected not into entities but into application (use-case) services. For example, an application service invokes your credit-check service, then creates an employee entity passing to its ctor the boolean result.

Related

Understanding Symfony2 services

I'm quite new to Symfony 2 and I'm moving to advanced topics like services. When should an object be a service?
For example, say that you have a facade object for making a call to a REST service. This class needs a username and password. Would it be correct modeling that class as a global service? Even if it's used only in a portion of the whole project?
# app/config/config.yml
parameters:
my_proxy.username: username
my_proxy.password: password
services:
my_proxy:
class: Acme\TestBundle\MyProxy
arguments: [%my_proxy.username%, %my_proxy.password%]
Definition taken from the Symfony2 glossary:
A Service is a generic term for any PHP object that performs a specific task. A service is usually used "globally", such as a database connection object or an object that delivers email messages. In Symfony2, services are often configured and retrieved from the service container. An application that has many decoupled services is said to follow a service-oriented architecture.
I think your example is a perfect candidate for a service.
You don't want to copy construction code to all places you need your API client. It's better to delegate this task to the dependency injection container.
This way it's easier to maintain (as construction happens in one place and it's configurable).
It's also more flexible as you can easily change the API client class without affecting code which uses it (as long as it implements the same interface).
I don't think there's a golden rule. But basically all classes implementing a task are good candidates for a service. Entities on the other hand are not as they're most often just data holders.
I always recommend Fabien's series of articles on the subject: http://fabien.potencier.org/article/11/what-is-dependency-injection
Yes, because this will spare you the configuration part. You're not going to fetch the username and password and give it to the constructor each time you need this class.

referencing a class as a web service

Whats the best way to implement this.
I am building application that will be hosted as a web service. This app takes an employeeID and returns an employee object that contains lots of info regarding the employee. (name, status, full-time/part-time, etc)
I want the two existing apps we have (and more to come) to be able to call a method that the web service will have and return the employee object. (also at time this web service that returns the object may have new fields added to it - Pay rate, etc)
How would I go about creating a new object from this web service reference in the existing applications.
Would I decalre it like Dim Employee as new emp_webservice.employee ?
And then be able to use this object within the app? Or would the better practice be to also included the same class files? It seems like this would not be the way to go, since if I make a change to that class I then have to make it in all places
Thanks for any clarification on this.
When you add a reference to a web service in a .net application, the objects exposed by that web service exist in the namespace that you created for that web service when it was added to your application.
So, any reference to classes from that web service would need to reference the namespace for that web service, as you have indicated. You could also have an Imports WebServiceNameSpace if you don't want to fully qualify every class.
You can't really include the class files if you are using the automatic web service interface generation functionality that VS.Net provides.
Also, if you change properties in the web service, those updated properties won't be propagated to the client until you update the web service reference in your project.
Finally, if you want to add methods or additional properties to the web service classes on the client side, you can use Partial classes.
For example, let's say that the web service only provides an hourly pay rate, but I want to show a weekly salary in the client. I can extend the web service class as follows:
Namespace emp_webservice
Partial Public Class employee
Public Function GetWeeklyPayRate() As Decimal
Return Me.HourlyRate * 8 * 5
End Function
End Class
End Namespace

what is the best Session management opt ion for Asp.net mvc - wcf - BLL - Nhibernate repository

I have an application architecture which has following layers (or c# projects).
web front end (asp.net mvc2)
service layer (normal c# class library)
Model layer (normal c# class library with entities, service and repository Interfaces)
Data layer (implements repository interface defined in BLL and uses NHibernate)
ISession is opened per http request and its working fine.
Now, I would like to add wcf layer on top of my current service layer. wcf project plainly calls original service layer classes. But as soon as I do this, the session/session factory at asp.net becomes unusable/unavailable. Looks like, wcf is running in totally different context than asp.net. Hence I would like to move the logic of initinializing session factory and session management to wcf. How should I do it? and even before is it a good practice? one of the reason I would like to add wcf is because I want to expose the operations to other applications (which may not be http based).
Any help, blog post or book reference would be greatly appreciated.
Use Per-call instancing of NHibernate session. Check this article. It explains how to create attribute which will attach Session to current instance context.
you probably want to have WCF running in the same context as asp.net... try this article:
http://msdn.microsoft.com/en-us/library/aa702682.aspx

Is the singleton in ASP.NET per session or per machine?

I have an web application written in ASP.NET (FW 3.5) (along with some VBScript, this is a legacy app) that uses a utility class in the backend that logs error.
I need to log several values that a user has entered in the front-end.
Since the utility class has no access to the front end (or any HTTP services),
i created a singleton class within the utility namespace that my front end UI can access and store information about the user.
I guess more specifically, I am wondering if there's a way to store session variables that can be shared across the web application and web services through a class referenced by both of the application and web services. For example, I have an error handling class that is used by both instances that required information about the user. Is there a way to create a per-session singleton to hold that information, so that my error class will have access to the user info? or is this not possible - that i'll need to pass the information around as they are needed?
If your singleton implementation uses a Shared variable, your instance will be unique within a single AppDomain.
That said, I would try to avoid using a Singleton simply to facilitate passing data to your utility class.

Avoiding having to map WCF's generated complex types

I have an ASP.NET MVC web app whose controllers use WCF to call into the domain model on a different server. The domain code needs to talk to a database and access to the database server isn't always possible from web servers (depends on the customer site) hence the use of WCF to get to a place where my code is allowed to connect to the database server.
This is configurable so if the controllers are able to access the database server directly then I use local instances of the domain objects rather than use WCF.
Lets say I have a page asking for person details like age, name etc. This is a complex type that is a parameter on my WCF operation like this :
[OperationContract]
string SayHello( Person oPerson);
When I generate the client code (eg; by adding a service reference in my client) I get a separate Person class that fulfills the wcf contract. The client, an MVC web app, can use this client Person class as the view model and all is well. I pass that straight into the WCF client methods and it all works brilliantly.
If my mvc client app is configured to NOT use WCF I have a problem. If I am calling my domain objects directly from the controller (assume I have a domain access factory/provider setup) then I need the original Person class and not the wcf generated Person class. This results in my problem which is that I will have to perform mapping from one object to another if I don't use WCF
The main problem with this is that there are many domain objects that will need to be mapped and errors may be introduced such as new properties forgotten about in future changes
I'm learning and experimenting with WCF and MVC can you help me know what my options are in this scenario? I'm sure there will be an easy way out of this given the extensibility of WCF and MVC
Thanks
It appears that you are not actually trying to use a service-oriented architecture. In this case, you can place the domain objects into a single assembly, and share it between the WCF service and the clients. When creating the clients, use "Add Service Reference", and on the "Advanced" tab, choose "Share Types". Either choose to share all types, or choose the list of assemblies whose types you want to share.
Sound service-oriented-architecture dictates that you use message based communication regardless of whether your service is on another machine, in another process, in another appdomain, or in your appdomain. You can use different endpoints with different bindings to take advantage of the speed of the link (http, tcp, named pipes) based on the location of your service, but the code using that service would remain the same.
This may not be the easiest or least time-consuming answer, but one thing you can do is avoid using the "add service reference" option, and then copy your contract interfaces to your MVC application and initiate the connection to WCF manually without automatically creating a service proxy. This will allow you to use one set of classes for your model objects and you can control explicitly when to use WCF or not.
There's a good series of webcasts on WCF by Michele Leroux Bustamante, and I think in episode 2, she explains how to do exactly this. Check it out here: http://www.dasblonde.net/WCFWebcastSeries.aspx
Hope this helps!
One sound option is that you always use WCF, even if client and server are in the same process, as Aviad points out.
Another option is to define the service contracts on interfaces, and to put these, together with the data contracts into an assembly that is shared between client and server. In the client, don't use svcutil or a service reference; instead, use ClientFactory<T>.
This way, your client code will use the same interfaces and classes as the server.

Resources