Domain Driven Design with Web API extensions part 6: domain events with RabbitMq

Introduction

In the previous post we looked at some basic theory behind messaging between independent applications. We discussed a couple of options to solve the problem. In this post we’ll start building our messaging environment using RabbitMq.

Read more of this post

Domain Driven Design with Web API extensions part 5: domain events between independent systems

Introduction

In the previous post we looked at a solution on how elements of a .NET solution can communicate with each other using a mediator. The mediator keeps the publisher decoupled from the subscribers. Also, the mediator won’t have any knowledge of the event handlers, their exact types and what and how they will handle the messages from the domain objects.

The solution helps the email sending event handler read the domain event in case a user added a new or updated an existing load test. In this post we’ll direct our attention to messaging between independent applications. We’ll ultimately simulate that a financial application also wants to be notified of the load test domain events in order to calculate the monthly profits.

Read more of this post

Domain Driven Design with Web API extensions part 4: domain events in code

Introduction

In the previous post we looked at some theory behind domain events. We said that domain events were events that happen within a domain and that other components of the system may be interested in. The domain becomes the publisher – or producer – and the listeners will be the subscribers, or consumers of the domain messages.

We established that we’d solve the communication of consumers and subscribers through a mediator which stands in between. Publishers and subscribers will stay decoupled that way.

In this post we’ll implement the theory in C# code.

Read more of this post

Domain Driven Design with Web API extensions part 3: starting with domain events

Introduction

In the previous post we looked at how to apply the decorator pattern for our emailing scenario in the domain driven design demo project. We saw how the pattern helped us augment the functionality of the original TimetableService in an object oriented fashion. We also managed to wire up the decorator in StructureMap.

In this post we’ll solve the same problem in a different way. Well, at least we’ll start looking at another solution. Also, we’ll start discussing another concept from DDD: domain events. This part of the topic will be divided into two posts: the current post lays the theoretical foundations for the concepts and the next post will show the code.

Read more of this post

Domain Driven Design with Web API extensions part 2: notifications with the decorator pattern

Introduction

In the previous post we started building an extension to our DDD skeleton project. We saw a simple way of adding a component to the TimetableService so that we could send an email upon inserting or updating a load test. We also discussed the pros and cons of the current implementation.

In this post we’ll see an alternative solution using the Decorator design pattern.

Read more of this post

Domain Driven Design with Web API extensions part 1: notifications

Introduction

A couple of weeks ago we went through an updated series on Domain Driven Design starting with this post. We built a functioning skeleton project with EntityFramework as the backing store, a Web API layer as the top consumer, a loosely coupled service layer and a central domain layer with some logic.

In this extension series we’ll investigate a couple of ways to add various dependencies to the project. In particular we’ll look into how to send email notifications in case a new load test has been booked.

Read more of this post

Extension to the DDD skeleton project: per session object context in Repository layer

Introduction

If you followed through the DDD skeleton project blog series then you’ll recall that the following interface was used to get hold of the DB object context in the concrete repositories:

public interface IObjectContextFactory
{
	InMemoryDatabaseObjectContext Create();
}

You’ll also recall that we pulled a valid InMemoryDatabaseObjectContext instance using the singleton pattern:

public class LazySingletonObjectContextFactory : IObjectContextFactory
{
	public InMemoryDatabaseObjectContext Create()
	{
		return InMemoryDatabaseObjectContext.Instance;
	}
}

In retrospect I think I should have gone through another implementation of the IObjectContextFactory interface, one that better suits a real life scenario with an ORM platform such as Entity Framework or NHibernate.

If you’d like to take on the singleton pattern to construct and retrieve an EF object context then you’ll likely run into some difficulties. The singleton pattern was OK for this in-memory solution so that we could demonstrate insertions, deletions and updates in the repository. As the singleton always returns the same InMemoryDatabaseObjectContext instance we won’t lose the new data from request to request as we saw in the demo.

However, this is not desirable if you’re working with an EF object context. If you always return the same object context for every request then even the data retrieved by that object context will be the same upon subsequent requests. If you make a change to an object then it won’t be visible in another session as that new session retrieves the same object context that was present when it was created by the singleton, i.e. when it was first called:

public static InMemoryDatabaseObjectContext Instance
{
	get
	{
		return Nested.instance;
	}
}

private class Nested
{
	static Nested()
	{
	}
	internal static readonly InMemoryDatabaseObjectContext instance = new InMemoryDatabaseObjectContext();
}

If you update a Customer object in one session then the next session won’t see the updates as it still retrieves the original, “unchanged” Customer that was present in the original instance of InMemoryDatabaseObjectContext. You’ll need to call the Refresh method of the EF object context manually to make sure that you get the latest state of the retrieved object like this:

