HTTP endpoints

Since the most obvious communication method for APIs nowadays is using synchronous HTTP calls, we will start with this. We will be using the ASP.NET WebAPI. Therefore we need to add a controller that will accept our commands. Let's add a file called ClassifiedAdsCommandsApi.cs to the Api folder of our executable project, make the class inherit from Controller and add one Post method to handle the command that we added in the previous section:

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

namespace Marketplace.Api
{
[Route("/ad")]
public class ClassifiedAdsCommandsApi : Controller
{
[HttpPost]
public async Task<IActionResult> Post(
Contracts.ClassifiedAds.V1.Create request)
{
// handle the request here

return Ok();
}
}
}

We are not doing anything there yet. Instead, we are creating a web API that will accept commands from the outside world. We will add code that handles these commands later. Remember, this is our adapter for the HTTP infrastructure, which finds its place at the outermost layer of the onion architecture. That's we can call this layer the edge because there is nothing outside of it, which we can consider a part of our app. The application can have multiple ways to communicate with the outside world, so if we added some other edge, like messaging, we would expect for this new communication adapter to process the same commands.

Now, we need to add more code to the application startup to make the WebAPI work. There are a few things we need to add to the Program class:

  • Build the configuration
  • Configure web host
  • Execute web host

To do these operations, we need the Program class to look like this:

using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using static System.Environment;
using static System.Reflection.Assembly;

namespace Marketplace
{
public static class Program
{
static Program() =>
CurrentDirectory = Path.GetDirectoryName(GetEntryAssembly().Location);

public static void Main(string[] args)
{
var configuration = BuildConfiguration(args);

ConfigureWebHost(configuration).Build().Run();
}

private static IConfiguration BuildConfiguration(string[] args)
=> new ConfigurationBuilder()
.SetBasePath(CurrentDirectory)
.Build();

private static IWebHostBuilder ConfigureWebHost(
IConfiguration configuration)
=> new WebHostBuilder()
.UseStartup<Startup>()
.UseConfiguration(configuration)
.ConfigureServices(services =>
services.AddSingleton(configuration))
.UseContentRoot(CurrentDirectory)
.UseKestrel();
}
}

There is not much going on here. We ensure that our current directory is where the executable is located because this is where we also can find the configuration file. We then read the configuration, and from the configuration, we create the web host and start it. Right now we have no configuration file and therefore no configuration, but we will be adding some later.

Now, we are using the Startup class to configure services, and it needs some attention as well. In the Startup, we need to configure WebAPI so it can use our controller. In addition to that, we need some easy way to interact with the API without having any user interface yet. One nice and easy way to do it is to use Swagger (https://swagger.io/) integration with WebAPI. Before we can start using it, we need to add a Swagger WebAPI integration NuGet package Swashbuckle.AspNetCore. With the new csproj file format the easiest way to do it is probably by adding the package reference directly to the project file. Below you can see the new content for the Marketplace.csproj file, and changes are highlighted:

<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="3.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..Marketplace.DomainMarketplace.Domain.csproj" />
</ItemGroup>
</Project>
Swashbuckle.AspNetCore package might have different a different version at the moment you are reading this book. Use the latest available version.

When you save the project file, your IDE will install the package and add the reference to your project.

Now, we can change the Startup class, so it registers WebAPI internals, our controller, and all necessary Swagger generation. Also, we add an embedded version of Swagger UI so we can test our API directly from the browser, without any additional software:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Swashbuckle.AspNetCore.Swagger;
using static System.Environment;
// ReSharper disable UnusedMember.Global

namespace Marketplace
{
public class Startup
{
public Startup(IHostingEnvironment environment,
IConfiguration configuration)
{
Environment = environment;
Configuration = configuration;
}

private IConfiguration Configuration { get; }
private IHostingEnvironment Environment { get; }

public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSwaggerGen(c =>
c.SwaggerDoc("v1",
new Info
{
Title = "ClassifiedAds",
Version = "v1"
}));
}

public void Configure(IApplicationBuilder app,
IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

app.UseMvcWithDefaultRoute();
app.UseSwagger();
app.UseSwaggerUI(c =>
c.SwaggerEndpoint(
"/swagger/v1/swagger.json",
"ClassifiedAds v1"));
}
}
}

With everything in place now, we are ready to start the application for the first time. After pressing F5, you should see the following at the console:

Now, let's open the Swagger UI by going to http://localhost:5000/swagger in the browser. We should see one operation (Post), and when we expand it, the following should appear:

You can click on the Try it out button and send some requests to the API, but it won't do anything because we always return 200 OK response.

At this moment we have completed all the necessary steps to expose a primitive WebAPI endpoint and have the bootstrap code to support it. We also have created one API contract that represents the command to create a classified ad. It is time to make this command work.

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

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