0

Please note that the issue I'm experiencing is NOT a generic "IndexOutOfRangeException", which I am well familiar with. The issue I am seeing is specific to the Unity DI container when using with an ASP.NET Web API back end, and occurs at random times.

I am using a Unity DI container within the context of an ASP.NET Web API back end written in C#. For the most part, the site works fine. However, at random times throughout the day, we are getting an HTTP 500 error code with the message "An error occurred when trying to create a controller of type 'MyController'. Make sure that the controller has a parameterless public constructor. .... Exception is: IndexOutOfRangeException - Index was outside the bounds of the array".

We've tried using IIS configuration to recycle the app pool on a regular basis, but we are still getting this error.

Here's my code

protected void Application_Start()
{
    GlobalConfiguration.Configure(WebApiConfig.Register);
    GlobalConfiguration.Configuration.EnableDependencyInjection();
    AreaRegistration.RegisterAllAreas();
    RouteConfig2.RegisterRoutes(RouteTable.Routes);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
    UnityConfig.RegisterComponents();
}

public static class UnityConfig
{
    public static void RegisterComponents()
    {
        var container = UnityDI.Containers.GetContainer();
        GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
    }
}


namespace UnityDI
{
    public static class Containers
    {
        public static UnityContainer GetContainer(bool staticDbFactory = false)
        {
            var container = new UnityContainer();

            //DbContext
            if (staticDbFactory)
                container.RegisterType<IDbContextFactory, DbContextFactory>(new ContainerControlledLifetimeManager());
            else
                container.RegisterType<IDbContextFactory, DbContextFactory>();

            //Services
            container.RegisterType<IAddressService, AddressService>();
            container.RegisterType<IAdminService, AdminService>();
            /* (other items omitted for brevity) */

            /* EdiFileProcessorBase registrations */
            container.RegisterType<EdiFileProcessorBase, AbcInboundBolFileProcessor>(EdiFileTypeEnum.AbcInboundBol.ToString());
            container.RegisterType<EdiFileProcessorBase, AbcInboundVesselStatusFileProcessor>(EdiFileTypeEnum.AbcInboundVesselStatus.ToString());
            return container;
        }
    }
}

[InjectionConstructor]
public DocumentService(
    IDbContextFactory dbContextFactory,
    IBlobStorageService blobStorageService,
    Lazy<IEmailService> emailService,
    Lazy<ILocationService> locationService,
    Lazy<IMailingService> mailService,
    Lazy<IOceanBookingService> oceanBookingService
    ) : base(dbContextFactory)
{
    _blobStorageService = blobStorageService;
    _emailService = emailService;
    _locationService = locationService;
    _mailService = mailService;
    _xmlHelper = new XMLHelper();
    _oceanBookingService = oceanBookingService;

    Aspose.Pdf.License license = new Aspose.Pdf.License();
    license.SetLicense("Aspose.Total.lic");
    license.Embedded = true;

    Aspose.Words.License wlicense = new Aspose.Words.License();
    wlicense.SetLicense("Aspose.Total.lic");
    Aspose.Cells.License clicense = new Aspose.Cells.License();
    clicense.SetLicense("Aspose.Total.lic");
}

Here's the full error message we're seeing.


