The mechanics of delegates


In the first part of this series, I tried to explain what delegates are in the .NET context. Now, as promised, I’m going to explain the mechanics of delegates in particular:

  1. Declaration of a delegate type
  2. Providing an implementation compatible with the delegate signature. Strictly speaking, this can exist independently of delegates but it is required before the next step can happen.
  3. Instantiation of a delegate
  4. Invocation of a delegate

Declaration of a delegate type

class Person
{
public static void Eats()
{
// Some implementation
}
public static void Says(string message)
{
// Some implementation
}
}

The code above is the same one provided in a previous post and we’ll re-use this later in order to discuss the mechanics of delegates.

If you are familiar with Interfaces in .NET then the following code:

Interface IMyInterface
{
void SomeMethod();
}
view raw gistfile1.cs hosted with ❤ by GitHub

should not be daunting.

In this interface, we are specifying a signature for a method “SomeMethod” which doesn’t take any parameter and doesn’t return any value.

void SomeMethod();

There is absolutely no implementation provided because in an Interface we are merely declaring a contract through the method signature that compatible methods should adhere to.

Likewise, when declaring a delegate, we are declaring a contract and specifying the signature that compatible methods should adhere to. In .NET, this is how we do it:

delegate void PersonEatsDelegate();

If you were to remove the “delegate” keyword, then the signature of “PersonEatsDelegate” is exactly the same as that of “SomeMethod” i.e. any method adhering to the “PersonEatsDelegate” will not take any parameter and return no value.

Just like in the Interface example, there is absolutely no implementation given, just a contract. Hence, it is quite common to hear delegates being explained as being like an Interface with only one method contract, which is exactly what a delegate declaration is. For completeness’s sake, the delegate declaration cannot be in a file of its own but has to exist either in a file where a class or interface is defined.

Providing an implementation compatible with the delegate signature

Since, in the delegate declaration we have provided absolutely no implementation but merely a contract, we now have to provide a handler method implementation which adheres to the signature of the delegate declaration.

If you’ve been able to follow along, then if you go back to the top of this post, you will notice that the “Eat” method of the “Person” class provides one such implementation.

public static void Eats()
{
// Some implementation
}

because it is a method with no parameter and which doesn’t return anything and that matches the “PersonEatsDelegate” delegate type declaration.

Now consider the method “Says” of the Person class:

public static void Says(string message)
{
// Some implementation
}

this method doesn’t match the delegate declaration since it has one parameter.

Instantiation of a delegate

This was actually already given in the first part of this series as:

PersonEatsDelegate personEatsDelegate = Person.Eat;

However, if you were to try and do:

PersonEatsDelegate personEatsDelegate = Person.Says;

you wouldn’t be able to compile the code because the signature of method “Says” doesn’t match the delegate type declaration “PersonEatsDelegate“.

Now in the first part of this series, I tried to emphasise time and again the fact that a delegate is a reference type. The reason I bring this up is because when one instantiates a reference type, one usually uses the “new” keyword and in our two instantiation examples, there is no sight of the “new” keyword. For example, when we instantiate a class we would “new” it up like:

var person = new Person();

So why is this not the case for delegates? Well in actual fact, there is an implicit “newing” up. So when we instantiate the delegate as:

PersonEatsDelegate personEatsDelegate = Person.Eat;

we could also write it as:

PersonEatsDelegate personEatsDelegate = new PersonEatsDelegate(Person.Eat);

The first incarnation is simply the shortened form of the second. However, the latter emphasises the fact that a delegate type is indeed a reference type albeit a special one.

In the first part of this series, I asked the reader to ignore the fact that we are using “Person.Eat” rather than “Person.Eat()” which syntactically might be more familiar when dealing with methods whereby the former might indicate the referencing of an object property. However, during the instantiation  of a delegate we’re assigning (or pointing to) a method to a delegate type. If, we were to call “Person.Eat()”, then the method would actually be invoked and this is not really what we want. What we want is to have a reference to a method which conforms to the signature of the delegate.

Invocation of a delegate

This is the easy part. Now that we’ve instantiated the delegate as:

PersonEatsDelegate personEatsDelegate = Person.Eat;

we invoke it as:

personEatsDelegate();

as a result of which, the method “Eats()” will get executed.

The code given in this section can be found here.

A few words

This section hopefully will have provided a good explanation about the mechanics of delegates. However, it is understandable if the user is still none the wiser as to when to use it but this will be explained in another post in this series.

 

 

Advertisement
Posted in .NET

Delegates


When learning about a new technique/tool, I think is it is important to ask the following questions:

  1. Why i.e. what problem does this technique I’m trying to learn about solve?
  2. What i.e. what are the concepts/ideas behind the technique?
  3. How i.e. what are the mechanics involved using the technique?
  4. When i.e. when is it appropriate to use the technique?

So the main reason why delegates are useful stems from the fact that they help with writing loosely coupled code. It is a bit difficult to explain this in detail until the “What” and the “How” are explained.

Hence, I will begin with item 2 i.e. the What.

What are delegates?

