Building endpoints with .NET Core 3.1

Component: NServiceBus
NuGet Package NServiceBus (7.x)

This sample demonstrates:

  • a simple application running on .NET Core 3.1
  • how to integrate NServiceBus with an ASP.NET Core Web API project
  • a simple back-end process running in the .NET Core generic host
  • the built-in tools used to inject dependencies into message handler classes
The NServiceBus.MicrosoftLogging community NuGet package should be installed to use the Microsoft.Extensions.Logging library.

Front-end

The front-end project hosts a simple web page that contains a form. When the form is submitted, a message is sent to the back-end application via NServiceBus for processing.

The front-end uses the .NET Core generic host to host an NServiceBus endpoint and ASP.NET Core WebAPI controllers. The endpoint is configured as a send only endpoint as it does not need to process any messages. There is routing configured for a single message type; SomeMessage messages get routed to Sample.BackEnd.

public static void Main(string[] args)
{
    CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .UseNServiceBus(context =>
        {
            var endpointConfiguration = new EndpointConfiguration("Sample.FrontEnd");
            endpointConfiguration.SendOnly();

            var transport = endpointConfiguration.UseTransport<LearningTransport>();
            transport.Routing().RouteToEndpoint(typeof(SomeMessage), "Sample.BackEnd");

            return endpointConfiguration;
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        })
    ;

The WebAPI controller is able to take a dependency on IMessageSession and use it to send messages to the backend.

public class HomeController : Controller
{
    IMessageSession messageSession;
    
    public HomeController(IMessageSession messageSession)
    {
        this.messageSession = messageSession;
    }

    public ActionResult Index()
    {
        return View();
    }
    
    [HttpPost]
    public async Task<ActionResult> Index(ViewModel model)
    {
        if (!ModelState.IsValid)
        {
            return View(model);
        }
        
        await messageSession.Send(new SomeMessage { Number = model.Number })
            .ConfigureAwait(false);

        ViewBag.Message = "Request was queued successfully.";
        
        return View(model);
    }
}

Back-end

The back-end project hosts an NServiceBus endpoint which processes messages sent from the front-end. When handling each message it relies on a service that is registered with the host's service collection.

The back-end uses the same API as the front-end to register an NServiceBus endpoint with the generic host.

builder.UseNServiceBus(ctx =>
{
    var endpointConfiguration = new EndpointConfiguration("Sample.BackEnd");
    endpointConfiguration.UseTransport<LearningTransport>();

    endpointConfiguration.DefineCriticalErrorAction(OnCriticalError);

    return endpointConfiguration;
});

Additionally, it registers an important calculation service with the host's service collection.

builder.ConfigureServices(services =>
{
    services.AddSingleton<ICalculateStuff, CalculateStuff>();
});

The NServiceBus message handler is able to take a dependency on the registered service and use it when handling the message.

public class SomeHandler : IHandleMessages<SomeMessage>
{
    private readonly ICalculateStuff stuffCalculator;

    public SomeHandler(ICalculateStuff stuffCalculator)
    {
        this.stuffCalculator = stuffCalculator;
    }

    public async Task Handle(SomeMessage message, IMessageHandlerContext context)
    {
        await stuffCalculator.Calculate(message.Number);
        
        // Do some more stuff if needed
    }
}

Related Articles


Last modified