Customer c = some query;
if (c != null)
{
	EfObjectContextInstance.Refresh(RefreshMode.StoreWins, c);
}

In short: my recommendation is that you don’t use the singleton pattern to retrieve the EF object context.

An EntityFramework friendly solution

A better solution is to get an instance of the object context per HTTP session. This requires a different implementation of the IObjectContextFactory interface. The following implementation can do the job:

public class HttpAwareOrmDataContextFactory : IObjectContextFactory
{
	private string _dataContextKey = "EfObjectContext";

	public InMemoryDatabaseObjectContext Create()
	{
		InMemoryDatabaseObjectContext objectContext = null;
		if (HttpContext.Current.Items.Contains(_dataContextKey))
		{
			objectContext = HttpContext.Current.Items[_dataContextKey] as InMemoryDatabaseObjectContext;
		}
		else
		{
			objectContext = new InMemoryDatabaseObjectContext();
			Store(objectContext);
		}
		return objectContext;
	}

	private void Store(InMemoryDatabaseObjectContext objectContext)
	{
		if (HttpContext.Current.Items.Contains(_dataContextKey))
		{
			HttpContext.Current.Items[_dataContextKey] = objectContext;
		}
		else
		{
			HttpContext.Current.Items.Add(_dataContextKey, objectContext);
		}
	}
}

We use the IDictionary object of HttpContext.Current.Items to store the InMemoryDatabaseObjectContext instance. We first check if an instance is available by the key _dataContextKey. If that’s the case then we return that instance. Otherwise we create a new instance of the object context and store it in the dictionary. HttpContext.Current will of course always be different with each new HTTP request to the API which ensures that we get the fresh data from the data store as well. In case the InMemoryDatabaseObjectContext is requested more than once during the same session then we hand out the same instance.

You might ask why we don’t construct a new InMemoryDatabaseObjectContext every single time one is needed like this:

public InMemoryDatabaseObjectContext Create()
{
     return new InMemoryDatabaseObjectContext();
}

That wouldn’t be a good idea as the object context will be called when making some changes to the underlying DB objects and then it’s called again when the changes are to be persisted using two separate calls to the Unit of Work:

void RegisterUpdate(IAggregateRoot aggregateRoot, IUnitOfWorkRepository repository);
.
.
.
void Commit();

The two calls will be very likely made during the same session otherwise the changes are lost. If you construct an InMemoryDatabaseObjectContext to register the changes and then construct another one to commit them then the second instance won’t automatically track the same updates of course so it won’t persist anything. That’s logical as we’re talking about two different instances: how would object context instance #2 know about the changes tracked by object context instance #1?

So now we have two implementations of the IObjectContextFactory interface. The beauty with our loosely coupled solution is that all it takes to change the concrete implementation injected into all Repository classes is to comment out the following line of code in IoC.cs:

x.For<IObjectContextFactory>().Use<LazySingletonObjectContextFactory>();

…and insert the following instead:

x.For<IObjectContextFactory>().Use<HttpAwareOrmDataContextFactory>();

You can run the project as it is now. Navigate to /customers and you should get the same dummy 3 customers we saw in the original demo.

View the list of posts on Architecture and Patterns here.

Extension to the DDD skeleton project: using an external settings source

Introduction

In this post we saw a way how to introduce caching in the DDD project. We also mentioned that hardcoding the caching duration directly in code may not be desirable for testing and maintenance purposes.

One way to externalise the caching duration is the following setup:

  • We can have a settings file where we set up the caching profiles, such as LongCache = 1 minute, MediumCache = 30sec, ShortCache = 10sec.
  • These profiles can be saved in different places: web.config or app.config, database, customised XML/JSON file, even an external service
  • This is telling us that retrieving the correct setting should be abstracted away

Infrastructure

Open the Infrastructure.Common layer and insert a new folder called Configuration. Insert the following interface:

public interface IConfigurationRepository
{        	
        T GetConfigurationValue<T>(string key);
        string GetConfigurationValue(string key);
        T GetConfigurationValue<T>(string key, T defaultValue);
        string GetConfigurationValue(string key, string defaultValue);
}

We’ll go for the most obvious implementation: the appSettings section in web.config. Insert the following class into the folder:

public class AppSettingsConfigurationRepository : IConfigurationRepository
{        
        public T GetConfigurationValue<T>(string key)
        {
            return GetConfigurationValue(key, default(T), true);
        }

        public string GetConfigurationValue(string key)
        {
            return GetConfigurationValue<string>(key);
        }