A lot of explanations I’ve read about what delegates are, involve the use of analogies e.g. Jon Skeet in his book C# in depth talks about the executor of a will; or as in the C# 3.0: Master the fundamentals of C# 3.0 book, the use of delegates in the “proper” sense of the word.

However, all analogies are just that and when they are probed hard enough, they fall apart. The difficulty lies in understanding what delegates are in the .NET context. Hence, I will try to explain in .NET terms what a delegate is.

The C# 3.0: Master the fundamentals of C# 3.0 book provides a very good starting point:

A delegate is a reference type, like the other reference types …, but instead of referring to an object, a delegate refers to a method

Let’s break down this definition in two parts:

  1. A reference type refers to an object.
  2. A delegate is also a reference type but one which points to a method.

If you’ve done any Object Oriented Programming, then the first part of this definition (reference types refer to an object) should make sense as the concept of a reference type should be clear to you (if not, you must understand this first).

Now consider the following code:

class Person
{
public static void Eats()
{
// Some implementation
}
public static void Says(string message)
{
// Some implementation
}
}

The following should make sense in the context of the first part of the definition:

var person = new Person();

In essence, our reference “person” refers to the “Person” object.

Now for one minute imagine that you could somehow just write the following:

var personEatsDelegate = Person.Eats;

If you ignore the fact that it is “Person.Eats” and not “Person.Eats()”, then similar to the previous code, the delegate “personEatsDelegate” refers to the method “Person.Eats” which is exactly the second part of the definition of delegates as given above.

So in .NET, delegates provide a mechanism to assign a method to a variable where that variable is of type “delegate”.

Now, the code as given will not compile because I’ve omitted important code which I’ll cover when dealing with the mechanics of delegates (declaring, instantiating and invoking). What I’ve shown here is only the instantiation aspect of delegates. However, once the declaration part is done, this code will compile.

The fact that a delegate is a reference type means that we can do the following:

var result = SomeClass.DoSomething(personEatsDelegate);

In other words, we’re passing a function around. You will be no doubt be more familiar with passing Objects or value types around like:

var result = SomeClass.DoSomething(person);

But the point I want to emphasise is that delegates are reference types albeit a bit special. The reason for this empashis will become clear in the mechanics of delegates section which will be my next post.

Posted in .NET

Delegates and Events series


For a very long time, I have been what JP Boodhoo describes as being a “consumer developer” i.e. I’ve been using frameworks e.g. ASP.NET MVC, Castle Windsor, etc and generally programming at a “high level of abstraction”. Whatever the reasons for that state of affairs, it has become obvious that I really need to get to grips with some fundamentals of the .NET platform and what it offers.

One of these fundamentals is the topic of “Delegates and Events”. While I’ve been able to “use/consume” anonymous methods, lambdas, Func, Action, etc, my style of programming has been such that I’ve tended to avoid “producing” code using delegates simply because I’ve never really been that comfortable with the latter and I’ve been able to get away with it. Moreover, there seems to be a movement towards a more functional style of programming as Mark Seemann observes.

Hence, this is my attempt to document my understanding on the matter and here are the links to the various posts:

Delegates

The mechanics of delegates

 

Tagged with: , ,
Posted in .NET

ASP.NET MVC Deep Dive – Routing


Oftentimes as developers we use frameworks without really knowing how hte magic happens because we are so focussed on delivery and lean upon the frameworks. So for instance, have you ever wondered how the following are achieved:

  1. How do images, stylesheets and javascript files (resources in .NET parlance) get served?
  2. How does the framework “know” how to return a Http 404?

In order to answer these questions one has to first understand the ASP.NET pipeline and in particular the Routing aspect of it.

Effectively when our web server gets an incoming request, it gets routed to an appropriate http handler. According to the msdn page

An ASP.NET HTTP handler is the process that runs in response to a request that is made to an ASP.NET Web application

That, in a nutshell, answers both questions. In essence, in the ASP.NET framework we have:

  • one handler, ResourceHandler, which will serve resources
  • and we have another handler (in the case of MVC it’s the MvcHandler) that will return a Http 404. In fact, the MvcHandler is responsible for returning web pages in response to something a request like /Home/Account.

Now let’s get to the nitty gritty of how this is actually implemented in ASP.NET MVC.

Routing in ASP.NET

In the ASP.NET pipeline, an incoming request will be matched against a list of routes and based upon some route constraints, each request will be filtered down to the appropriate http handler. In this post we shall ignore the route constraints because this post does a great job at explaining it. However, what should be clear, and at the risk of repeating myself, is that based upon the incoming request, as soon as a route in the route list is matched, the response is returned by the corresponding http handler.

I shall first deal with how a request such to /Home/Index is handled in the context of ASP.NET MVC.

The default IRouteHandler and IHttpHandler in ASP.NET MVC

If you were to create an ASP.NET MVC4 Internet application and then look at the RouteConfig class, you would see something like:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

the MapRoute extension method in System.Web.Mvc is simply a convenience method for, unsurprisingly, mapping an incoming request to a route.

