NServiceBus Home

Contents

  • Long-Running Processes
  •     Sagas

Using NServiceBus with ASP MVC3

In order to see how to use NServiceBus in an Asp.Net Mvc3 application, open up the AsyncPagesMvc3 sample.
First of all run the solution - a new browser window/tab should open up, as well as a console application.
The web sample starts with two available methods of sending a command to the server and waiting for a response from it:

  1. SendAndBlock - a Controller uses NServiceBus
  2. SendAsync - an AsyncController uses NServiceBus
We will cover the Asynchronous message sending, the send and block is similar as far as NServiceBus is concerned.
One thing to notice in the SendAndBlock is that the web page renders synchronously - from the user's perspective, the interaction is synchronous and blocking, even though behind the scenes NServiceBus is doing asynchronous messaging.

AsyncPages Asp.Net Mvc3 sample running

Choosing SendAsync brings the following page:

AsyncPages Asp.Net Mvc3 sample running

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

AsyncPages sample

Now let's take a look into the code:

In this sample, there are 3 projects:

  1. AsyncPlagesMvc3 - Asp.Net Mvc3 application that will send messages (found in Messages project)
  2. Messages - Declaration of messages
  3. Server - Destination of messages sent from the Mvc3 project. Hosted in a console application

Initializing the bus

The samples' controllers holding on to a reference of the bus - this will be used later for the purposes of sending messages and receiving a response.

In AsyncPagesMvc3 open up Global.asax.cs and look at the Application_Start method. In there you'll see the following code:


Configure.WithWeb()
    .AsMasterNode()
    .DefaultBuilder()
    .ForMvc()
    .Log4Net()
    .XmlSerializer()
    .MsmqTransport()
        .IsTransactional(false)
        .PurgeOnStartup(false)
    .UnicastBus()
        .ImpersonateSender(false)
    .CreateBus()
    .Start(() => Configure.Instance.
        ForInstallationOn<NServiceBus.Installation.Environments.Windows>().Install());

This code, by calling "WithWeb()" indicates to NServiceBus that it should scan the directory where the web application is deployed (which is different than non-web applications).

The .ForMvc extension method is responsible to inject IBus into the controllers. It does this by implementing the Mvc3 interfaces IDependencyResolver and IControllerActivator.

NServiceBus builder is utilized to register and instantiate IControllerActivator so when the controllers will be requested, the NServiceBus builder will have the opportunity to inject IBus implementation into their IBus public property.

For more information on how the IBus is injected into the controllers please read here and also in David Boike's article: Injecting NServiceBus into ASP.NET MVC 3.

The rest of the code above is quite standard when hosting NServiceBus in your own process. You can read more about the other lines here.

Sending a message

Asynchronous message sending - SendAsync controller

Open SendAsyncController class:

   1:  var command = new Command { Id = number };
   2:  Bus.Send(command).Register<int>(status=>
   3:  	{AsyncManager.Parameters["errorCode"] = Enum.GetName(typeof(ErrorCodes), status);});

At line 1 a new NServiceBus message of the type "Command", and initializing its "Id" property with the value from the text box.
At line 2, we are sending the command using the Bus.Send syntax with registering a callback anonymous method.
This method (line 3) will be executed when the reply from the server will be received.
The server will execute the following for that:

    Bus.Return(ErrorCodes.Fail);

Or

    Bus.Return(ErrorCodes.None);

Depending if the Command Id is an even or odd number.

Let's open up the class definition for the Command type in the Messages project:

[Serializable]
public class Command : IMessage
{
    public int Id { get; set; }
}

As you can see, this class is very simple - the only special thing about it is the IMessage interface that its implementing. This interface comes from NServiceBus and indicates that instances of this class can be sent and received by the bus. The IMessage interface itself is empty - a marker interface. For more information on defining messages, see here. Beginning NServiceBus 3, it is possible to send messages without implementing NServiceBus marker interfaces, please see Unobtrusive message and the accompanying sample.

Synchronous message sending - SendAndBlockController controller

Open SendAndBlockController class:

Bus.Send(command).Register(SimpleCommandCallback, this);

The controller is referencing it's IBus (that was injected when the controller was instantiated, by NServiceBus). We are calling the send method passing in the "command" object we just created.
The "bus" isn't anything special in code - it's just an object you call methods on.
In addition, the call registers a callback method that will be called (with the this parameter) as soon as a response will be received by the server.

Routing Configuration

Now open up the web.config file in AsyncPagesMvc3, and scroll down until you see the following:

<MsmqTransportConfig ErrorQueue="error" NumberOfWorkerThreads="1" MaxRetries="5"/>
<UnicastBusConfig>
    <MessageEndpointMappings>
        <add Messages="Messages" Endpoint="Server"/>
    </MessageEndpointMappings>
</UnicastBusConfig>

There are 2 configuration sections we're looking at: MsmqTransportConfig and UnicastBusConfig.

For information on MsmqTransportConfig, click here.

The UnicastBusConfig section describes which messages should be sent to which queue. In the configuration above, we see that all messages belonging to the "Messages" assembly should be sent to a queue named "Server".

At Server project, the queue name equals to the namespace of the MessageEndpoint class, that is, "Server".

This is how routing is configured in NServiceBus. In this case, the routing is configuring a request/response interaction rather than a publish/subscribe interaction, but later you'll see that the same configuration holds for all kinds of interactions.

Handling the message

In the Server project, open the CommandMessageHandler class - in it you'll see the following:

public class CommandMessageHandler : IHandleMessages<Command>
{
    public IBus Bus { get; set; }

    public void Handle(Command message)
    {
        Console.WriteLine("=================================================");

        Thread.Sleep(TimeSpan.FromSeconds(1));

        if (message.Id % 2 == 0)
            Bus.Return(ErrorCodes.Fail);
        else 
            Bus.Return(ErrorCodes.None);
    }
}

This class implements the NServiceBus interface "IHandleMessages<T>" where T is the specific message type being handled - in this case, the Command message.

Classes the implement this interface are managed by NServiceBus. When a message arrives in the input queue, it is deserialized and then, based on its type, NServiceBus instantiates the relevant classes and calls their "Handle" method - passing in the message object.

Notice the IBus property of the class - that's how it gets a reference to the bus. In the method body you can see it calling the Return method on the bus - this results in a message being sent back to WebApplication1, specifically putting a message in its input queue which is name is determined by the namespace where the bus was configured in this case, in the global.asax: "AsyncPagesMVC3".

Where to go next?

If you are not familiar with Unobtrusive messaging mode, read the documentation here or see the working sample here.

Legal

“NServiceBus” is among the trademarks of NServiceBus Ltd. All other product and company names and marks mentioned are the property of their respective owners and are mentioned for identification purposes only.

© 2010-2012 NServiceBus Ltd. All rights reserved.