        public T GetConfigurationValue<T>(string key, T defaultValue)
        {
            return GetConfigurationValue(key, defaultValue, false);
        }
        
        public string GetConfigurationValue(string key, string defaultValue)
        {
            return GetConfigurationValue<string>(key, defaultValue);
        }

        private T GetConfigurationValue<T>(string key, T defaultValue, bool throwException)
        {
            var value = ConfigurationManager.AppSettings[key];
            if (value == null)
            {
                if(throwException)
                    throw new KeyNotFoundException("Key "+key+ " not found.");
                return defaultValue;
            }
            try
            {
                if (typeof(Enum).IsAssignableFrom(typeof(T)))
                    return (T)Enum.Parse(typeof(T), value);
                return (T)Convert.ChangeType(value, typeof(T));
            }
            catch (Exception ex)
            {
                if (throwException)
                    throw ex;
                return defaultValue;
            }
        }
}

You’ll need to set a reference to the System.Configuration library otherwise ConfigurationManager will not be found.

This is an application of the Adapter pattern which we used in the previous post.

Application service

Locate the EnrichedCustomerService class from the previous post on Service layer caching. Add the following private field:

private readonly IConfigurationRepository _configurationRepository;

Modify the constructor as follows:

public EnrichedCustomerService(ICustomerService innerCustomerService, ICacheStorage cacheStorage, IConfigurationRepository configurationRepository)
{
	if (innerCustomerService == null) throw new ArgumentNullException("CustomerService");
	if (cacheStorage == null) throw new ArgumentNullException("CacheStorage");
	if (configurationRepository == null) throw new ArgumentNullException("ConfigurationRepository");
	_innerCustomerService = innerCustomerService;
	_cacheStorage = cacheStorage;
	_configurationRepository = configurationRepository;
}

We want to read the cache duration setting in GetAllCustomers. Modify the method as follows:

public GetCustomersResponse GetAllCustomers()
{
	string key = "GetAllCustomers";
	GetCustomersResponse response = _cacheStorage.Retrieve<GetCustomersResponse>(key);
	if (response == null)
	{
		int cacheDurationSeconds = _configurationRepository.GetConfigurationValue<int>("ShortCacheDuration");
		response = _innerCustomerService.GetAllCustomers();
		_cacheStorage.Store(key, response, TimeSpan.FromSeconds(cacheDurationSeconds));
	}
	return response;
}

It would be better to have some external container for string values such as ShortCacheDuration, but this will be enough for now.

Web layer

Open the web.config file and enter the following appSetting:

<add key="ShortCacheDuration" value="60"/>

We also need to instruct StructureMap to select AppSettingsConfigurationRepository for any IConfigurationRepository it encounters. Enter the following line into the ObjectFactory.Initialize block of IoC.cs:

x.For<IConfigurationRepository>().Use<AppSettingsConfigurationRepository>();

Set a breakpoint within GetAllCustomers() of EnrichedCustomerService.cs. Set the start page to “customers”: open the Properties of the WebService layer, select Web, Specific Page, “customers”. Start the application.

Code execution will stop at the break point. Step through the code by pressing F11. You’ll see how the settings are extracted from the config file and used with the cache storage mechanism.

Now every time you want to change the cache duration you just update the appropriate settings value. There’s nothing stopping you from inserting different cache duration profiles in your configuration source as mentioned above: ShortCache, LongCache, MediumCache etc. Also, we solved yet another dependency problem in an OOP and SOLID way.

Read the next extension to the DDD project here.

View the list of posts on Architecture and Patterns here.

Extension to the DDD skeleton project: caching in the service layer

Introduction

This post is a direct continuation of the DDD skeleton project. In this extension we’ll investigate how to incorporate caching into the solution.

Caching can mean several things in an application. It can be introduced at different levels: you can cache database call results, MVC views, service call results, etc. You can save just about any object in one of the cache engines built into .NET.

In this post we’ll concentrate on caching in the Service layer. We’ll try to solve the requirement to cache the result of the following service call of ICustomerService for a period of time:

GetCustomersResponse GetAllCustomers();

A naive but quick solution would be to cache the results directly in the implementing CustomerService class:

public GetCustomersResponse GetAllCustomers()
{
        if (cacheEngine.IncludesObject<GetCustomersResponse>())
        {
              return cacheEngine.RetrieveObject<GetCustomersResponse>();
        }
        else
        {
	     GetCustomersResponse getCustomersResponse = new GetCustomersResponse();
	     IEnumerable<Customer> allCustomers = null;

	     try
	     {
		    allCustomers = _customerRepository.FindAll();
		    getCustomersResponse.Customers = allCustomers.ConvertToViewModels();
                    cacheEngine.SaveObject<GetCustomersResponse>(getCustomersResponse);
	     }
	     catch (Exception ex)
	     {
		    getCustomersResponse.Exception = ex;
	     }
	     return getCustomersResponse;
       }
}