public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces)
{
    //Guard clauses

    Route route = new Route(url, new MvcRouteHandler())
    {
        Defaults = CreateRouteValueDictionary(defaults),
        Constraints = CreateRouteValueDictionary(constraints),
        DataTokens = new RouteValueDictionary()
    };

    if ((namespaces != null) && (namespaces.Length > 0))
    {
        route.DataTokens["Namespaces"] = namespaces;
    }

    routes.Add(name, route);

    return route;
}

What is of particular interest is the MvcRouteHandler class, which as it turns out it the default implementation for IRouteHandler in ASP.NET MVC. If you were to open up MvcRouteHandler, you would see:

public class MvcRouteHandler : IRouteHandler
{    
    ...
    protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        requestContext.HttpContext.SetSessionStateBehavior(GetSessionStateBehavior(requestContext));
        return new MvcHandler(requestContext);
    }
    ...
}

The method GetHttpHandler has to be implemented since it is defined in IRouteHandler. In effect, in our implementation we are setting the IHttpHandler i.e. actual http handler to MvcHandler, which is hence the default implementation of IHttpHandler in ASP.NET MVC.

Before going any further let us summarise how an incoming request is eventually routed to the appropriate route handler.

  1. We first define the url pattern e.g. “{controller}/{action}/{id}” for a given route
  2. Each given route, and therefore url, is mapped onto a particular implementation of IRouteHandler e.g. Route route = new Route(url, new MvcRouteHandler()). In other words, if a given url matches a route, then use the given IRouteHandler.
  3. The IRouteHandler will then define what IHttpHandler to use.

Resource handler in ASP.NET

It should be clear that resources do not get processed by the MvcHandler since there are no matching controllers. Hence, I started looking for classes that implement IRouteHandler and found ResourceRouteHandler in System.Web.WebPages.ApplicationParts. In GetHttpHandler of that class, ResourceHandler is returned and it is effectively this implementation of IHttpHandler which is returning the various resources.

This also answers a question I had regarding how the “~” in paths was working.

The only thing that I couldn’t figure out is where the url to route mapping is defined although I looked in the various *.config files and IIS.

Http 404 in ASP.NET MVC

This is a bit trickier in the sense that there might be different versions. Let me explain by trying to go to

  • /NotFound
  • /Home/About/something/nonexistent

In the first instance, here’s the error page:

ControllerFactory404while the second instance, the error page is:

IIS404I had a hunch about why this was happening but as I couldn’t properly prove it, I decided to ask the question of why this was happening on Stackoverflow. Although the accepted answer also does not conclusively explain why, it did concur with my hypothesis (taking the scienfitic approach here) and until I get told otherwise, I’ll just accept it.

To summarise the answer given, in the first case it is ASP.NET MVC producing the error page while in the second case, it is IIS. In the next post we will delve deeper into the former case.

Posted in ASP.NET MVC

Global exception logging in ASP.NET MVC 4


This post is an aggregation of various posts found on the web which aim to address the issue of global logging of exceptions as well as the display of nice “error” pages in ASP.NET MVC 4.

As developers, we do spend quite a bit of time debugging applications. However, implementing error logging is often an afterthought of the development process and more often than not the solutions, although functional, are poorly executed.

Display nice error page to user

Here’s a very nice page which explains how to get a nice custom error page. Moreover, it explains how you can log exceptions (We’ll come back to why the suggestions provided are not optimal).

What is missing from that post is what happens if we try to go to a non existent page and the answer is that the user, with the code provided in the post, will see:

404Now, for me, when I was a beginner, this was confusing. The source of confusion comes from the fact that “error” and “exception” are often used interchangeably. The web.config entry:

<customErrors mode="On">
</customErrors>

as it currently stands will deal with exceptions i.e. whenever there is an exception, the “Error.cshtml” page will be invoked. (If you want to know how this happensthen look at his page.)

However, in the wider meaning of error, we get the page shown above. The way to show a custom error page in that case is to add the following in the web.config file:

<customErrors mode="On">
  <error statusCode="404" redirect="~/HttpError/NotFound404"/>
</customErrors>

The “redirect” path is in the format Controller/Action. Hence, it will come as no surprise that the following controller:

using System.Web.Mvc;

namespace MVC4_WebApplication_InternetApplication.Controllers
{
    public class HttpErrorController : Controller
    {
        public ActionResult NotFound404()
        {
            return View();
        }
    }
}

and the corresponding view:

<hgroup>
    <h1>Error.</h1>
    <h2>The page you are trying to access doesn't exist. Please ensure that you have typed in the correct address.</h2>
</hgroup>

Once this is in place, a custom error page will be shown to the user. You might, at this point, want to show appropriate error pages for the various Http status codes wherever suitable.

Exception logging

The point of exception logging, in my view, is to help with debugging issues and it is really valuable in production environments or environments where you have limited access to.

Now I’m going to explain why the error logging strategy given in the post above isn’t optimal. In the case whereby the OnException method of Controller is overriden, the code isn’t DRY as Mark Seeman explains. His solution does work but in ASP.NET MVC 4, Global Error Handling is taken care of for us:

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
    }
}

Mark Seeman also has another post detailing how to perform logging of exceptions. Based upon his solution, I also created a decorator class:

