Skip to content

Less handler fails in conjunction with 'Microsoft.Extensions.DependencyInjection' v8 #82

@julealgon

Description

@julealgon

The Less request handler (BundleTransformer.Less.HttpHandlers.LessAssetHandler) defines 2 public constructors:

/// <summary>
/// Constructs a instance of the debugging LESS HTTP handler
/// </summary>
public LessAssetHandler()
: this(HttpContext.Current.Cache,
BundleTransformerContext.Current.FileSystem.GetVirtualFileSystemWrapper(),
BundleTransformerContext.Current.Configuration.GetCoreSettings().AssetHandler)
{ }
/// <summary>
/// Constructs a instance of the debugging LESS HTTP handler
/// </summary>
/// <param name="cache">Server cache</param>
/// <param name="virtualFileSystemWrapper">Virtual file system wrapper</param>
/// <param name="assetHandlerConfig">Configuration settings of the debugging HTTP handle</param>
public LessAssetHandler(Cache cache,
IVirtualFileSystemWrapper virtualFileSystemWrapper,
AssetHandlerSettings assetHandlerConfig)
: base(cache, virtualFileSystemWrapper, assetHandlerConfig)
{ }

This breaks when attempting to resolve the handler through DI when using Microsoft.Extensions.DependencyInjection v8, as a breaking change was introduced that now throws an InvalidOperationException when multiple valid constructors are found.

Section of a stacktrace from our WebForms app which uses Autofac through MEDI: 

Exception information:
Exception type: InvalidOperationException
Exception message: Multiple constructors accepting all given argument types have been found in type 'BundleTransformer.Less.HttpHandlers.LessAssetHandler'. There should only be one applicable constructor.
at bool Microsoft.Extensions.DependencyInjection.ActivatorUtilities.TryFindMatchingConstructor(Type instanceType, Type[] argumentTypes, out ConstructorInfo matchingConstructor, out Nullable[] parameterMap)
at void Microsoft.Extensions.DependencyInjection.ActivatorUtilities.FindApplicableConstructor(Type instanceType, Type[] argumentTypes, out ConstructorInfo matchingConstructor, out Nullable[] matchingParameterMap)
at object Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, object[] parameters)
at object OutProject.DependencyInjection.AutofacWebObjectActivator.GetService(Type serviceType) in ....

And how we are configuring the handler in the web.config:

<system.web>
  <pages>
    <httpHandlers>
      <add path="*.less" verb="GET" type="BundleTransformer.Less.HttpHandlers.LessAssetHandler, BundleTransformer.Less" />
      ...
    </httpHandlers>
    ...
  </pages>
</system.web>

Here is the documentation regarding the breaking change in MEDI v8 that explains the issue in more detail:

This likely breaks with other containers or setups as well since depending on the DI adapter implementation, it could just call directly into a build-up method in the DI library and many DI libraries will choke when multiple public constructors are found.

In our setup, we should be able to workaround this issue by manually registering the handler using a factory registration, but you might still want to reconsider the design here and opt to have just a single constructor (and maybe move the second one into a factory class).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions