Application layer

The edge, in our case it is a simple web API, accepts requests from the outside world. The main job for our edge component is to accept some request, sent as a JSON document, XML document, message via RabbitMQ or any other communication channel and serialization type, convert it to a command, and then ensure this command gets handled.

The edge can, of course, work directly with the domain model, but this would mean we accept the fact that we will always be working with one edge type only, with one communication protocol. Also, edge components usually heavily dependent on the communication infrastructure when while this is fine for integration tests, creating unit tests for such components might be challenging.

To isolate the communication infrastructure from the actual request handling, we can introduce the application layer. In this layer, we need a component that will accept commands from the edge and use our domain model to handle these commands. Such a component is called application service.

If you refer to Chapter 4, "Designing the model" and look at the picture of onion architecture, you will find application services between infrastructure and the domain model. Application services have no dependency on the transport that is used to send commands from the outside. However, it needs to have a way to load and store entities, because a typical operation of an application service would be to execute a command like this:

There are a couple of exceptions from this flow. When the application service receives a command that requires creating a new entity, it won't load anything from the entity storage, since there is nothing to load yet. It will create the entity and save it to the entity store. Also, when handling a command requires deleting an entity, the application service will load the entity, but not necessarily save it back. It might just delete this entity from the store instead, but this very much depends on a model. For example, if the business requires keeping all the data, we might just mark the entity as deleted and then persist changes to the entity store.

Let's add a new application service class to our project and write some code. First, we need a new file in the Api folder of our executable WebAPI project. Some might argue that application services aren't part of the API but for now, we have only one edge and there is no real reason to separate them. The new file name would be ClassifiedAdApplicationService.cs, and it has code like this:

namespace Marketplace.Api
{
public class ClassifiedAdsApplicationService
{
public void Handle(Contracts.ClassifiedAds.V1.Create command)
{
// we need to create a new Classified Ad here
}
}
}

Now, we need to call the application service from our API. We need to add the application service as a dependency to our controller and in the startup, register the dependency in ASP.NET Core service locator. First, we do the registration. Since our application service class has no dependencies yet, we can use a singleton, so we add one line to the ConfigureServices method of the Startup class:

public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(new ClassifiedAdsApplicationService());
...
}

When this is done, we can add the ClassifiedAdsApplicationService class as a dependency to the ClassifiedAdsCommandsApi controller and call the Handle method from our Post method:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace Marketplace.Api
{
[Route("/ad")]
public class ClassifiedAdsCommandsApi : Controller
{
private readonly ClassifiedAdsApplicationService _applicationService;

public ClassifiedAdsCommandsApi(
ClassifiedAdsApplicationService applicationService)
=> _applicationService = applicationService;

[HttpPost]
public async Task<IActionResult> Post(
Contracts.ClassifiedAds.V1.Create request)
{
_applicationService.Handle(request);

return Ok();
}
}
}

In the next section, we will dive into command handling, including saving entities to an entity store and retrieving them back. We will add more commands and handlers for those commands too.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.229.111