public class LoggingExceptionFilter : IExceptionFilter
{
    private readonly IExceptionFilter _filter;

    private readonly ILogWriter _logWriter;

    public LoggingExceptionFilter(IExceptionFilter filter,
        ILogWriter logWriter)
    {
        if (filter == null)
        {
            throw new ArgumentNullException("filter");
        }

        if (logWriter == null)
        {
            throw new ArgumentNullException("logWriter");
        }

        _filter = filter;
        _logWriter = logWriter;
    }

    public void OnException(ExceptionContext filterContext)
    {
        _logWriter.WriteError(filterContext.Exception);
        _filter.OnException(filterContext);
    }
}

and changed the class “FilterConfig” to:

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new LoggingExceptionFilter(new HandleErrorAttribute(), new NLogWriter()));
    }
}

where NLogWriter is:

public class NLogWriter : ILogWriter
{
    private static readonly Logger _logger = LogManager.GetCurrentClassLogger();

    public void WriteError(Exception exception)
    {
        _logger.Error("An exception occurred with the following message {0}\n and the following stacktrace: {1}", exception.Message, exception.StackTrace);
    }
}

The code is available on GitHub.

Posted in .NET, ALT.NET, ASP.NET MVC, NLog

Castle Windsor NLog Integration dll versioning problem


Today I was setting up a new project that was using Castle Windsor’s NLog integration facility. However, when I tried running my ASP.NET MVC project I got the following error:

Could not load file or assembly ‘NLog, Version=2.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c’ or one of its dependencies. The located assembly’s manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

The solution was to add the following entry in the configuration file

<runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="NLog" publicKeyToken="5120e14c03d0593c" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.0.1.0" newVersion="2.0.1.0" />
      </dependentAssembly>
    </assemblyBinding>
</runtime>

It is important to note the xml namespace. This workaround, I believe, is not specific to NLog or Castle. From my limited understanding, this is caused by the fact that I’ve got a newer version of NLog (2.0.1.0) while Castle Windsor is expecting version 2.0.0.0.

Posted in .NET, ALT.NET, Castle.Windsor, NLog, Troubleshooting

ASP.NET MVC Label display name and validation messages


This is an aide-memoire for how ASP.NET MVC will output label and error messages and what “settings” will override which ones.

Model

public class LoginModel
{
    [Required]
    public string UserName { get; set; }
    [Required]
    [DataType(DataType.Password)]
    public string Password { get; set; }

    public bool RememberMe { get; set; }
}

View

<li>
    @Html.LabelFor(m => m.UserName)
    @Html.TextBoxFor(m => m.UserName, new { @class = "inputcontact" })
    @Html.ValidationMessageFor(m => m.UserName)
</li>
<li>
    @Html.LabelFor(m => m.Password)
    @Html.PasswordFor(m => m.Password, new { @class = "inputcontact" })
    @Html.ValidationMessageFor(m => m.Password)
</li>
<li>
    @Html.LabelFor(m => m.RememberMe, new { @class = "checkbox" })
    @Html.CheckBoxFor(m => m.RememberMe)
    <input type="submit" value="Log in" />
</li>

and this is the result when you run the code:

It should not be news that with the current code, the labels are named exactly as the Property names in the LoginModel class. Before explaining how to control the display names of the labels let me show the validation messages when submitting the form without filling in anything.

OriginalValidationOnce more, the PropertyNames in the LoginModel class are used in the validation messages.

As far as the display name of the label is concerned there are a couple of ways to control it:

  1. Use data annotations
  2. Use the overloaded version of Html.LabelFor

Data annotations

In our example, the two labels which I’d like to modify are “UserName”, “Password” and “RememberMe” which will be changed to “Username *”, “Password *” and “Remember me?” respectively:

public class LoginModel
{
    [Required]
    [Display(Name = "Username *")]
    public string UserName { get; set; }
    [Required]
    [DataType(DataType.Password)]
    [Display(Name = "Password *")]
    public string Password { get; set; }
    [Display(Name="Remember me?")]
    public bool RememberMe { get; set; }
}

Consequently, the updated form is:

DataAnnotationThis seems to be doing what we need until we exercise validation:

DataAnnotiationValidationAsteriskThe asterisks which are used to denote “mandatoriness” also appear in the validation message. Normally it’s not what we really want and instead we’d want the asterisk to be omitted from the message. Before, addressing that let’s see how we can control the display names of the label using the second method.

Html.LabelFor

With the model code left as is, and with the following changes to the view:

<li>
    @Html.LabelFor(m => m.UserName, "Username *")
    @Html.TextBoxFor(m => m.UserName, new { @class = "inputcontact" })
    @Html.ValidationMessageFor(m => m.UserName)
</li>
<li>
    @Html.LabelFor(m => m.Password, "Password *")
    @Html.PasswordFor(m => m.Password, new { @class = "inputcontact" })
    @Html.ValidationMessageFor(m => m.Password)
</li>
<li>
    @Html.LabelFor(m => m.RememberMe, "Remember me?", new { @class = "checkbox" })
    @Html.CheckBoxFor(m => m.RememberMe)
    <input type="submit" value="Log in" />
</li>

