Autofac returns different instance in asp.net mvc web api - asp.net-mvc-4

I'm using autofac in an asp.net mvc and webapi project.
In the configuration I'm doing this :
var builder = new ContainerBuilder();
builder.Register(x => NHibernateConfigurator.BuildSessionFactory()).SingleInstance();
builder.Register(x => x.Resolve<ISessionFactory>().OpenSession()).InstancePerHttpRequest();
builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource());
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
Now the problem is that in an api controller if I inject ISession via the constructer and also call
DependencyResolver.Current.GetService<ISession>()
it will return 2 different instances.
I'm guessing the problem is because of these 2 lines :
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
But how can I make it return the same instance ?
Edit:
Just to be more clear - I'm expecting the same instance of ISession per HttpRequest. Right now I'm getting different instances on the same request.
Thanks

Ok, I think I found the answer - it can't be done .. at least not with DependencyResolver.
ASP .Net 4 Web Api RC + Autofac manual resolving
I did what it said in the comments, added IComponentContext to the constructor and used that to resolve what I needed.
It seems to be working. Thanks.

Related

Netcore how to remove endpoints/routes at runtime

Is there a way to remove registered routes in net core web api project?
So I'm dynamically adding controllers in a net core web api project, the controller class code is not part of the project but dynamically loaded, compiled and add to the project at runtime
//code that compiles the c# class(controller)
var compiledAssembly= CompileHelper.Compile(csharpCode)
using (var controllerAssemblyMs = new MemoryStream(compiledAssembly))
{
var assemblyLoadContext = new SimpleAssemblyLoadContext();//inherits AssemblyLoadContext
var dynamicControllers = new MvcAssemblyPart(controllerAssemblyMs);
Services.AddControllersWithViews().ConfigureApplicationPartManager(apm =>
apm.ApplicationParts.Add(dynamicControllers));
}
so any new Endpoints/Routes are registered.
the problem is that because routes have been registered every time it compiles the code, if I change Get action to Post action, compile before and after, the endpoints end up in an erroneous state,
AmbiguousMatchException: The request matched multiple endpoints. Matches:
DynamicCodeProject.Controllers.DynamicallyAddedController.Post (string)
DynamicCodeProject.Controllers.DynamicallyAddedController.Get (string)
in which case I have to restart the application,
is it possible to remove routes/endpoints at runtime so I don't have to restart the application?
I has a same problem. My solution was remove previous controller from apm.ApplicationParts
var parts = _partManager.ApplicationParts.Where((x) => ((AssemblyPart)x).Assembly.GetName().Name == compiledAssembly.GetName().Name).ToList();
foreach(var part in parts)
{
apm.ApplicationParts.Remove(part);
}
apm.AddApplicationPart(compiledAssembly);
this work in asp.net core 5.0

how to use GetConnectedClientsAsync from MQTTnet.Server in asp.net core

I can host mqtt broker with MQTTnet nuget in asp.net core 2.2 by following code. I just want to show list of connected cliend in my controller and I found that GetConnectedClientsAsync method can be used. But I don't know how to use in core 2.2. Any suggestion.
In ConfigureServices
var mqttServerOption = new MqttServerOptionsBuilder()
.WithDefaultEndpointPort(6261)
.WithConnectionValidator(Mqtt.connectionValidator.validator)
.Build();
services.AddHostedMqttServer(mqttServerOption)
.AddMqttConnectionHandler()
.AddConnections()
.AddMqttTcpServerAdapter();
In Configure
app.UseMqttEndpoint();
finally found the solution.
just added controller constructor
private readonly MQTTnet.AspNetCore.MqttHostedServer mqttHostedServer;
public testController(MQTTnet.AspNetCore.MqttHostedServer mqttHostedServer)
{
this.mqttHostedServer = mqttHostedServer;
}
and I can use it now.
var clients = await mqttHostedServer.GetClientStatusAsync();

Autofac PerRequest WebApi 2 + Owin