There are a couple of problems with this solution:

  • The method violates the Single Responsibility Principle: it doesn’t only look up all customers but caches them as well
  • The method doesn’t indicate to its consumers what’s going in its method body. The signature states that it will retrieve all customers but there’s nothing about caching. If it returns stale data then the programmer must inspect the method body to find the reason – and will get a surprise: hey, you never told me about caching!
  • It’s difficult to test the service call in isolation: the cache is empty on the first test run but then as the method returns the cached data you cannot test the actual customer retrieval easily. You’d need to clear the cache before every test run. So if the test fails then you won’t know really why it fails: was it because the customer retrieval threw an exception or because the caching engine misbehaved?

Therefore a more thorough solution requires a different way of thinking.

If you are familiar with SOLID and especially the letter ‘D‘ then you’ll know that all this is pointing towards injecting the caching strategy into CustomerService without having to add the caching operations directly within the GetAllCustomers() method body.

There are different ways to solve this problem that we discussed in this post on Interception with their pros and cons:

  • The Decorator pattern
  • AOP
  • Dynamic interception with a DI container

In this post we’ll go for the “purist” Decorator pattern: it is very object oriented and is probably the easiest to follow for a newcomer to this topic. I’m not a fan of AOP – for reasons read the reference above – and dynamic interception is too technical at this level. I don’t want to make a very technical post concentrating on a specific DI container. We’ll learn a lot of new things with the Decorator pattern. In case you’re not at all familiar with the decorator pattern make sure to check out this reference. We’ll also see the Adapter pattern in action to hide the concrete implementation of the caching engine.

The solution we’re going to go through can be applied to a wide range of cross-cutting concerns, such as logging. I’ll present a decorator that adds caching to a service. By the same token you can build a decorator for logging as well. You can then decorate the service class with a logger AND a caching mechanism as well.

Infrastructure

Caching is an example of a cross-cutting concern. Caching can be introduced in many places within a solution and the same caching strategy can be re-used across several applications. This is pointing us towards the Infrastructure layer of the DDD skeleton project.

Also, the technology you choose for caching can vary: use one of the built-in objects in .NET, such as the System.Runtime.Cache, you can use a third part component or write your own custom solution. The point is that the caching engine may change and you’ll want to be able to easily change the concrete implementation. So it sounds like we have a variable dependency that may change over time, and therefore it needs to be hidden behind an abstraction.

Open the Infrastructure.Common layer of the DDD solution and add a new folder called Caching. Add the following interface:

public interface ICacheStorage
{
	void Remove(string key);
	void Store(string key, object data);
        void Store(string key, object data, TimeSpan slidingExpiration);
	void Store(string key, object data, DateTime absoluteExpiration, TimeSpan slidingExpiration);
	T Retrieve<T>(string key);
}

All cache storage mechanisms will need to implement this interface. We’ll go for the highly efficient, general-purpose caching engine of System.Runtime.Caching in the first implementation. Add the following class to the Caching folder:

public class SystemRuntimeCacheStorage : ICacheStorage
{
	public void Remove(string key)
	{
		ObjectCache cache = MemoryCache.Default;
		cache.Remove(key);
	}

	public void Store(string key, object data)
	{
		ObjectCache cache = MemoryCache.Default;
		cache.Add(key, data, null);
	}

	public void Store(string key, object data, DateTime absoluteExpiration, TimeSpan slidingExpiration)
	{
		ObjectCache cache = MemoryCache.Default;
		var policy = new CacheItemPolicy
		{
			AbsoluteExpiration = absoluteExpiration,
			SlidingExpiration = slidingExpiration
		};

		if (cache.Contains(key))
		{
			cache.Remove(key);
		}

		cache.Add(key, data, policy);
	}

	public T Retrieve<T>(string key)
	{
		ObjectCache cache = MemoryCache.Default;
		return cache.Contains(key) ? (T)cache[key] : default(T);
	}

        public void Store(string key, object data, TimeSpan slidingExpiration)
	{
		ObjectCache cache = MemoryCache.Default;
		var policy = new CacheItemPolicy
		{
			SlidingExpiration = slidingExpiration
		};

		if (cache.Contains(key))
		{
			cache.Remove(key);
		}

		cache.Add(key, data, policy);
	}
}