the display names and the validation messages are exactly the same as before. However, if we edit the model to:

public class LoginModel
{
    [Required]
    [Display(Name = "Username")]
    public string UserName { get; set; }
    [Required]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }
    public bool RememberMe { get; set; }
}

then this is what we get:

DesiredResultIn other words, the label text is obtained from the View while the field name for the validation message is obtained from the Model. However, a better way to express that would be:

public class LoginModel
{
    [Required(ErrorMessage = "The Username field is required")]
    public string UserName { get; set; }
    [Required(ErrorMessage = "The Password field is required")]
    [DataType(DataType.Password)]
    public string Password { get; set; }
    public bool RememberMe { get; set; }
}

Now these are just a couple of the quick and dirty ways to get the label display name and the validation message to work as required. However, it is not “optimal” in the sense that there is duplication of text and there might be “better” ways such as the one explained in this post or this one. Regardless of what way you choose, what I find quite surprising is that having this done automatically is not out of the box in ASP.NET MVC because it is such a common scenario.

Posted in AideMemoire, ASP.NET MVC

Getting to grips with EasyNetQ – Part 3 – Request Response


This post is about fleshing out the Request Response implementation of EasyNetQ.

Request class

using System;
using EasyNetQ;
using SubscribeWithLoggerConsoleAppNamespace;

namespace RequestClosureConsoleAppNamespace
{
    class Program
    {
        static void Main()
        {
            var logger = new MyLogger();

            using (var bus = RabbitHutch.CreateBus("host=Ubuntu-12"))
            {
                var myRequest = new MyRequest();

                using (var publishChannel = bus.OpenPublishChannel())
                {
                    for (var i = 0; i < 5; i++)
                    {
                        myRequest.Text = "Send to Response Server " + i;
                        publishChannel.Request<MyRequest, MyResponse>(myRequest, response =>
                                                                                logger.InfoWrite(
                                                                                     "Got response: {0}", response.Text));                        
                    }
                    Console.ReadKey();
                }
            }
        }
    }
}

The code highlighted in blue is the interesting part because it again assumes that there is some response code listening in to the incoming requests.

Upon running this code, this is what happens:

ENQ-RequestRunOverviewAn exhange has been added but when you look at the details of the exchange added, you’ll see that it’s different to when we run “Publish” code.

ENQ-RequestExchangeFirst of all, the name of the exchange doesn’t follow the same pattern and is simply named “easy_net_q_rpc”. The other difference is the fact that the exchange type is not “topic” but is “direct” instead.

The behaviour while running this code differs in the fact that “queues” are actually created when sending data:

ENQ-QueuesCreatedFollowingRequestIf you look at the names of the queues created, you’ll notice that they are named “easynetq.response.xxxxxx”. The fact that they are contain “response” and the fact that the “Ready” and “Total” columns are all 0 would indicate that these queues would be used for the Response code to send data to. However, when you look at the details in each queue, you will see that none of the queues is bound to the newly created exchange i.e. “easy_net_q_rpc” and they are in fact bound to the default exchange.

ENQ-RandomQueueBinding

This was, to say the least, quite puzzling. Hence, I asked about it on the forums and here is the answer from Mike Hadlow:

Each request creates a short lived temporary queue. They can only be consumed from the requester, but they are bound to an exchange 
that the responder can publish to. Each gets one message (the response), which is swiftly consumed, so you are unlikely to see the 
message on the queue.
Because you end up with 5 consumers all bound to different queues, there's no real order. It's down to whichever RabbitMQ sends first.

Upon exiting the console application, all the queues created by the latter are removed although the exchange created does remain.

Response class

using System;
using EasyNetQ;
using RequestClosureConsoleAppNamespace;
using SubscribeWithLoggerConsoleAppNamespace;

namespace ResponseClosureConsoleAppNamespace
{
    class Program
    {
        static void Main()
        {
            var logger = new MyLogger();
            Func<MyRequest, MyResponse> respond = request =>
                {
                    logger.InfoWrite("Received {0} ", request.Text);
                    return new MyResponse
                        {
                            Text = "Responding to " + request.Text
                        };
                };

            using (var bus = RabbitHutch.CreateBus("host=Ubuntu-12"))
            {
                bus.Respond(respond);
                Console.ReadKey();
            }
        }
    }
}

This code is fairly straighforward in the sense that it kind of echoes the content of the Request.

If you now run both console applications, this is what will happen:

ENQ-ResponseQueueCreatedFirst a new queue “RequestClosureConsoleAppNamespace_MyRequest:RequestClosureConsoleAppAssembly” is created and the naming convention follows the one used for a PubSub exchange scenario i.e. there is no “id” in the name.

The other is the order in which the messages are sent and received:

Response log

2013-08-16 11:17:42.6424 INFO Received Send to Response Server 1 
2013-08-16 11:17:42.6414 INFO Received Send to Response Server 0 
2013-08-16 11:17:42.6424 INFO Received Send to Response Server 4 
2013-08-16 11:17:42.6424 INFO Received Send to Response Server 3 
2013-08-16 11:17:42.6424 INFO Received Send to Response Server 2

