ComponentResolutionException after upgrading to Castle 3.0 - c#

I've just upgraded a solution from .NET 3.5 to .NET 4
In the same time, I've upgraded all external libraries to the latest version, so Castle is now upgraded from 2.5.2 to v3.0
I've some code that register db access that throw now an Exception when I try to resolve:
[Castle.MicroKernel.ComponentResolutionException] {"Could not obtain
scope for component DF.MailFlowAdapter. This is most likely either a
bug in custom IScopeAccessor or you're trying to access scoped
component outside of the scope (like a per-web-request component
outside of web request
etc)"} Castle.MicroKernel.ComponentResolutionException
The component is registered this way:
Container
.AddFacility<WcfFacility>()
.AddFacility<DataAccessAdapterFacility>()
.Register(Component
.For<SD.LLBLGen.Pro.ORMSupportClasses.IDataAccessAdapter>()
.ImplementedBy<MailFlowAdapter>()
.LifeStyle.PerWcfOperation())
The problem comes from the PerWcfOperation LifeStyle, but I don't know why: The project is a WCF project and the component is resolved when calling a WCF method.
This registration is working fine in the branch that use Castle 2.5.
The exception is thrown when Validating the wcf login/pwd (in a IAuthorizationPolicy that use a UserNamePasswordValidator), because I resolve an IDataAccessAdapter (to check login/pwd in the db).
Other piece of information:
The DataAccessAdapterFacility is an old code that register a component activator, I had to slightly change de code because model.Service changed to model.Services:
void Kernel_ComponentModelCreated(ComponentModel model)
{
foreach (var service in model.Services)
{
if (service == typeof(SD.LLBLGen.Pro.ORMSupportClasses.IDataAccessAdapter))
{
model.CustomComponentActivator = typeof(DataAccessAdapterActivator);
}
}
}
And the DataAccessAdapterActivator has in charge to create the object using a connection string in the config file:
protected override object InternalCreate(CreationContext context)
{
var connectionString = string.Empty;
if (ConfigurationManager.ConnectionStrings["Main"] != null)
connectionString = ConfigurationManager.ConnectionStrings["Main"].ConnectionString;
return new MailFlowAdapter(connectionString);
}
I think the code with DataAccessAdapterFacility/DataAccessAdapterActivator could be simplify using Factory but it's not the question here :)
So does someone have an idea on why I can't use PerWcfOperation lifestyle ?

I don't believe an OperationContext.Current is available at the point where a custom UserNamePasswordValidator is called. Is it possible to use another lifestyle for that component?

Ok Let's resume my discussion with Craig Neuwirt on the castle mailing list:
The behaviour has changed, in v2.5 is was falling back on a
transient lifestyle. But as it was not consistent (No info on when
the component was PerWcfOperation and when it was Transient) this has
been removed.
It's possible to do the same using a custom lifestyle scope accessor
I'll not post my code here as it's trivial once you've read how the Hybrid lifestyle are done in the castlecontrib project

Related

Replacement for TraceFilter in Azure.WebJobs 3.0+

I am upgrading from Microsoft.Azure.WebJobs 2.0.0 to 3.0.30. In our existing code, we have some custom code that uses the TraceFilter from the older SDK, which is no longer present.
Is there a way to port the following code relying on JobHostConfiguration and TraceFilter to the newer SDK?
In Program.Main():
// config was a JobHostConfiguration, which is not present in the newer SDK
config.Tracing.Tracers.Add(new TraceMonitor()
.Filter(e => (e.Exception is FunctionInvocationException fie ? fie.InnerException : e.Exception)?.IsMonitored() ?? false, "Exception Handler")
.Subscribe(Process));
public void Process(TraceFilter filter)
{
var events = filter.GetEvents().Where(e => e.Exception != null);
foreach (var traceEvent in events) {
...
}
}
In Azure SDK 2.0 an instance of JobHostConfiguration is used to configure settings Like, Tracing and Timer Methods and then this configuration object is passed as a parameter in JobHost instance, JobHost is a runtime container to execute continuously and triggered WebJobs by calling RunAndBlock method of JobHost instance.
In SDK 3.0, JobHostConfiguration has been removed and in place of it, all configurations are configured by HostBuilder.
The Host Builder is much like the latest ASP.Net Core. Firstly you need to create an instance of HostBuilder and configure it as ‘Development’ environment and then configure WebJobs by calling ConfigureWebJobs method.
In this method setup AddAzureStorageCoreServices (it will hook WebJobs to Azure storage Account) and AddTimers ( will let WebJobs to periodically trigger tasks defined in the project).

Override Lifetime in ASP.NET Core Dependency Injection

I've registered an Entity Framework DBContext using standard code like this:
public void ConfigureServices(IServiceCollection services)
{
[...]
services.AddDbContext<MyDbContextType>(ServiceLifetime.Scoped);
}
And this works just great for services called from controllers that require EF services.
However I have a couple of controllers that are special. They start jobs on new threads that run past the lifetime of the web request. When these jobs use my DbContext (or use services that use my DbContext) an error is thrown because the scoped instance has already been disposed.
Is there a way to override the service lifetime of my injected DbContext just for certain controllers? Or is there another solution you could suggest?
You should not override this behavior. Instead, the code you run on a background thread should run in its own scope. This means that the first thing that the background thread does is create a new IServiceScope using the IServiceScopeFactory. From this scope you resolve the service you wish to use and you call that service. At the end of the operation you dispose your scope.
For instance:
private IServiceScopeFactory factory;
new Thread(() =>
{
using (var scope = this.factory.CreateScope())
{
// Resolve
var service = scope.ServiceProvider.GetRequiredService<IService>();
// Use
service.DoStuff();
// Dispose scope
}
}).Start();
For more information on working with DI in multi-threaded applications, take a look at this documentation. Although the documentation is written for a specific DI Container, it is generic in nature and the advice applies to your DI Container as well.

Eager Loading Faulting WCF with Entity Framework 6

I have a WCF service project that is faulting when I am trying to eager load entities. (.Include).
My setup is like this:
WCF Service Library Project
Class Library Project -- Edmx is housed there
Class Library Project -- View Models housed there
WPF Project
I have spent some time trying to fix this serialization issue when I am eager loading entities.
Here is where I am now. The below works:
[OperationContract]
[FaultContract(typeof(HandleException))]
[ApplyProxyDataContractResolver]
List<Item> GetItems();
using (var dbContext = new MyEntities())
{
dbContext.Configuration.LazyLoadingEnabled = false;
return dbContext.Items.ToList();
}
And displays this:
But this faults and gives the generic error message
Failed to invoke the service. Possible causes: The service is offline or inaccessible; the client-side configuration does not match the proxy; the existing proxy is invalid. Refer to the stack trace for more detail. You can try to recover by starting a new proxy, restoring to default configuration, or refreshing the service.
This is what is throwing the exception
return dbContext.Items.Include(x => x.Category).ToList();
I have tried changing the return type to Item and then something like this
return dbContext.Items.Include(x => x.Category).FirstOrDefault(t => t.Category.CategoryId == t.CategoryId);
And I have added [CyclicReferencesAware(true)] but the test client is still bombing out.
Categories are a self referencing hierarchy -- I think that is why it can't handle it.
How can I resolve this?
Thanks.
WcfTestClient.exe can't handle cyclic references - have you tried testing with your own custom code?

Dependency Injection and project structure for Console applications

I have 4 projects:
Core (IServer):
System
System.Core
DependencyResolver:
Core
StructureMap
Infrastructure (Service):
Core
External dependency
Console:
Core
DependencyResolver
Requierements:
I am trying to use StructureMap only in the DependencyResolver.
Furthermore the Console application should not know anything about Infrastucture.
When I do not want to reference StructureMap on my Console Application I have to build a ServiceLocator.
In the DependencyResolver I have a Bootstrapper that is responsible for calling StructureMap registry stuff (Register)
In my Console application I want to get an instance. For this I need to reference StructureMap. Another way would be to write a little wrapper around StructureMaps resolving methods.
Is there any other better way of decoupling the console from StructureMap?
While I see a reason for separating IoC register,resolve,release from the implementation of the application, I don't see any reason why the IoC container shouldn't be in the console application (the composition root) and the application implemention in another assembly instead.
That way the console application is very easy:
Create the container
Load the container configuration
Resolve the Application
Call run on the application and pass the console arguments along
dispose the container when the application exits the run method
With SM it look about like this:
public void Main(params string[] args)
{
using (var container = new Container())
{
container.LoadAllConfigurationModules();
container.AddRegistry<SomeRegistry>();
container.GetInstance<Application>().Run(args);
}
}
For things you can't create at startup you create a factory interface in your application assembly:
interface ISomeFactory { ISomeDependency CreateSomeDependency() }
and implement this interface in the console application by injecting the container and use it to resolve the instance. I guess the SM implementation looks like this:
public class SomeFactory : ISomeFactory
{
public SomeFactory(IContainer sontainer) { this.container = container; }
ISomeDependency CreateSomeDependency() { this.container.GetInstance<ISomeDependency>(); }
}
Other IoC container even have the functionallity to implement these interface factories automatically.

XML namespace problem in Visual Studio generated service reference

I'm connecting to a web service hosted by a third-party provider. I've added a service reference in my project to the web service, VS has generated all the references and classes needed.
I'm connecting with this piece of code (client name and methods anonymized):
using (var client = new Client())
{
try
{
client.Open();
var response = client.Method(...);
return response.Status;
}
catch (SoapException ex)
{
throw CreateServiceException(ex);
}
finally
{
client.Close();
}
}
When reaching the client.Open(), I get an exception with this message:
The top XML element '_return' from
namespace '' references distinct types
System.Boolean and
Service.Status.
Use XML attributes to specify another
XML name or namespace for the element
or types.
In reference.cs, I can see that the "_return" variable is decorated with
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="", Order=0)]
Is there a problem with the wsdl, the generated service reference or in my code?
Update: Generating the service as an old school Web Service solves the problem. I've marked Sixto's answer as accepted for now, but I'm still curious what could've caused the problem and if any parameters to the service generator could solve the original problem.
If you were able to create a service reference then the WSDL is valid. The exception message is saying you have namespace/type ambiguity problem with _return. The generated code is probably using it in some context as a boolean and in another context as a Service.Status type.
I don’t call the ClientBase.Open method before invoking a service method because I’ve never seen the need for it. I do always call the Close & Abort methods as appropriate. The Open method basically just changes the state of the client to no longer be configurable. I’m not sure how that would trigger code in the generated class since it is an inherited method. I’d try just removing that line and see if you get the same exception. Otherwise, if you haven’t already done so, search the generated code for all the places _return is used and see if you can manually sort-out the appropriate type. You may need different names for each context.
Another way to troubleshoot the WSDL is to create a Web Reference (assuming it’s an HTTP based service) and see if the generate code works as expected. If it does work, go with the ASMX client unless you have a need for WCF proxy capabilities.

Categories

Resources