The code may not compile at first as ObjectCache is located in an unreferenced library. Add a reference to the System.Runtime.Caching dll in the Infrastructure project.

Decorator pattern in the ApplicationServices layer

OK, now we have the caching elements in place using the Adapter pattern. Next we want to enrich the existing CustomerService implementation of the ICustomerService interface to include caching. In the following stub we’ll delegate most of the methods to the inner customer service, which will be our “normal” CustomerService class – we’ll look at the GetAllCustomers() method in a sec. Insert the following class into the Implementations folder:

public class EnrichedCustomerService : ICustomerService
{
	private readonly ICustomerService _innerCustomerService;
	private readonly ICacheStorage _cacheStorage;

	public EnrichedCustomerService(ICustomerService innerCustomerService, ICacheStorage cacheStorage)		
	{
		if (innerCustomerService == null) throw new ArgumentNullException("CustomerService");
		if (cacheStorage == null) throw new ArgumentNullException("CacheStorage");
		_innerCustomerService = innerCustomerService;
		_cacheStorage = cacheStorage;
	}

	public GetCustomerResponse GetCustomer(GetCustomerRequest getCustomerRequest)
	{
		return _innerCustomerService.GetCustomer(getCustomerRequest);
	}

	public GetCustomersResponse GetAllCustomers()
	{
		throw new NotImplementedException();
	}

	public InsertCustomerResponse InsertCustomer(InsertCustomerRequest insertCustomerRequest)
	{
		return _innerCustomerService.InsertCustomer(insertCustomerRequest);
	}

	public UpdateCustomerResponse UpdateCustomer(UpdateCustomerRequest updateCustomerRequest)
	{
		return _innerCustomerService.UpdateCustomer(updateCustomerRequest);
	}

	public DeleteCustomerResponse DeleteCustomer(DeleteCustomerRequest deleteCustomerRequest)
	{
		return _innerCustomerService.DeleteCustomer(deleteCustomerRequest);
	}
}

Again, if you don’t understand the structure of this class check out the post on the Decorator pattern. Here’s the implementation of the GetAllCustomers() method:

public GetCustomersResponse GetAllCustomers()
{
	string key = "GetAllCustomers";
	GetCustomersResponse response = _cacheStorage.Retrieve<GetCustomersResponse>(key);
	if (response == null)
	{
		response = _innerCustomerService.GetAllCustomers();
		_cacheStorage.Store(key, response, TimeSpan.FromMinutes(1));
	}
	return response;
}

We check in the cache if a GetCustomersResponse object is present and return it. Otherwise we ask the inner customer service to fetch all customers and put the result into the cache for 1 minute – we’ll come back to this point at the end of the post.

We are done with the decorated CustomerService class. Now we’d like to make sure that the CustomerController receives the EnrichedCustomerService instead of CustomerService.

StructureMap

Recall that we’re using StructureMap as our DI container. At present it follows the convention that whenever it sees an interface dependency whose name starts with “I” it will look for a concrete implementation with the same name without the “I”: IProductService == ProcuctService, ICustomerRepository == CustomerRepository. We also saw examples of specifying a concrete class that StructureMap will insert:

x.For<IUnitOfWork>().Use<InMemoryUnitOfWork>();
x.For<IObjectContextFactory>().Use<LazySingletonObjectContextFactory>();

So we should be able to add the following code, right?

x.For<ICustomerService>().Use<EnhancedCustomerService>();

Keep in mind that EnhancedCustomerService also has a dependency on ICustomerService so this code would inject another EnhancedCustomerService into EnhancedCustomerService which is not what we want. The goal is the following:

  • The CustomerController class should get EnhancedCustomerService from StructureMap
  • EnhancedCustomerService should get CustomerService from StructureMap

In fact this is such a common problem that it has been solved multiple times in StructureMap. All decent DI containers provide a solution for the Decorator pattern. It can be solved in at least 3 ways in StructureMap:

  • Decorating with instance references
  • Decorating with named instances
  • Decorating with delegates

This is not a technical post about StructureMap so I won’t go into any detail. We’ll go for the first option. Locate the IoC.cs class in the WebService layer and add the the following piece of code the the ObjectFactory.Initialize block:

x.For<ICacheStorage>().Use<SystemRuntimeCacheStorage>();
var customerService = x.For<ICustomerService>().Use<CustomerService>();
x.For<ICustomerService>().Use<EnrichedCustomerService>().Ctor<ICustomerService>().Is(customerService);