Request log

2013-08-16 11:17:42.7865 INFO Got response: Responding to Send to Response Server 2
2013-08-16 11:17:42.7985 INFO Got response: Responding to Send to Response Server 0
2013-08-16 11:17:42.7985 INFO Got response: Responding to Send to Response Server 3
2013-08-16 11:17:42.8155 INFO Got response: Responding to Send to Response Server 4
2013-08-16 11:17:42.8155 INFO Got response: Responding to Send to Response Server 1

This is really surprising because not only would it appear that the requests were sent in random order but the responses were processed and sent back in random order as well.

For completeness, here are the

MyRequest and MyResponse classes

namespace RequestClosureConsoleAppNamespace
{
    public class MyRequest|MyResponse    
    {
        public string Text { get; set; }
    }
}
Posted in .NET, ALT.NET, EasyNetQ, RabbitMQ

Getting to grips with EasyNetQ – Part 2 – Logger


In part 1 of this series about EasyNetQ, I’ve provided an overview of what happens when we use the Publish and Subscribe methods as well as explaining the actual default behaviour. In part 2, I will experiment with the logger in EasyNetQ and is a logical continuation of part 1.

In this particular case, I will log to a file using NLog rather than logging to the console which is the default behaviour in EasyNetQ. So here is the code (source code available here) used:

Subscriber with logging

using EasyNetQ;
using PublishConsoleAppNamespace;

namespace SubscribeWithLoggerConsoleAppNamespace
{
    class Program
    {
        static void Main()
        {
            var logger = new MyLogger();
            logger.InfoWrite("In subscriber");
            var bus = RabbitHutch.CreateBus("host=Ubuntu-12", x => x.Register<IEasyNetQLogger>(_ => logger));

            bus.Subscribe<MyMessage>("SubscribeWithLoggerConsoleAppId"
                                     , msg => logger.InfoWrite(msg.Text));
        }
    }
}

MyLogger class

using System;
using EasyNetQ;
using NLog;

namespace SubscribeWithLoggerConsoleAppNamespace
{
    public class MyLogger:IEasyNetQLogger
    {
        private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
        public void DebugWrite(string format, params object[] args)
        {
            Logger.Debug(format);
        }

        public void InfoWrite(string format, params object[] args)
        {
            Logger.Info(format);
        }

        public void ErrorWrite(string format, params object[] args)
        {
            Logger.Error(format);
        }

        public void ErrorWrite(Exception exception)
        {
            Logger.ErrorException("An exception has occurred", exception);
        }
    }
}

NLog configuration file

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

  <!-- 
  See http://nlog-project.org/wiki/Configuration_file 
  for information on customizing logging rules and outputs.
   -->
  <targets>
    <!-- add your targets here -->

    <target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
            layout="${longdate} ${uppercase:${level}} ${message}" />

  </targets>

  <rules>
    <!-- add your logging rules here -->

    <logger name="*" minlevel="Trace" writeTo="f" />

  </rules>
</nlog>

The code in the SubscribeWithLogger Console App is the one of interest and in particular:

var logger = new MyLogger();
logger.InfoWrite("In subscriber");
var bus = RabbitHutch.CreateBus("host=Ubuntu-12", x => x.Register<IEasyNetQLogger>(_ => logger));

bus.Subscribe<MyMessage>("SubscribeWithLoggerConsoleAppId"
                         , msg => logger.InfoWrite(msg.Text));

This is pretty much the code described in the logging section of  this page. So first, you should run this code on its own and when you do so, the console application will just remain there. That is due to the fact that we are not disposing the connection:

bus.Dispose();

The reason why I’m not disposing of the connection is due to the fact that I don’t want to encounter the issue described at the end of the post in the first post in this series.

In any case close the application and if you look at the RabbitMQ admin web page, you will see that a new queue has been added because I used a new id “SubscribeWithLoggerConsoleAppId”:

ENQ-Queue for loggerNote that this queue has been bound to the already existing exchange “PublishConsoleAppNamespace_MyMessage:PublishConsoleAppAssembly”.

Now run the PublishConsoleApp code, which is also provided in the first post, on its own. What actually surprised me in this case was the number of messages being queued:

ENQ-20000MsgsQueuedIn the first post when we ran this, we had 10,000 messages queued where as now we had twice that amount. In fact, if we look at the “Queues” page we see that each queue contains 10,000 messages.

ENQ-QueueBreakdownSo, the logical question is what messages are now on each queue and the answer lies in running each of the subscriber application in turn.

This is the output when the information is sent to the console window.

ENQ-SubscribeConsoleand this is an excerpt of the output when the information is sent to a log file:

2013-08-15 12:17:04.9033 INFO Hello Rabbit9992
2013-08-15 12:17:04.9033 DEBUG Received 
    RoutingKey: '{0}'
    CorrelationId: '{1}'
    ConsumerTag: '{2}'
2013-08-15 12:17:04.9033 INFO Hello Rabbit9993
2013-08-15 12:17:04.9203 DEBUG Received 
    RoutingKey: '{0}'
    CorrelationId: '{1}'
    ConsumerTag: '{2}'
