Error registering IErrorHandler with Rebus - rebus

Error below occurred:
System.InvalidOperationException HResult=0x80131509 Message=A
circular dependency was detected for the service of type
'Rebus.Retry.IErrorHandler'.
Rebus.Retry.IErrorHandler(Rebus.AzureServiceBus.ErrorMessage.ErrorMessageHandler)
-> Rebus.Retry.IErrorHandler Source=Microsoft.Extensions.DependencyInjection StackTrace: at
Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteChain.CheckCircularDependency(Type
serviceType) at
Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type
serviceType, CallSiteChain callSiteChain) at
Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type
serviceType, Type implementationType, CallSiteChain callSiteChain,
ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound) at
Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(Type
serviceType, Type implementationType, CallSiteChain callSiteChain)
at
Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor
descriptor, Type serviceType, CallSiteChain callSiteChain) at
Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(Type
serviceType, CallSiteChain callSiteChain) at
Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type
serviceType, CallSiteChain callSiteChain) at
Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.CreateServiceAccessor(Type
serviceType) at
System.Collections.Concurrent.ConcurrentDictionary2.GetOrAdd(TKey
key, Func2 valueFactory) at
Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type
serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at
Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider
provider) at
RebusSubscriber.<>c__DisplayClass7_0`1.b__5(IResolutionContext
c) in C:_Repos\AzureServiceBus\Subscriber\RebusSubscriber.cs:line 45
at Rebus.Injection.Injectionist.ResolutionContext.GetTService
Below registers dependency for IErrorHandler
services.AddTransient<IErrorHandler, ErrorMessageHandler>();
Below is how it resolves ErrorMessageHandler and error above occurred.
Configure.With(Activator)
.Options(o =>
{
o.Decorate<IErrorHandler>(c =>
new ErrorMessageHandler(c.Get<IErrorHandler>()));
}
public class ErrorMessageHandler : IErrorHandler
{
private readonly IErrorHandler _errorHandler;
public ErrorMessageHandler(IErrorHandler errorHandler)
{
_errorHandler = errorHandler;
}
public async Task HandlePoisonMessage(TransportMessage transportMessage, ITransactionContext transactionContext, Exception exception)
{
// keep original behaviour
await _errorHandler.HandlePoisonMessage(transportMessage, transactionContext, exception);
}
}
It seems not using IResolutionContext causes the error.
Is there a solution?
Update
The problem is that IResolutionContext is required to register its own implementation instead of own IoC. It seems the name of IErrorHandler is overused.
My requirement is, given two separate components (Rebus wrapper, and its client), that we need to let client of rebus wrapper to define and use custom error handler, ErrorMessageHandler in this case.
For example, the pseudocode of Rebus wrapper below:
Configure.With(Activator)
.Options(o =>
{
//logic to implement below that allow different message handler somehow
//ErrorMessageHandler is this case.
o.Decorate<IErrorHandler>(c =>
xxxxxxx(c.Get<IErrorHandler>()));
}
Pseudocode of Client of the Rebus wrapper:
//pass ErrorMessageHandler to the Rebus wrapper above.

The error comes from the Microsoft Dependency Injection container – it's caused by the fact that your IErrorHandler implementation takes an IErrorHandler in its constructor, which it doesn't seem to like.
This particular pattern is the Decorator pattern, which helps transparently extend the capabilities of existing services. Rebus encourages you to use it to extend its behavior, which you seem to be doing correctly by registering it with configurer.Decorate<IErrorHandler>(...).
The error in this case seems to be that you're registering your ErrorMessageHandler in your IoC container. Rebus doesn't use your IoC container to resolve its own services, it's ONLY used for resolving message handlers.
Your IErrorHandler is not a message handler, it's the abstraction that decides how Rebus deals with messages once they have failed too many times.
Therefore: Don't register it in your IoC container.

Related

SignalR notification using SqlScaleoutConfiguration gives random exception for Rebus.Transport.TransactionContext not serializable

I use:
SignalR 2.2.2 in SqlScaleoutConfiguration
Rebus 3.0.1
Some events stored in Rebus are handled by a notification hub and pushed to the clients using signalR.
Everything works fine, but this morning, after having published a new version, none of the clients received the "new version" message probably because of the following exception:
10:39:04.586| |ERROR| |ProcessId=8196| |ThreadId=5| |SignalR.SqlMessageBus| |Stream 0 : Error starting SQL notification listener: System.Runtime.Serialization.SerializationException: Type 'Rebus.Transport.TransactionContext' in Assembly 'Rebus, Version=3.0.1.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
Server stack trace:
at System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)
at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo()
at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
at System.Runtime.Remoting.Channels.CrossAppDomainSerializer.SerializeMessageParts(ArrayList argsToSerialize)
at System.Runtime.Remoting.Messaging.SmuggledMethodCallMessage..ctor(IMethodCallMessage mcm)
at System.Runtime.Remoting.Messaging.SmuggledMethodCallMessage.SmuggleIfPossible(IMessage msg)
at System.Runtime.Remoting.Channels.CrossAppDomainSink.SyncProcessMessage(IMessage reqMsg)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at System._AppDomain.CreateInstance(String assemblyName, String typeName)
at System.Data.SqlClient.SqlDependency.CreateProcessDispatcher(_AppDomain masterDomain)
at System.Data.SqlClient.SqlDependency.ObtainProcessDispatcher()
at System.Data.SqlClient.SqlDependency.Start(String connectionString, String queue, Boolean useDefaults)
at Microsoft.AspNet.SignalR.SqlServer.ObservableDbOperation.StartSqlDependencyListener()
The message in Rebus queue results as correctly handled.
The handler is this:
public async Task Handle(ApplicationVersionEvent message)
{
await
Clients.All.CheckApplicationVersion(new ApplicationCurrentVersionNotification
{
CurrentVersion = message.CurrentVersion
});
}
It was resolved by a restart, but I need to understand what happened.
I similar issues are:
https://github.com/SignalR/SignalR/issues/3401
https://github.com/SignalR/SignalR/issues/3404
SQL Query Notifications do not always work in scaleout setup (SQL Server)
https://github.com/rebus-org/Rebus/issues/493
Rebus, exception when creating AppDomain / Instance from async Handler
but I think this is not the same case.
It is really hard for me to tell you what's going on here besides what you have already discovered: SignalR for some weird reason seems to want to serialize the values stashed in the current execution context, and one of those values is Rebus' current transaction context.
As explained in the links you included, Rebus stores an "ambient transaction" this way when handling a message, allowing all of its own operations to be enlisted in the same unit of work.
You could use the approach explained here, where the transaction context is temporarily removed in a safe way like this
public async Task Handle(SomeMessage message)
{
var transactionContext = AmbientTransactionContext.Current;
AmbientTransactionContext.Current = null;
try
{
JuggleWithAppDomainsInHere();
}
finally
{
AmbientTransactionContext.Current = transactionContext;
}
}
possibly moving relevant bits to the constructor/Dispose method respectively in a class that implements IDisposable, making for a smoother API:
using(new DismantleAmbientRebusStuff())
{
JuggleWithAppDomainsInHere();
}
I think someone who knows a lot about SignalR would need to chime in if we were to find out what really happened.
I forgot this issue, but I solved it by a workaround a little later on.
The clue is that SqlMessageBus serializes the context when it is initialized and this happens the first time it is retrieved invoking GetHubContext, so I forced its initialization before executing any command.
app.MapSignalR();
var context = new OwinContext(app.Properties);
var token = context.Get<CancellationToken>("host.OnAppDisposing");
if (token != CancellationToken.None)
{
token.Register(() =>
{
log.Info("host.OnAppDisposing");
// code to run when server shuts down
BackendMessageBusConfig.DisposeContainers();
});
}
// this code brings forward SignalR SqlMessageBus initialization
var forceInit = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
BackendMessageBusConfig.Register();

EntityContext throwing "not marked as serializable" in UnitOfWork Pattern using State Server

Background is ASP.NET WebForms application using Entity Framework with Repository and UnitOfWork pattern. Note that the application is also configured to use the out-of-proc StateServer for Session mgt which I understand means that anything I store in session must be serializable.
I also have an HttpModule configured to create a UnitOfWork object (which contains my entity context object) upon each HttpRequest, store it in HttpContext.Current.Items, and of course dispose it at the end of each request.
My UnitOfWork class itself contains properties for each of my repositories as well as the entity context itself.
In an effort to allow more flexible testing in the future, I created an IObjectContext interface with signatures for the methods and properties on my entity context, and I created a partial class for my entity context and inherited from it.
public class UnitOfWork : IUnitOfWork
{
private IObjectContext context;
}
public UnitOfWork(IObjectContext context)
{
this.context = context;
}
public partial class MyEntities : IObjectContext
{
}
private static void ApplicationBeginRequest(Object source, EventArgs e)
{
if (!HttpContext.Current.Items.Contains("UnitOfWork"))
{
IUnitOfWork unitOfWork = new UnitOfWork();
HttpContext.Current.Items.Add("UnitOfWork", unitOfWork);
}
}
private void ApplicationEndRequest(object sender, EventArgs e)
{
if (HttpContext.Current.Items["UnitOfWork"] != null)
((IUnitOfWork)HttpContext.Current.Items["UnitOfWork"]).Dispose();
}
The goal here is ultimately to allow me to fake my entity context object to create for example, an in-memory context for testing purposes.
Everything was going fine until I started getting "not marked as serializable" exceptions on my entity context object. Obviously my first thought was to just add [Serializable] to my partial entity context class, but then it started complaining that System.Data.Objects.ObjectContext in Assembly System.Data.Entity was not marked as serializable (which I obviously don't have any control over).
What am I missing here? It seems like I can't store my entity context object in HttpContext.Current.Items, which I must do for my unit of work pattern implementation.
Is this because I'm using the ASP.NET State Server instead of in-proc session mgt? Surely there's a way to store the context for the life of the HTTP request if you're using the State Server?
Just feel like I'm missing something obvious here. I've added [Serializable] to everything from the UnitOfWork to the MyEntities context to each repository class. Still can't get past the entity context itself.
Any ideas?
UPDATE (Adding Stack Trace):
[SerializationException: Type 'myDAL.Model.myEntities' in Assembly 'myDAL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.]
System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type) +14324629
System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context) +408
System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo() +420
System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder) +532
System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo) +969
System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck) +633
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck) +322
System.Web.Util.AltSerialization.WriteValueToStream(Object value, BinaryWriter writer) +1487
[HttpException (0x80004005): Unable to serialize the session state. In 'StateServer' and 'SQLServer' mode, ASP.NET will serialize the session state objects, and as a result non-serializable objects or MarshalByRef objects are not permitted. The same restriction applies if similar serialization is done by the custom session state store in 'Custom' mode.]
System.Web.Util.AltSerialization.WriteValueToStream(Object value, BinaryWriter writer) +2485899
System.Web.SessionState.SessionStateItemCollection.WriteValueToStreamWithAssert(Object value, BinaryWriter writer) +49
System.Web.SessionState.SessionStateItemCollection.Serialize(BinaryWriter writer) +746
System.Web.SessionState.SessionStateUtility.Serialize(SessionStateStoreData item, Stream stream) +336
System.Web.SessionState.SessionStateUtility.SerializeStoreData(SessionStateStoreData item, Int32 initialStreamSize, Byte[]& buf, Int32& length, Boolean compressionEnabled) +99
System.Web.SessionState.OutOfProcSessionStateStore.SetAndReleaseItemExclusive(HttpContext context, String id, SessionStateStoreData item, Object lockId, Boolean newItem) +3828904
System.Web.SessionState.SessionStateModule.OnReleaseState(Object source, EventArgs eventArgs) +1021
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +80
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +165
The stack trace indicates that there is a non-serializable object in the session, not in the context. Double check that you did not put your data object in session by mistake.
Putting it into the context request should not be giving this error.

No parameterless constructor object defined

I know that this is a duplicate question but i can't find answer to my error.
I'm trying to show a list of my rooms saved in database but i get next error:
Server Error in '/' Application.
No parameterless constructor defined for this object.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.MissingMethodException: No parameterless constructor defined for this object.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[MissingMethodException: No parameterless constructor defined for this object.]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache) +98
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache) +241
System.Activator.CreateInstance(Type type, Boolean nonPublic) +69
System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +67
[InvalidOperationException: An error occurred when trying to create a controller of type 'HotelProjectFinal.Controllers.RoomController'. Make sure that the controller has a parameterless public constructor.]
System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +182
System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +80
System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +74
System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +232
System.Web.Mvc.<>c__DisplayClass6.<BeginProcessRequest>b__2() +49
System.Web.Mvc.<>c__DisplayClassb`1.<ProcessInApplicationTrust>b__a() +13
System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f) +7
System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +22
System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Func`1 func) +124
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +98
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +50
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8969412
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184
But i have a constructor withou a parameter:
namespace HotelProjectFinal.Controllers
{
public class RoomController : Controller
{
private IRoomRepository repository;
public RoomController(IRoomRepository roomRepository)
{
repository = roomRepository;
}
public ViewResult List()
{
return View(repository.Rooms);
}
}
}
My view is :
#model IEnumerable<HotelProjectFinal.Models.Room>
#{
ViewBag.Title = "List";
}
#foreach (var p in Model)
{
<div class="item">
<h3>#p.Room_number</h3>
#p.Room_Type
<h4>#p.Room_Type.Price.ToString("c")</h4>
</div>
}
I am using ninject:
public class NinjectControllerFactory : DefaultControllerFactory
{
private IKernel ninjectKernel;
public NinjectControllerFactory()
{
ninjectKernel = new StandardKernel();
AddBindings();
}
protected override IController GetControllerInstance(RequestContext requestContext,
Type controllerType)
{
return controllerType == null
? null
: (IController)ninjectKernel.Get(controllerType);
}
private void AddBindings()
{
ninjectKernel.Bind<IRoomRepository>().To<EFRoomRepository>();
}
}
}
You've got a controller factory, but the fact that the stacktrace says nothing about Ninject suggests you have forgotten to tell MVC about it.
You could fix that by adding a line to tell it that.
However the recommended practice is to hook Ninject in by adding a NuGet reference to Ninject.MVC3. There are docs about it on the associated Ninject MVC3 wiki.
Please try changing your constructors to the following:
public RoomController() { } // You were missing this parameterless constructor
[Inject]
public RoomController(IRoomRepository roomRepository)
{
repository = roomRepository;
}
Ninject is looking for a parameterless constructor because you haven't specified [Inject] above constructor that you wish to use for dependency injection. This has confused "Ninject" and caused an exception to be thrown.
The primary DI pattern is Constructor Injection. When activating an instance of a type Ninject will choose one of the type’s constructors to use by applying the following rules in order:-
If a constructor has an [Inject] attribute, it is used (but if you apply the attribute to more than one, Ninject will throw a NotSupportedException at runtime upon detection).
If no constructors have an [Inject] attribute, Ninject will select the one with the most parameters that Ninject understands how to resolve.
If no constructors are defined, Ninject will select the default parameterless constructor (assuming there is one).
More information can be found here:
https://github.com/ninject/ninject/wiki/Injection-Patterns
As pointed out by Ruben, [Inject] attribute pollutes the controller with external concerns.
This ties your code to a specific container. (Although Ninject does permits the customization of the specific attribute to look for, the point remains – you’re polluting an interface with external concerns.)
Your actual problem probably relies in a missing reference to Ninject.MVC3
Even though IRoomRepository could be null, that doesn't make it a parameterless constructor. At first glace, it looks like your IoC isn't wired up correctly for IRoomRepository. With no IoC, or misconfigured IoC, the controller activator looks for a parameterless constructor for your controllers.
// This is a parameterless constructor.
public RoomController()
{ }
// This is not a parameterless constructor.
public RoomController(IRoomRepository roomRepository)
{
repository = roomRepository;
}
Edit, Are you using Ninject.Mvc and your base MvcHttpApplication is implementing NinjectHttpApplication?

Moq + Castle Dynamic Proxy - exception mocking nested generic interfaces

I'm receiving an argument exception from Castle Dynamic Proxy, while using Moq to create a mock of object that is implementing a nested generic interface with generic method that has an interface constraint.
The exception is: System.ArgumentException : Cannot set parent to an interface.
Happens while accessing Object property of the mock directly after the mock creation. (Call stack is at the bottom for the sake of readability)
The code is simple and self-describing:
public interface A<T>
{
void Method<Z>() where Z : T;
}
public interface B
{
}
[Test]
public void MockNestedGenericInterfaceTest()
{
Mock<A<B>> mock = new Mock<A<B>>();
var o = mock.Object; //argument exception here
}
Test does not generate an exception if where Z : T clause is removed.
I did some research and found a ticket here. I'm using latest versions of Moq and Castle.
Is there a workaround for this problem? The only way I see it working is a manual mock implementation. Rhino mocks did not work for me either.
Thank you.
Call stack:
at System.Reflection.Emit.TypeBuilder.SetParent(Type parent)
at Castle.DynamicProxy.Generators.Emitters.GenericUtil.CopyGenericArguments(MethodInfo methodToCopyGenericsFrom, Dictionary2 name2GenericType, ApplyGenArgs genericParameterGenerator)
at Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.CopyGenericParametersFromMethod(MethodInfo methodToCopyGenericsFrom)
at Castle.DynamicProxy.Generators.InvocationTypeGenerator.Generate(ClassEmitter class, ProxyGenerationOptions options, INamingScope namingScope)
at Castle.DynamicProxy.Contributors.InterfaceProxyWithoutTargetContributor.GetInvocationType(MetaMethod method, ClassEmitter emitter, ProxyGenerationOptions options)
at Castle.DynamicProxy.Contributors.InterfaceProxyWithoutTargetContributor.GetMethodGenerator(MetaMethod method, ClassEmitter class, ProxyGenerationOptions options, OverrideMethodDelegate overrideMethod)
at Castle.DynamicProxy.Contributors.CompositeTypeContributor.ImplementMethod(MetaMethod method, ClassEmitter class, ProxyGenerationOptions options, OverrideMethodDelegate overrideMethod)
at Castle.DynamicProxy.Contributors.CompositeTypeContributor.Generate(ClassEmitter class, ProxyGenerationOptions options)
at Castle.DynamicProxy.Generators.InterfaceProxyWithoutTargetGenerator.GenerateType(String typeName, Type proxyTargetType, Type[] interfaces, INamingScope namingScope)
at Castle.DynamicProxy.Generators.InterfaceProxyWithTargetGenerator.GenerateCode(Type proxyTargetType, Type[] interfaces, ProxyGenerationOptions options)
at Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, IInterceptor[] interceptors)
at Moq.Proxy.CastleProxyFactory.CreateProxy(ICallInterceptor interceptor, Type[] interfaces, Object[] arguments)
at Moq.Mock1.b__0()
at Moq.Mock1.InitializeInstance()
at Moq.Mock1.OnGetObject()
at Moq.Mock`1.get_Object()
This bug was fixed in last version of DynamicProxy. Make sure you're using latest version of Moq

