StructureMap LoadFrom causes ArgumentOutOfRangeException "Length cannot be less than zero."

40 views
Skip to first unread message

Jeff T

unread,
Mar 27, 2015, 12:56:15 AM3/27/15
to masstrans...@googlegroups.com
I am trying to use the AzureServiceBus as my transport and StructureMapIntegration but am running into issues with the StructureMap part of it. I've created a subscriber console application that is as simple as I can make it that has this problem.  The code is listed below.  To summarize, when I manually setup a consumer instead of using StructureMap it hooks it up, the message gets routed to it and everything works as expected.  Then when I switch to using SM and the extension LoadFrom (Container), it still calls my consumer and runs through it, but then after it is done it throws the following exception:

System.ArgumentOutOfRangeException was unhandled by user code
  HResult=-2146233086
  Message=Length cannot be less than zero.
Parameter name: length
  Source=mscorlib
  ParamName=length
  StackTrace:
       at System.String.Substring(Int32 startIndex, Int32 length)
       at Magnum.Extensions.ExtensionsToType.ToShortTypeName(Type type)
       at MassTransit.Pipeline.Sinks.ContextConsumerMessageSink`2.<>c__DisplayClass1.<Selector>b__0(IConsumeContext`1 context) in z:\Builds\work\aa063b4295dfc097\src\MassTransit\Pipeline\Sinks\ContextConsumerMessageSink.cs:line 51
       at MassTransit.Pipeline.Sinks.InboundConvertMessageSink`1.<>c__DisplayClass2.<>c__DisplayClass4.<Enumerate>b__1(IConsumeContext x) in z:\Builds\work\aa063b4295dfc097\src\MassTransit\Pipeline\Sinks\InboundConvertMessageSink.cs:line 45
       at MassTransit.Context.ServiceBusReceiveContext.DeliverMessageToConsumers(IReceiveContext context) in z:\Builds\work\aa063b4295dfc097\src\MassTransit\Context\ServiceBusReceiveContext.cs:line 162
  InnerException: 

I've narrowed down the issue to the config.Subscribe section below:

                                config.Subscribe(subs =>
                                                 {
                                                     // using the LoadFrom causes an ArgumentOutOfRangeException to be throw
                                                     // subs.LoadFrom(container);
                                                     subs.Consumer<TestMessage1Consumer>().Permanent();
                                                 });

The consumer I created just uses the default constructor without any SM injection going on, very vanilla plain example.

I am using the following NuGet packages:

  <package id="Magnum" version="2.1.3" targetFramework="net45" />
  <package id="MassTransit" version="2.9.9" targetFramework="net45" />
  <package id="MassTransit.AzureServiceBus" version="0.4.1" targetFramework="net45" />
  <package id="MassTransit.StructureMap" version="2.9.9" targetFramework="net45" />
  <package id="Microsoft.WindowsAzure.ConfigurationManager" version="3.1.0" targetFramework="net45" />
  <package id="Newtonsoft.Json" version="6.0.8" targetFramework="net45" />
  <package id="structuremap" version="3.1.4.143" targetFramework="net45" />
  <package id="WindowsAzure.ServiceBus" version="2.6.2" targetFramework="net45" />



Here is my entire console application in case the rest of the configuration helps:

    class Program
    {
        static void Main(string[] args)
        {
            var container = StructureMapFactory.Container;

            var bus = ServiceBusFactory.New(config =>
                            {
                                var azureNamespace = ConfigurationManager.AppSettings["ServiceBus.Namespace"];
                                var queueUri = "azure-sb://" + azureNamespace + "/TestCloudSubscriber3";

                                config.ReceiveFrom(queueUri);

                                config.UseAzureServiceBus(a => a.ConfigureNamespace(azureNamespace, h =>
                                                                                                    {
                                                                                                        h.SetKeyName("RootManageSharedAccessKey");
                                                                                                        h.SetKey(ConfigurationManager.AppSettings["ServiceBus.Key"]);
                                                                                                    }));
                                config.UseAzureServiceBusRouting();

                                config.SetConcurrentConsumerLimit(64);
                                config.Subscribe(subs =>
                                                 {
                                                     // using the LoadFrom causes an ArgumentOutOfRangeException to be throw
                                                     // subs.LoadFrom(container);
                                                     subs.Consumer<TestMessage1Consumer>().Permanent();
                                                 });
                            });


            container.Inject(bus);

            Console.ReadLine();
        }
    }

And here is my simple Consumer that I am testing with:

    public interface ITestMessage1Consumer : Consumes<ISomethingHappened>.Context
    {
        
    }

    public class TestMessage1Consumer : ITestMessage1Consumer
    {
        public void Consume(IConsumeContext<ISomethingHappened> message)
        {
            Trace.TraceInformation("TXT: " + message.Message.What +
                        "  SENT: " + message.Message.When +
                        "  PROCESSED: " + DateTime.Now +
                        " (" + Thread.CurrentThread.ManagedThreadId + ")");

            // Simulate processing time
            Thread.Sleep(250);
        }
    }


Sorry if I'm providing too much code, but I've been banging my head on this for a while so any suggestions are appreciated.

Thanks,

Jeff

Chris Patterson

unread,
Mar 27, 2015, 10:11:41 AM3/27/15
to masstrans...@googlegroups.com
The one item left out is how you're registering the consumer. Should just be a RegisterType, with only the concrete class consumer type registered.


--
You received this message because you are subscribed to the Google Groups "masstransit-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to masstransit-dis...@googlegroups.com.
To post to this group, send email to masstrans...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/masstransit-discuss/e6e52175-f41e-4a6f-889a-ce205aa129f9%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jeff Treuting

unread,
Mar 27, 2015, 12:10:04 PM3/27/15
to masstrans...@googlegroups.com

I thought the LoadFrom extension method with the StructureMapIntegration Nuget package took care of that for me.  Is that not correct?


From: masstrans...@googlegroups.com <masstrans...@googlegroups.com> on behalf of Chris Patterson <ch...@phatboyg.com>
Sent: Friday, March 27, 2015 7:11 AM
To: masstrans...@googlegroups.com
Subject: Re: [masstransit-discuss] StructureMap LoadFrom causes ArgumentOutOfRangeException "Length cannot be less than zero."
 
You received this message because you are subscribed to a topic in the Google Groups "masstransit-discuss" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/masstransit-discuss/Kw1e4tvUm6Q/unsubscribe.
To unsubscribe from this group and all its topics, send an email to masstransit-dis...@googlegroups.com.

To post to this group, send email to masstrans...@googlegroups.com.

Chris Patterson

unread,
Mar 27, 2015, 12:30:40 PM3/27/15
to masstrans...@googlegroups.com
It doesn't register your consumers in the container for you, it just finds them in the container and subscribes them to the queue.


Jeff Treuting

unread,
Mar 27, 2015, 12:43:22 PM3/27/15
to masstrans...@googlegroups.com

Oh sorry I was confused with what you were saying.  Here is my StrucutreMap config that is used in my simple example.  It is relying on the SingleImplementationsOfInterface right now since I created the consumer against a single interface.  I had tried using AddAllTypesOf(typeof(IConsumer)) and ConnectImplementationsToTypesClosing(typeof(Consumes<>.Context)) previously but was hitting a wall so tried to simplify.



public class StructureMapConfig : Registry
    {
        public StructureMapConfig()
        {
            Scan(scanner =>
                 {
                     scanner.TheCallingAssembly();
                     scanner.SingleImplementationsOfInterface();

                     scanner.WithDefaultConventions();
                 });
        }
    }


Sent: Friday, March 27, 2015 9:30 AM

Chris Patterson

unread,
Mar 27, 2015, 1:48:39 PM3/27/15
to masstrans...@googlegroups.com
I THINK this works:

 cfg.Scan(x =>
               {
                   x.TheCallingAssembly();
                   x.AddAllTypesOf(typeof(IConsumer));
               });
 
Might need to add an .AsSelf() or something but this seems to be how it's done around various places I've looked.


Dru Sellers

unread,
Mar 27, 2015, 2:18:08 PM3/27/15
to masstrans...@googlegroups.com
Agreed re: AsSelf. the items have to have the service type be the concrete type.

-d

Jeff Treuting

unread,
Mar 27, 2015, 4:06:06 PM3/27/15
to masstrans...@googlegroups.com

Thanks guys.  I will give that a shot tonight and see how it goes.  I appreciate it.


From: masstrans...@googlegroups.com <masstrans...@googlegroups.com> on behalf of Dru Sellers <d...@drusellers.com>
Sent: Friday, March 27, 2015 11:18 AM
Reply all
Reply to author
Forward
0 new messages