2013-08-15 12:17:04.9203 INFO Hello Rabbit9994
2013-08-15 12:17:04.9203 DEBUG Received 
    RoutingKey: '{0}'
    CorrelationId: '{1}'
    ConsumerTag: '{2}'
2013-08-15 12:17:04.9333 INFO Hello Rabbit9995
2013-08-15 12:17:04.9333 DEBUG Received 
    RoutingKey: '{0}'
    CorrelationId: '{1}'
    ConsumerTag: '{2}'
2013-08-15 12:17:04.9333 INFO Hello Rabbit9996
2013-08-15 12:17:04.9333 DEBUG Received 
    RoutingKey: '{0}'
    CorrelationId: '{1}'
    ConsumerTag: '{2}'
2013-08-15 12:17:04.9333 INFO Hello Rabbit9997
2013-08-15 12:17:04.9533 DEBUG Received 
    RoutingKey: '{0}'
    CorrelationId: '{1}'
    ConsumerTag: '{2}'
2013-08-15 12:17:04.9533 INFO Hello Rabbit9998
2013-08-15 12:17:04.9533 DEBUG Received 
    RoutingKey: '{0}'
    CorrelationId: '{1}'
    ConsumerTag: '{2}'
2013-08-15 12:17:04.9663 INFO Hello Rabbit9999

Effectively, it would appear that both queues contained the same published data and although the exchange type is topic, it is behaving very much like a fanout exchange i.e. the messages published are sent to all bound queues.

When you look at the overview of these two operations, you will see that both operations were quite quick although the debug to console (1) was quicker:

ENQ-TimeTaken

Posted in .NET, ALT.NET, EasyNetQ, RabbitMQ

Getting to grips with EasyNetQ – Part 1- PubSub


Following on from the series I had on RabbitMQ, I then moved onto EasyNetQ. Now, if you have no idea what RabbitMQ is, then this post is unlikely to be appropriate. I would suggest to first go through the blog posts by Derek Greer and then maybe go through the related blog posts. Having a basic understanding of AMQP (like I do) would also be very beneficial.

Now this post is not really the “Hello World” of how to use EasyNetQ. The GitHub wiki and this video tutorial amply demonstrate how to get going. What I want to achieve in this post is to hopefully give a bit more detail about what and how EasyNetQ is doing under the covers.

So, what I did first was to fork the project on Gitbub so that I could then debug code execution. Then I created my own project which would then reference the forked version of EasyNetQ. Hence, unless you also do the same, you won’t be able to use the code as is.

Publishing

Let’s start with some code in order to publish a message onto the message broker.

using System.Threading;
using EasyNetQ;

namespace PublishConsoleAppNamespace
{
    class Program
    {
        static void Main()
        {
            using (var bus = RabbitHutch.CreateBus("host=Ubuntu-12"))
            {
                Thread.Sleep(1000);                
                try
                {
                    using (var publishChannel = bus.OpenPublishChannel())
                    {
                        for (var i = 0; i < 10000; i++)
                        {
                            var message = new MyMessage
                            {
                                Text = "Hello Rabbit" + i
                            };
                          
                            publishChannel.Publish(message);
                        }
                    }
                }
                catch (EasyNetQException)
                {
                    // the server is not connected
                }
            }
        }
    }
}

namespace PublishConsoleAppNamespace
{
    public class MyMessage
    {
        public string Text { get; set; }
    }
}

Before running this code, here is the state of my RabbitMQ server:

ENQ-OverviewUpon running the code, here is what happens:

ENQ-PublishThe first thing to notice is that a message is indeed received on the server but that it is not queued. Hence, it is indication that when we publish a message, EasyNetQ does not declare a queue and this is confirmed by the fact that in “Global count – Queues ” = 0. However, a new exchange has indeed been created:

ENQ-Exchange created

The exchange is named according to the following pattern namespace_class:assembly and hence in our case, the name of our exchange is “PublishConsoleAppNamespace_MyMessage:PublishConsoleApp”. When I mentioned “namespace”, it is the namespace of the DTO “MyMessage” i.e. the exchange name is based upon the DTO class. The type of our exchange is “Topic”. Upon drilling into this exchange we’ll see that there are no queues bound to it:

ENQ-Exchange bindingsBefore closing the discussion about the Publisher code, I would like to draw your attention to this line:

var message = new MyMessage
{
    Text = "Hello Rabbit" + i
};

publishChannel.Publish(message);

Notice that we are passing message in as an argument to the Publish method and that the argument is of type “MyMessage”.

Were the code to be this:

var message = new MyMessage
{
    Text = "Hello Rabbit" 
};

publishChannel.Publish((message.Text + i));

Then the argument type you’re passing in actually a “String”. Hence, a new exchange will be created!

ENQ-StringPassedIn

So be careful and ascertain that you the right type is getting passed as an argument to the Publish method.

As the Publisher will not create the queue, it follows that in EasyNetQ, that this will happen in the Subscriber code.

Subscribing

So I then created a new console application:

using System;
using EasyNetQ;
using PublishConsoleApp;