Resolving HttpRequestScoped services in ASMX with Autofac 2.1.12

The Description I had a legacy type that is HttpRequestScoped and a legacy web service consuming that service. To resolve services in legacy concerns, I have a global resolver. This was all working well in 1.4, and now that I'm using 2.1.12 I'm experiencing DependencyResolutionException.
The Code In 2.1.12, my Global.asax.cs:
builder.Register(c => new SomeLegacyType(HttpContext.Current)) // note: it relies on HttpContext.Current
.As<SomeLegacyType>()
.HttpRequestScoped();
_containerProvider = new ContainerProvider(builder.Build()); // this is my app's IContainerProvider
Setup.Resolver = new AutofacResolver(_containerProvider.ApplicationContainer);
Setup.Resolver is a singleton, and it is being set to AutofacResolver which looks something like this:
public class AutofacResolver : IResolver
{
private readonly IContainer _container;
public AutofacResolver(IContainer container)
{
_container = container;
}
public TService Get<TService>()
{
return _container.Resolve<TService>();
}
}
The web service looks like this:
[WebService]
public LegacyWebService : WebService
{
[WebMethod(EnableSession=true)]
public String SomeMethod()
{
var legacyType = Setup.Resolver.Get<SomeLegacyType>();
}
}
The Exception The following exception when Setup.Resolver.Get<SomeLegacyType>() is called:
Autofac.Core.DependencyResolutionException: No scope matching the expression 'value(Autofac.Builder.RegistrationBuilder`3+<>c__DisplayClass0[SomeAssembly.SomeLegacyType,Autofac.Builder.SimpleActivatorData,Autofac.Builder.SingleRegistrationStyle]).lifetimeScopeTag.Equals(scope.Tag)' is visible from the scope in which the instance was requested.
at Autofac.Core.Lifetime.MatchingScopeLifetime.FindScope(ISharingLifetimeScope mostNestedVisibleScope)
at Autofac.Core.Resolving.ComponentActivation..ctor(IComponentRegistration registration, IResolveOperation context, ISharingLifetimeScope mostNestedVisibleScope)
at Autofac.Core.Resolving.ResolveOperation.Resolve(ISharingLifetimeScope activationScope, IComponentRegistration registration, IEnumerable`1 parameters)
at Autofac.Core.Lifetime.LifetimeScope.Resolve(IComponentRegistration registration, IEnumerable`1 parameters)
at Autofac.Core.Container.Resolve(IComponentRegistration registration, IEnumerable`1 parameters)
at Autofac.ResolutionExtensions.TryResolve(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance)
at Autofac.ResolutionExtensions.Resolve(IComponentContext context, Service service, IEnumerable`1 parameters)
at Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context, IEnumerable`1 parameters)
at Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context)
Side Question Is there a better way to have properties injected in ASMX, the same way my ASPX pages are injected (rather than use Setup.Resolver)? I use the AttributedInjectionModule because of legacy concerns. It doesn't appear that the module works on ASMX.
If you configure your 'resolver' to use the RequestLifetime rather than ApplicationContainer all should work as expected.
This means your IContainer parameter will have to change to ILifetimeScope.
I'm not sure about a better way to inject ASMX dependencies, there may be one but I don't think Autofac supports it.

Resources