The first row is quite clear: we want to use the SystemRuntimeCacheStorage implementation of the ICacheStorage interface. The second row indicates that we want to use CustomerService where ICustomerService is used and retain a reference to the object returned by the Use method: a SmartInstance of T which is a StructureMap object. In the third row we modify this statement by saying that for ICustomerService we want an EnrichedCustomerService object and inject the retained customerService in its constructor. The other elements in the EnrichedCustomerService constructor will be resolved automatically by StructureMap. This looks a bit cryptic at first but that’s how it’s done, period.

Open the Properties window of the WebService layer, select the Web tag, click “Specific Page” and enter “customers” as the start-up page. Set a couple of breakpoints:

  • One withing the Get() method of CustomersController
  • Another one within GetAllCustomers() of EnrichedCustomerService

Start the web service and the start up URL in the browser should be something like http://localhost:9985/customers. The port number will probably be different in your case. Code execution should stop at the first breakpoint in the Get() method. Inspect the type of the injected ICustomerService in CustomersController.cs, it should be of type EnrichedCustomerService. Let the code continue and execution will stop again at GetAllCustomers in EnrichedCustomerService. Inspect the type of the inner customer service in that class: it should be of CustomerService. From here on I encourage you to step through the code with F11 to see how caching is used. Then refresh the page in the browser and you’ll see that the GetCustomersResponse is fetched from the cache instead of asking the CustomerService instance.

That’s about it. We have solved the caching problem in an object oriented, testable and SOLID way.

Further enhancement

There’s still room for improvement in our cache solution. Right now the cache duration is hard coded here:

_cacheStorage.Store(key, response, TimeSpan.FromMinutes(1));

It would be better with a more configurable solution where you can change the duration without coming back to this class every time. Imagine that you have caching in hundreds of classes – changing the duration in every single one will not make a happy programmer.

There are several ways to solve this problem. The next post will present a possible solution.

View the list of posts on Architecture and Patterns here.

Extension to the DDD skeleton project: domain specific rules Part 2

Introduction

In the first part of this DDD skeleton project extension we completed the domain and repository layers. The repository implementation was only a stub as we want to concentrate on validating domains with differing regional rules.

In this post we’ll finish off the communication chain in the skeleton web service.

Let’s get started! Open the DDD project and we’ll continue with the application service layer.

The Application services layer

We’ll concentrate on inserting new CountrySpecificCustomer objects in the data store. We won’t support the entire GET/POST/PUT/DELETE spectrum. You can do all that based on how we did it for the simple Customer object. Locate the Messaging folder and insert a new sub-folder called EnhancedCustomers. Insert the following messaging objects in this new folder:

public class CountrySpecificCustomerViewModel
{
	public string FirstName { get; set; }
	public int Age { get; set; }
	public string NickName { get; set; }
	public string Email { get; set; }
	public string CountryCode { get; set; }
}

public class InsertCountrySpecificCustomerRequest : ServiceRequestBase
{
	public CountrySpecificCustomerViewModel CountrySpecificCustomer { get; set; }
}

public class InsertCountrySpecificCustomerResponse : ServiceResponseBase
{}

Nothing fancy here I hope. These objects follow the same structure as their original Customer counterparts.

Add the following interface in the Interfaces folder:

public interface ICountrySpecificCustomerService
{
	InsertCountrySpecificCustomerResponse InsertCountrySpecificCustomer(InsertCountrySpecificCustomerRequest insertCustomerRequest);
}

Recall that the constructor of the CountrySpecificCustomer object is expecting an instance of Country. We already have a factory in the Domain layer that returns the correct country based on the country code. So we *could* use that factory here as well since the CountrySpecificCustomerViewModel allows for the specification of a country code. However, it would be unfortunate to use that concrete factory in the Services layer as it would only increase the degree of coupling between the Services and the Domain layer. So we’ll hide it behind an abstraction.

Locate the folder where you saved the CountryFactory object in the Domain layer. Insert the following interface:

public interface ICountryFactory
{
	Country CreateCountry(string countryCode);
}

The existing CountryFactory can implement the interface as follows:

public class CountryFactory : ICountryFactory
{
	private static IEnumerable<Country> AllCountries()
	{
		return new List<Country>() { new Hungary(), new Germany(), new Sweden() };
	}

	public static Country Create(string countryCode)
	{
		return (from c in AllCountries() where c.CountryCode.ToLower() == countryCode.ToLower() select c).FirstOrDefault();
	}

	public Country CreateCountry(string countryCode)
	{
		return Create(countryCode);
	}
}