namespace SubscribeConsoleAppNamespace
{
    class Program
    {
        static void Main()
        {
            Console.WriteLine("In subscriber");
            using (var bus = RabbitHutch.CreateBus("host=Ubuntu-12"))
            {
                bus.Subscribe<MyMessage>("SubscribeConsoleAppId"
                    , msg => Console.WriteLine(msg.Text));
                Console.ReadKey();
            }
        }
    }
}

Upon running this code on its own i.e. don’t run the PublisherConsoleApp code at the same time, the following message will appear in the console:

In subscriber
DEBUG: Trying to connect
DEBUG: OnConnected event fired
INFO: Connected to RabbitMQ. Broker: 'Ubuntu-12', Port: 5672, VHost: '/'
DEBUG: Declared Consumer. queue='PublishConsoleAppNamespace_MyMessage:PublishConsoleAppAssembly_SubscribeConsoleAppId', prefetchcount=50

This confirms that when we first ran the publisher, the messages just fell into a black hole. Moreover, as the last line and the following confirm, a queue has been created:

ENQ-Queue created NB: Had we run the Subscriber code before the Publisher code, both the queue and the exchange would have been created by EasyNetQ.

The name of the queue is again based upon the SubscribeConsoleApp code and the pattern is namespace_class:assembly_id. The naming requires further explanation and stems from this line of code:

bus.Subscribe<MyMessage>("SubscribeConsoleAppId"
                    , msg => Console.WriteLine(msg.Text));

Effectively, EasyNetQ would appear to be looking at the generic type being passed in i.e. “MyMessage” as well as the id i.e. “SubscribteConsoleAppId” in order to build the name of the queue. Hence, the namespace and assembly are “PublishConsoleAppNamespace”, “PublishConsoleAppAssembly” rather than “SubscribeConsoleAppNamespace”, “SubscribeConsoleAppAssembly”. So, the full name of the queue is “PublishConsoleAppNamespace_MyMessage:PublishConsoleAppAssembly_SubscribeConsoleAppId”

Moreover, you can also see that the queue has been bound to the exchange created earlier. Conversely, the exchange shows that the newly created queue has been bound

ENQ-Exchange bound to queue

One other thing to note is that with EasyNetQ the queue is durable i.e. even after a server restart, the queue will still be there.

Now, when you run the PublishConsoleApp on its own, you should see this:

ENQ-Messages queuedIn other words, the published messages have now been put into the queue until such time that the SubscribeConsoleApp is run.

ENQ-Messages consumed

One of the problems I encounted happened when I changed the code to this:

Console.WriteLine("In subscriber");
using (var bus = RabbitHutch.CreateBus("host=Ubuntu-12"))
{
    bus.Subscribe<MyMessage>("SubscribeConsoleAppId"
        , msg => Console.WriteLine(msg.Text));
}
Console.ReadKey();

In other words, I moved the code after the connection was closed and here is what was output to the console:

In subscriber
DEBUG: Trying to connect
DEBUG: OnConnected event fired
INFO: Connected to RabbitMQ. Broker: 'Ubuntu-12', Port: 5672, VHost: '/'
DEBUG: Declared Consumer. queue='PublishConsoleAppNamespace_MyMessage:PublishCon
soleAppAssembly_SubscribeConsoleAppId', prefetchcount=50
DEBUG: Received
        RoutingKey: ''
        CorrelationId: '75328e0f-20b4-43c0-b597-701bfde3f50c'
        ConsumerTag: 'ec9d949f-f42c-4fd1-810e-2a17f25a2ffd'
DEBUG: Model Shutdown for queue: 'PublishConsoleAppNamespace_MyMessage:PublishCo
nsoleAppAssembly_SubscribeConsoleAppId'
DEBUG: Connection disposed
Hello Rabbit0
INFO: Basic ack failed because channel was closed with message The AMQP operatio
n was interrupted: AMQP close-reason, initiated by Application, code=200, text="
Goodbye", classId=0, methodId=0, cause=. Message remains on RabbitMQ and will be
 retried.

As I was unsure about what was happening I posted this issue on the forums and this is the answer provided by Mike Hadlow, one of the authors of EasyNetQ:

When you dispose the IBus instance, the connection to the RabbitMQ broker is closed. 
The subscription handler (msg => Console.WriteLine(msg.Text)) runs on a separate thread 
when a message is received, so your code is setting up a subscription and then immediately 
closing the connection. I'm surprised that you are even seeing the WriteLine running. By 
the time it comes to send the ack the connection is closed and you get the error that you're seeing.

A basic application scenario is to open a connection (RabbitHutch.CreateBus) and keep it open for the 
lifetime of the app. When the app exits, you dispose the IBus instance which closes the connection.

So that poses the question of “How do I write the subscriber for a console application and closing the connection when the application is shut down?”. At this point, I am not quite sure but once I do, I’ll blog about it.

EDIT

Here is a site which I’ve found and which might solve the issue of running code at console application shut down. I have not tried it but it might be worth a try.

Posted in .NET, ALT.NET, EasyNetQ, RabbitMQ

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 3 other subscribers
June 2023
M T W T F S S
 1234
567891011
12131415161718
19202122232425
2627282930