> An error occurred when trying to create a controller of type
> 'MyController'. Make sure that the controller has a parameterless
> public constructor. Resolution of the dependency failed, type =
> "ACME.AcmeApp.API.Controllers.MyController", name = "(none)".
> Exception occurred while: Calling constructor
> ACME.AcmeApp.Services.Services.DocumentService(ACME.AcmeApp.DAL.Interfaces.IDbContextFactory
> dbContextFactory, ACME.AcmeApp.Services.Interfaces.IBlobStorageService
> blobStorageService,
> System.Lazy`1[[ACME.AcmeApp.Services.Interfaces.IEmailService,
> ACME.AcmeApp.Services, Version=1.0.0.0, Culture=neutral,
> PublicKeyToken=null]] emailService,
> System.Lazy`1[[ACME.AcmeApp.Services.Interfaces.ILocationService,
> ACME.AcmeApp.Services, Version=1.0.0.0, Culture=neutral,
> PublicKeyToken=null]] locationService,
> System.Lazy`1[[ACME.AcmeApp.Services.Interfaces.IMailingService,
> ACME.AcmeApp.Services, Version=1.0.0.0, Culture=neutral,
> PublicKeyToken=null]] mailService,
> System.Lazy`1[[ACME.AcmeApp.Services.Interfaces.IOceanBookingService,
> ACME.AcmeApp.Services, Version=1.0.0.0, Culture=neutral,
> PublicKeyToken=null]] oceanBookingService). Exception is:
> IndexOutOfRangeException - Index was outside the bounds of the array.
> ----------------------------------------------- At the time of the exception, the container was:
> 
>   Resolving ACME.AcmeApp.API.Controllers.MyController,(none)  
> Resolving parameter "documentService" of constructor
> ACME.AcmeApp.API.Controllers.MyController(ACME.AcmeApp.DAL.Interfaces.IDbContextFactory
> dbFactory, ACME.AcmeApp.Services.Interfaces.ISiService siService,
> ACME.AcmeApp.Services.Interfaces.IStorageService storageService,
> ACME.AcmeApp.Services.Services.IRepairService repairService,
> ACME.AcmeApp.Services.Interfaces.IDocumentService documentService,
> ACME.AcmeApp.Services.Interfaces.IImageService ImageService,
> ACME.AcmeApp.Services.Interfaces.INoteService noteService,
> ACME.AcmeApp.Services.Interfaces.IVisitService visitService,
> ACME.AcmeApp.Services.Interfaces.IOrderService orderService,
> ACME.AcmeApp.Services.Interfaces.IAuditService auditService,
> ACME.AcmeApp.Services.Interfaces.INotificationService
> notificationService, ACME.AcmeApp.Services.Interfaces.ILocationService
> locationService, ACME.AcmeApp.Services.ICustomerService
> customerSerivce, ACME.AcmeApp.Services.Interfaces.ICommonService
> commonService,
> System.Lazy`1[[ACME.AcmeApp.Services.Interfaces.ILegService,
> ACME.AcmeApp.Services, Version=1.0.0.0, Culture=neutral,
> PublicKeyToken=null]] legService)
>     Resolving ACME.AcmeApp.Services.Services.DocumentService,(none) (mapped from ACME.AcmeApp.Services.Interfaces.IDocumentService,
> (none))
>     Calling constructor ACME.AcmeApp.Services.Services.DocumentService(ACME.AcmeApp.DAL.Interfaces.IDbContextFactory
> dbContextFactory, ACME.AcmeApp.Services.Interfaces.IBlobStorageService
> blobStorageService,
> System.Lazy`1[[ACME.AcmeApp.Services.Interfaces.IEmailService,
> ACME.AcmeApp.Services, Version=1.0.0.0, Culture=neutral,
> PublicKeyToken=null]] emailService,
> System.Lazy`1[[ACME.AcmeApp.Services.Interfaces.ILocationService,
> ACME.AcmeApp.Services, Version=1.0.0.0, Culture=neutral,
> PublicKeyToken=null]] locationService,
> System.Lazy`1[[ACME.AcmeApp.Services.Interfaces.IMailingService,
> ACME.AcmeApp.Services, Version=1.0.0.0, Culture=neutral,
> PublicKeyToken=null]] mailService,
> System.Lazy`1[[ACME.AcmeApp.Services.Interfaces.IOceanBookingService,
> ACME.AcmeApp.Services, Version=1.0.0.0, Culture=neutral,
> PublicKeyToken=null]] oceanBookingService)  Index was outside the
> bounds of the array.

Nkosi
  • 235,767
  • 35
  • 427
  • 472
P.J.
  • 29
  • 1
  • 3
  • My question is not a duplicate. This is not a generic IndexOutOfRangeException, as the exception seems to be within Unity DI code, not code that I've written. My issue is specific to Unity DI. – P.J. Aug 16 '19 at 05:01
  • Please remove the "marked as duplicate" tag. – P.J. Aug 16 '19 at 05:08
  • Can you post the code inside the relevant constructor for `ACME.AcmeApp.Services.Services.DocumentService`? – Jonas Høgh Aug 16 '19 at 11:03
  • I've added the code for the DocumentService constructor above. – P.J. Aug 16 '19 at 11:25
  • Smells like a bug in the Aspose license initialization, such as the one this user is experiencing: https://forum.aspose.com/t/indexoutofrangeexception-occurs-randomly-in-setting-license-for-aspose-pdf/35839 – Jonas Høgh Aug 16 '19 at 11:28
  • I don't think that's it. That post is over 4 years old and refers to Aspose PDF for .NET 10.1.0. We're using version 19.1.0. – P.J. Aug 16 '19 at 11:48

1 Answers1

0

I realize this isn't an answer as such, but I hope you can use it anyway, it's too long for a comment, so here goes:

I don't believe the error is related to Unity as such. Unity is telling you that the DocumentService constructor is throwing an exception. I would proceed with the following steps to investigate further:

  1. If possible, move all the Aspose license initialization code to a static method, and call it once at application startup time. There's no reason to waste time having Aspose look for license files over and over again
  2. Inject a logger into the documentservice, wrap the constructor body in a try/catch, and log the exception to your logger
  3. If there's anything interesting in the default constructor of XMLHelper, investigate this code as well. Since its constructed explicitly in the code rather than by Unity, this could also be the source of the error.
Jonas Høgh
  • 10,358
  • 1
  • 26
  • 46
  • 1
    These are good suggestions. I will try them and report back what I find. Thanks! – P.J. Aug 16 '19 at 12:16
  • It looks like the issue was indeed the Apose licensing. I moved that code into the Application_Start method, and the bulk of the intermittent HTTP 500 errors are gone. – P.J. Aug 19 '19 at 11:33
  • Aspose APIs require license initiation code to be processed first and only once in the whole application life cycle. For a web (ASP.NET) based application, it is always recommended to set the licensing code in Application_Start event. PS. I am working as Support developer/ Evangelist at Aspose. – Amjad Sahi Aug 27 '19 at 14:30