Back in the services layer we can implement the ICountrySpecificCustomerService interface. Just to refresh our minds open the CustomerService class in the Implementations folder. You’ll recall that its constructor requires an IUnitOfWork object. The implementation of the ICountrySpecificCustomerService will also need one. This calls for a base class which both implementations can derive from. Insert the following abstract class in the Implementations folder:

public abstract class ApplicationServiceBase
{
	private readonly IUnitOfWork _unitOfWork;

	public ApplicationServiceBase(IUnitOfWork unitOfWork)
	{
		if (unitOfWork == null) throw new ArgumentNullException("UnitOfWork");
		_unitOfWork = unitOfWork;
	}

	public IUnitOfWork UnitOfWork
	{
		get
		{
			return _unitOfWork;
		}
	}
}

Next modify the declaration and constructor of the CustomerService object as follows:

public class CustomerService : ApplicationServiceBase, ICustomerService
{
	private readonly ICustomerRepository _customerRepository;

	public CustomerService(ICustomerRepository customerRepository, IUnitOfWork unitOfWork)
		: base(unitOfWork)
	{
		if (customerRepository == null) throw new ArgumentNullException("Customer repo");
		_customerRepository = customerRepository;
	}
.//implementations omitted
.
.
}

After this change you’ll get some errors saying that the _unitOfWork variable is not accessible, e.g. here:

_unitOfWork.Commit();

Replace those calls by referring to the public accessor of the base class:

UnitOfWork.Commit();

Add a new class to the Implementations folder called CountrySpecificCustomerService. Insert the following implementation stub:

public class CountrySpecificCustomerService : ApplicationServiceBase, ICountrySpecificCustomerService
{
	private readonly ICountrySpecificCustomerRepository _repository;
	private readonly ICountryFactory _countryFactory;

	public CountrySpecificCustomerService(IUnitOfWork unitOfWork, ICountrySpecificCustomerRepository repository
		, ICountryFactory countryFactory) : base(unitOfWork)
	{
		if (repository == null) throw new ArgumentNullException("CountrySpecificCustomerRepository");
		if (countryFactory == null) throw new ArgumentNullException("ICountryFactory");
		_repository = repository;
		_countryFactory = countryFactory;
	}

	public InsertCountrySpecificCustomerResponse InsertCountrySpecificCustomer(InsertCountrySpecificCustomerRequest insertCustomerRequest)
	{
		throw new NotImplementedException();
	}
}

In the InsertCountrySpecificCustomer implementation we’ll follow the same structure as in CustomerService.InsertCustomer: construct the domain object, validate it and then insert it. Insert the following implementation:

public InsertCountrySpecificCustomerResponse InsertCountrySpecificCustomer(InsertCountrySpecificCustomerRequest insertCustomerRequest)
{
	CountrySpecificCustomer newCustomer = BuildCountrySpecificCustomer(insertCustomerRequest.CountrySpecificCustomer);
	ThrowExceptionIfCustomerIsInvalid(newCustomer);
	try
	{
		_repository.Insert(newCustomer);
		UnitOfWork.Commit();
		return new InsertCountrySpecificCustomerResponse();
	}
	catch (Exception ex)
	{
		return new InsertCountrySpecificCustomerResponse() { Exception = ex };
	}
}

BuildCountrySpecificCustomer and ThrowExceptionIfCustomerIsInvalid look as follows:

private CountrySpecificCustomer BuildCountrySpecificCustomer(CountrySpecificCustomerViewModel viewModel)
{
	return new CountrySpecificCustomer(_countryFactory.CreateCountry(viewModel.CountryCode))
	{
		Age = viewModel.Age
		, Email = viewModel.Email
		, FirstName = viewModel.FirstName
		, NickName = viewModel.NickName
	};
}

private void ThrowExceptionIfCustomerIsInvalid(CountrySpecificCustomer newCustomer)
{
	IEnumerable<BusinessRule> brokenRules = newCustomer.GetBrokenRules();
	if (brokenRules.Count() > 0)
	{
		StringBuilder brokenRulesBuilder = new StringBuilder();
		brokenRulesBuilder.AppendLine("There were problems saving the LoadtestPortalCustomer object:");
		foreach (BusinessRule businessRule in brokenRules)
		{
			brokenRulesBuilder.AppendLine(businessRule.RuleDescription);
		}

		throw new Exception(brokenRulesBuilder.ToString());
	}
}

New elements in the Web layer

We’re now ready to construct our new Controller. Locate the Controllers folder in the WebService project of the solution. Add a new empty ApiController called CountrySpecificCustomersController. Add the following private field and constructor:

private readonly ICountrySpecificCustomerService _countrySpecificCustomerService;