Trying to implement autofac with my WebApi ... but having some issues with lifetime for my objects...
My startup webapi class:
var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).InstancePerRequest();
container.RegisterType<MyConcreteClass>().As<IMyInterface>().InstancePerRequest();
var container = builder.Build();
app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(config);
var csl = new AutofacServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => csl);
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
But not works
Unable to resolve the type 'IMyInterface' because the lifetime scope it belongs in can't be located. The following services are exposed by this registration:
- IMyInterface
Details ---> No scope with a tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested.
If you see this during execution of a web application, it generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario). Under the web integration always request dependencies from the dependency resolver or the request lifetime scope, never from the container itself. (See inner exception for details.)
Removing this part .InstancePerRequest(); , then works, but the object is not disposing.
What am i doing wrong ?
Thanks!
I strongly suspect the problem lies with the following code:
var csl = new AutofacServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => csl);
The error message indicates you must resolve dependencies using the dependency resolver, but this is bypassing that and using the container itself.
On a side note, using a service locator is anti-pattern. You should be injecting dependencies into your controllers and other MVC extension points rather than using this approach.

Autofac v3, Web Api and the Authorize attribute

I have a project with both Mvc Controllers and Web Api controllers.
Everything is wired up using autofac 3 :
var builder = new ContainerBuilder();
builder.Register(x => NHibernateConfigurator.BuildSessionFactory()).SingleInstance();
builder.Register(x => x.Resolve<ISessionFactory>().OpenSession()).InstancePerHttpRequest();
builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource());
builder.Register(x => new WebApiTransactionAttribute()).PropertiesAutowired();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterType<ExtensibleActionInvoker>().As<IActionInvoker>();
builder.RegisterWebApiFilterProvider(config);
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
The problem is that when I add the [Authorize] attribute (the one from System.Web.Http) I get :
Cannot choose between multiple constructors with equal length 1 on type 'System.String'.
Select the constructor explicitly, with the UsingConstructor() configuration method, when the component is registered.
Can someone point me in the right direction ?
Thanks.
Apologies, this is somewhat of a guess but the AnyConcreteTypeNotAlreadyRegisteredSource here looks like it may be too broad a registration:
Provides registrations on-the-fly for any concrete type not already registered with the container.
The Autofac Filter Provider could then be registering all kinds of framework concrete types and getting in a muddle.
It may be if you take this out and put in more targeted registrations it will help, perhaps register by convention instead.

Autofac WCF integration + sessions

I am having an ASP.NET MVC 3 application that collaborates with a WCF service, which is hosted using Autofac host factory. Here are some code samples:
.svc file:
<%# ServiceHost
Language="C#"
Debug="true"
Service="MyNamespace.IMyContract, MyAssembly"
Factory="Autofac.Integration.Wcf.AutofacServiceHostFactory, Autofac.Integration.Wcf" %>
Global.asax of the WCF service project:
protected void Application_Start(object sender, EventArgs e)
{
ContainerBuilder builder = new ContainerBuilder();
//Here I perform all registrations, including implementation of IMyContract
AutofacServiceHostFactory.Container = builder.Build();
}
Client proxy class constructor (MVC side):
ContainerBuilder builder = new ContainerBuilder();
builder.Register(c => new ChannelFactory<IMyContract>(
new BasicHttpBinding(),
new EndpointAddress(Settings.Default.Url_MyService)))
.SingleInstance();
builder.Register(c => c.Resolve<ChannelFactory<IMyContract>>().CreateChannel())
.UseWcfSafeRelease();
_container = builder.Build();
This works fine until I want WCF service to allow or require sessions ([ServiceContract(SessionMode = SessionMode.Allowed)], or [ServiceContract(SessionMode = SessionMode.Required)]) and to share one session with the MVC side. I changed the binding to WSHttpBinding on the MVC side, but I am having different exceptions depending on how I tune it.
I also tried changing AutofacServiceHostFactory to AutofacWebServiceHostFactory, with no result.
I am not using config file as I am mainly experimenting, not developing real-life application, but I need to study the case. But if you think I can achieve what I need only with config files, then OK, I'll use them.
I will provide exception details for each combination of settings if required, I'm omitting them not to make the post too large. Any ideas on what I can do?