Getting Started
Architecture
NServiceBus
Transports
Persistence
ServiceInsight
ServicePulse
ServiceControl
Monitoring
Modernization
Samples

Using NServiceBus with ASP.NET MVC

Component: NServiceBus
NuGet Package: NServiceBus 8.x

This sample consists of an ASP.NET MVC web application hosting an NServiceBus endpoint and a console application hosting another NServiceBus endpoint. The web application sends a command to the console application, waits for a reply, and returns the result to the user.

After running, the web application renders the following page:

AsyncPages Asp.Net Mvc sample running

This shows two methods for sending commands, which are explained below:

  • SendAndBlock: a method in synchronous Controller class
  • SendAsync: a method in asynchronous AsyncController class

Clicking one of the links will render a page that allows you to send commands:

AsyncPages Asp.Net Mvc sample running

Changing the number in the text box from even to odd changes the result.

Structure

The solution in the sample consists of three projects:

  • AsyncPagesMvc: ASP.NET Core MVC application that sends messages
  • Shared: Common code including messages types definitions
  • Server: Destination of messages sent from the MVC project. Hosted in a console application

Initializing NServiceBus

In AsyncPagesMvc, open Program.cs and see the code for the UseNServiceBus method:

var builder = WebApplication.CreateBuilder();

builder.Host.UseNServiceBus(context =>
{
    var endpointConfiguration = new EndpointConfiguration("Samples.Mvc.WebApplication");
    endpointConfiguration.MakeInstanceUniquelyAddressable("1");
    endpointConfiguration.EnableCallbacks();

    endpointConfiguration.UseTransport(new LearningTransport());

    return endpointConfiguration;
});

The call to builder.UseNServiceBus(endpointConfiguration); registers IMessageSession in the service collection, making it available for dependency injection into the controllers.

Sending a message

The controller actions send a message to the console application using the Request method from the injected IMessageSession and wait to receive the reply.

The sample demonstrates the differences between sending a message with NServiceBus in an asynchronous versus synchronous controller action.

Asynchronous controller

Using AsyncController:

var command = new Command
{
    Id = number
};

var sendOptions = new SendOptions();
sendOptions.SetDestination("Samples.Mvc.Server");

var status = await messageSession.Request<ErrorCodes>(command, sendOptions);

return IndexCompleted(Enum.GetName(typeof(ErrorCodes), status));

Synchronous controller

Open the SendAndBlockController class:

var command = new Command
{
    Id = number
};

var sendOptions = new SendOptions();
sendOptions.SetDestination("Samples.Mvc.Server");
var status = messageSession.Request<ErrorCodes>(command, sendOptions).GetAwaiter().GetResult();

return IndexCompleted(Enum.GetName(typeof(ErrorCodes), status));

The Request method returns once a response from the handler is received.

Handling the message

In the Server project, open the CommandMessageHandler class to see the following:

public class CommandMessageHandler :
    IHandleMessages<Command>
{
    static ILog log = LogManager.GetLogger<CommandMessageHandler>();

    public Task Handle(Command message, IMessageHandlerContext context)
    {
        log.Info("Hello from CommandMessageHandler");

        Task reply;
        if (message.Id % 2 == 0)
        {
            log.Info("Returning Fail");
            reply = context.Reply(ErrorCodes.Fail);
        }
        else
        {
            log.Info("Returning None");
            reply = context.Reply(ErrorCodes.None);
        }
        return reply;
    }
}

CommandMessageHandler implements the NServiceBus interface IHandleMessages<T> where T is the message type being handled, in this case, the Command message.

When a message arrives in the input queue it is deserialized and then, based on its type, NServiceBus instantiates the relevant IHandleMessages<T> implementations and calls their Handle methods passing in the message object and the context object.

Notice in the method body the response is being returned to the originating endpoint. This will result in the message being added to the input queue of the AsyncPagesMVC endpoint.

Related Articles