public CountrySpecificCustomersController(ICountrySpecificCustomerService countrySpecificCustomerService)
{
	if (countrySpecificCustomerService == null) throw new ArgumentNullException("CountrySpecificCustomerService");
	_countrySpecificCustomerService = countrySpecificCustomerService;
}

We’ll only support the POST operation so that we can concentrate on validation. Add the following Post method to the controller:

public HttpResponseMessage Post(CountrySpecificCustomerViewModel viewModel)
{
	ServiceResponseBase response = _countrySpecificCustomerService.InsertCountrySpecificCustomer(new InsertCountrySpecificCustomerRequest() { CountrySpecificCustomer = viewModel });
	return Request.BuildResponse(response);
}

That’s it actually, we can now test the new parts using the simple Console tool we built in the last post of the DDD series. Start the DDD web service and take note of the localhost URL in the web browser. Insert a breakpoint within the Post method of the CountrySpecificCustomersController class so that you can go through the code step by step.

Open that little test application and add the following class to the main project:

public class CountrySpecificCustomerViewModel
{
	public string FirstName { get; set; }
	public int Age { get; set; }
	public string NickName { get; set; }
	public string Email { get; set; }
	public string CountryCode { get; set; }
}

Insert two methods that will build a valid and an invalid country specific customer:

private static CountrySpecificCustomerViewModel BuildFailingCustomer()
{
	return new CountrySpecificCustomerViewModel()
	{
		FirstName = "Elvis"
		, Age = 17
		, CountryCode = "SWE"
	};
}

private static CountrySpecificCustomerViewModel BuildPassingCustomer()
{
	return new CountrySpecificCustomerViewModel()
	{
		FirstName = "John"
		, Age = 19
		, CountryCode = "SWE"
	};
}

Recall that Swedish customers must be over 18, so the insertion of the first object should fail. Insert the following test method to Program.cs:

private static void TestCountrySpecificCustomerValidation()
{
	HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, _serviceUriTwo);
	requestMessage.Headers.ExpectContinue = false;
	CountrySpecificCustomerViewModel vm = BuildFailingCustomer();
	string jsonInputs = JsonConvert.SerializeObject(vm);
	requestMessage.Content = new StringContent(jsonInputs, Encoding.UTF8, "application/json");
	HttpClient httpClient = new HttpClient();
	httpClient.Timeout = new TimeSpan(0, 10, 0);
	Task<HttpResponseMessage> httpRequest = httpClient.SendAsync(requestMessage,
			HttpCompletionOption.ResponseContentRead, CancellationToken.None);
	HttpResponseMessage httpResponse = httpRequest.Result;
	HttpStatusCode statusCode = httpResponse.StatusCode;
	HttpContent responseContent = httpResponse.Content;
	if (responseContent != null)
	{
		Task<String> stringContentsTask = responseContent.ReadAsStringAsync();
		String stringContents = stringContentsTask.Result;
		Console.WriteLine("Response from service: " + stringContents);
	}
	Console.ReadKey();
}

…where _serviceUriTwo is the URL of the controller. It should be something like this:

private static Uri _serviceUriTwo = new Uri("http://localhost:9985/countryspecificcustomers");

So we’ll be testing the failing customer first. Insert a call to this test method from Main and press F5. If you entered the breakpoint mentioned above then the code execution should stop there. Step through the code and when it hits the validation part in the application service layer – the ThrowExceptionIfCustomerIsInvalid method – you should see a validation error: There were problems saving the LoadtestPortalCustomer object: Swedish customers must be at least 18.

Next replace the following…

CountrySpecificCustomerViewModel vm = BuildFailingCustomer();

…with…

CountrySpecificCustomerViewModel vm = BuildPassingCustomer();

…within the TestCountrySpecificCustomerValidation() method and run the test again. Validation should succeed without any problems.

Feel free to test the code with the other cases we set up in the original specifications by playing with the property values of the CountrySpecificCustomerViewModel object we send to the service.

That’s all folks. We’ll look at caching in the next extension of the DDD project.

View the list of posts on Architecture and Patterns here.

ultimatemindsettoday

A great WordPress.com site

Elliot Balynn's Blog

A directory of wonderful thoughts

HarsH ReaLiTy

A Good Blog is Hard to Find

Softwarearchitektur in der Praxis

Wissenswertes zu Webentwicklung, Domain-Driven Design und Microservices

Technology Talks

on Microsoft technologies, Web, Android and others

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

Bite-size insight on Cyber Security for the not too technical.

Guru N Guns's

OneSolution To dOTnET.

Johnny Zraiby

Measuring programming progress by lines of code is like measuring aircraft building progress by weight.

%d bloggers like this: