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.
I am new to Web API and I have a Class Library I would like other applications to access via an ASP.NET Web API site.
The problem I have is that I do not know how to call methods that have multiple input objects some of which are custom entities (they all have several variables inside them and come from the Class Library which I don't have access to change).
Here is an example of one of the methods my API Controller
public bool Process(IBusinessObject businessObject, BusinessValidationObject businessValidationObject, IList<string> messages)
{
//Code to call Class Library is here that requires the 3 inputs
}
Is the above bit of code a valid API method?
I would like to call that method from another ASP.NET Web Application (an MVC application in another solution which will be installed on another server). I have had a look at the Web API Client Libraries but I can't see a way to pass in multiple objects.
Anyone have any ideas?
You can only post one complex object.
A solution might be to create an object that contains all three of the objects that you are trying to pass.
I have a WCF service running with ASP.NET compatibility.
This service is supposed to be readonly and is created using web script factory.
I want to get the singleton instance from anywhere in code (different pages.. etc), and if it's not created it should be created, but if accessed directly for first time it shouldn't create another singleton instance if there was one already created from somewhere in code. Basically, I want a classic singleton, but not using static and the creation of the service should be the factory's job.
You can do this using an attribute on your wcf service:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
class MySingleton : ...
{...}
With this your WCF service has a single instance, that is used by all callers.
For details see: http://msdn.microsoft.com/en-us/magazine/cc163590.aspx
The context:
(Note: in the following I am using "project" to refer to a collection of software deliverables, intended for a single customer or a specific market. I am not referring to "project" as it is used in Visual Studio to refer to a configuration that builds a single EXE or DLL, within a solution.)
We have a sizable system that consists of three layers:
A layer containing code that is shared across projects
A layer containing code that is shared across different applications within a project
A layer containing code that is specific to a particular application or website within a project.
The first two layers are built into DLL assemblies. The top layer is an assortment of EXEs and/or .aspx web applications.
IIRC, we have a number of different projects that use this pattern. All four share layer 1 (though often in slightly different versions, as managed by the VCS). Each of them has its own layer 2. Each of them has its own set of deliverables, which can range from a website, or a website and a background service, to our largest and most complex (and the bread-and-butter of our business) which consists of something like five independent web applications, 20+ console applications/background services, three or four independent web services, half-a-dozen desktop GUI apps, etc.
It's been our intent to push as much code into levels 1 and 2 as possible, to avoid duplicating logic in the top layers. We've pretty much accomplished that.
Each of layers 1 and 2 produce three deliverables, a DLL containing the code that is not web-related, a DLL containing the code that is web-related, and a DLL containing unit tests.
The problem:
The lower levels were written to make extensive use of singletons.
The non-web DLL in layer 1 contains classes to handle INI files, logging, a custom-built obect-relational mapper, which handles database connections, etc. All of these used singletons.
And when we started building things on the web, all of those singletons became a problem. Different users would hit the website, log in, and start doing different things. They'd do something that generated a query, which would result in a call into the singleton ORM to get a new database connection, which would access the singleton configuration object to get the connection string, and then the connection would be asked to perform a query. And in the query the connection would access the singleton logger to log the SQL statement that was generated, and the logger would access the singleton configuration object to get the current username, so as to include it in the log, and if someone else had logged in in the meantime that singleton configuration object would have a different current user. It was a mess.
So what what we did, when we started writing web applications using this code base was to create a singleton factory class, that was itself a singleton. Every one of the other singletons had a public static instance() method that had been calling a private constructor. Instead, the public static instance() method obtained a reference to the singleton factory object, then called a method on that to get a reference to the single instance of the class in question.
In other words, instead of having a dozen classes that each maintained its own private static reference, we now had a single class that maintained a single static reference, and the object that it maintained a reference to contained a dozen references to the other, formerly singleton classes.
Now we had only one singleton to deal with. And in its public static instance() method, we added some web-specific logic. If we had an HTTPContext and that context had an instance of the factory in its session, we'd return the instance from the session. If we had an HTTPContext, and it didn't have a factory in its session, we'd construct a new factory and store it in the session, and then return it. If we had no HTTPContext, we'd just construct a new factory and return it.
The code for this was placed in classes we derived from Page, WebControl, and MasterPage, and then we used our classes in our higher-level code.
This worked fine, for .aspx web applications, where users logged in and maintained session. It worked fine for .asmx web services running within those web applications. But it has real limits.
In particular, it won't work in situations where there is no session. We're feeling pressure to provide websites that serve a larger user base - that might have tens or hundreds of thousands of users hitting them dynamically. Up to now our users have been pretty typical desktop business users. They log into our websites, and stay in them much of the day, using our web apps as an alternative to a desktop app. A given customer might have as many as six users who might use our websites, and while we have a thousand or more customers, combined they don't make for all that heavy a load. But our current architecture will not scale to that.
We're also running into situations where ASP.NET MVC would be a better fit for building the web UI than .aspx web forms. And we're exploring building mobile apps that would be communicating with stand-alone WFC web services. And while in both of these, it looks like it's possible to run them in an environment that has a session, it looks to limit their flexibility and performance fairly severely.
So, we're really looking at ways to eliminate these singletons.
What I'd really like:
I'm trying to envision a series of refactors, that would eventually lead to a better-structured, more flexible architecture. I could easily see the advantages of an IoC framework, in our situation.
But here's the thing - from what I've seen of IoC frameworks, they need their dependencies provided to them externally via constructor parameters. My logger class, for example, needs an instance of my config class, from which to obtain the current user. Currently, it is using the public static instance() method on the config class to obtain it. To use an IoC framework, I'd need to pass it as a constructor.
In other words, from where I sit, the first, and unavoidable task, is to change every class that uses any of these singletons so as to take the singleton factory as a constructor parameter. And that's a huge amount of work.
As an example, I just spent the afternoon doing exactly that, in the level 1 libraries, to see just how much work it is. I ended up changing over 1300 lines of code. The level 2 libraries will be worse.
So, are there any alternatives?
Typically, you should try to wrap the contextual information into its own instance and provide a static accessor method to refer to it. For example, consider HttpContext and its available every where in web application via HttpContext.Current.
You should try to devise something similar so that instead of returning singleton instance, you would return the instance from the current context. That way, you need to not change your consumer code that refers to these static methods (e.g. Logger.Instance()).
I generally roll-up information such as logger, current user, configuration, security permissions into application context (can be more than one class if need arises). The AppContext.Current static method returns the current context. The method implementation goes something like
public interface IContextStorage
{
// Gets the stored context
AppContext Get();
// Stores the context, context can be null
void Set(AppContext context);
}
public class AppContext
{
private static IContextStorage _storageProvider, _defaultStorageProvider;
public static AppContext Current
{
get
{
var value = _storageProvider.Get();
// If context is not available in storage then lookup
// using default provider for worker (threadpool) therads.
if (null == value && _storageProvider != _defaultStorageProvider
&& Thread.CurrentThread.IsThreadPoolThread)
{
value = _defaultStorageProvider.Get();
}
return value;
}
}
...
}
IContextStorage implementations are application specific. The static variables _storageProvider gets injected at the application start-up time while _defaultStorageProvider is a simple implementation that looks into current call context.
App Context creation happens in multiple stages - for example, a global information such as configuration gets read and cached at application start-up while specific information such as user & security gets formed at authentication stage. Once all info is available, the actual instance is created and stored into the app specific storage location. For example, desktop application will use a singleton instance while web application can probably store the instance into the session state. For web application, you may have logic at start of each request to ensure that the context is initialized.
For a scalable web applications, you can have a storage provider that will store the context instance into the cache and if not present in the cache then re-built it.
I'd recommend starting by implementing "Poor Man's DI" pattern. This is where you define two constructors in your classes, one that accepts an instance of the dependencies (IoC), and another default constructor that new's them up (or calls a singleton).
This way you can introduce IoC incrementally, and still have everything else work using the default constructors. Eventually when you have IoC being used in most places you can start to remove the default constructors (and the singletons).
public class Foo {
public Foo(ILogger log, IConfig config) {
_logger = log;
_config = config;
}
public Foo() : this(Logger.Instance(), Config.Instance()) {}
}
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.