ContextRegistry rootContextName is always null or empty - c#

Using Spring.NET IoC to inject dependency objects into properties. The app is an Outlook plug-in.
The code:
IApplicationContext ctx = ContextRegistry.GetContext();
this.Property = (MyObject)ctx.GetObject("MyObject");
The Config:
<configuration>
<configSections>
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
</sectionGroup>
</configSections>
<spring>
<context>
<resource uri="config://spring/objects"/>
</context>
<objects xmlns="http://www.springframework.net">
<description></description>
<!--Business Logic Layer Binding Objects-->
<object name="MyObject"
type="Quadrant2.MSCRM.Recruit.OfficeAddins.Toolbar.BusinessLogic.Q2_Win_SearchClient_Logic, Quadrant2.MSCRM.Recruit.OfficeAddins.Toolbar.BusinessLogic">
<property name="SearchClientDAL" ref="DAL_SearchClient"/>
</object>
<!-- snip -->
This code was running fine for around 2 years and then we upgraded a few assemblies around Outlook to run in Outlook 2010 and some Ribbon modifications - nothing that should affect Spring.NET I think.
Started getting the "The context name passed to the GetContext method cannot be null or empty" exception thrown on the GetContext(); call. On closer inspection I noted that the rootContextName is null - fair call, explains the exception I thought.
Also noted that the code would run fine during debug but fail once it runs outside debug. Checked dll's, dependencies and configs are all in the right place during install.
"Force fed" GetContext(); a context name, "spring.root" as per debug session rootContextName value, and the exception goes away but IApplicationContext is returned null.
Any ideas or obvious issues here?

Related

Web.Config custom section returns null

Well I have following entries in my web config for SagePay Integration in an ASP.net MVC project.
<configuration>
<configSections>
<section name="SagePayConfiguration" type="System.Configuration.IgnoreSectionHandler" requirePermission="true" restartOnExternalChanges="true" allowLocation="true"/>
</configSections>
<SagePayConfiguration>
<!--Mandatory
Set to TEST for the Test Server and LIVE for the live environment-->
<add key="sagepay.api.env" value="TEST" />
.
.
</SagePayConfiguration>
However I am getting null when trying to access it from C# code.
SagePayConfiguration sagePayConfiguration = (SagePayConfiguration)System.Configuration.ConfigurationManager.GetSection("SagePayConfiguration");
Any help what I am missing here?
You must cast the ConfigrationItem to "System.Configuration.IgnoreSectionHandler" or set the type Attribute in web.conf to an existing Type in your assembly.
<section name="<SectionName>" type="<your type (FQN)>, <Assembly>" />
After that you can access it
YourType o = ((YourType)ConfigurationManager.GetSection("sectionName"));
EDIT:
The Type must derive from ConfigurationSection.

using multiple app.config files

I have a console application that loads other libraries (DLL's). I'm using Spring.NET. My console application is very simple, load the app.config that is configured through DI to initialize the chosen library.
Code
ContextRegistry.GetContext();
Configuration (app.config)
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="spring">
<section name="context"
type="Spring.Context.Support.ContextHandler, Spring.Core"/>
<section name="objects"
type="Spring.Context.Support.DefaultSectionHandler, Spring.Core"/>
</sectionGroup>
</configSections>
<spring>
<context>
<resource uri="config://spring/objects"/>
<resource uri="assembly://MyDLL/MyDLL.Config/Services.xml"/>
</context>
<objects xmlns="http://www.springframework.net"
xmlns:aop="http://www.springframework.net/aop">
</objects>
</spring>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup></configuration>
Each library has its own "services.xml" file. These libraries also use Spring.NET.
<objects xmlns="http://www.springframework.net"
xmlns:aop="http://www.springframework.net/aop">
<object id="componentObj"
type="MyDLL.Services.ComponentService, MyDLL"
singleton="true" />
<object
id="componentServiceHost"
type="Spring.ServiceModel.Activation.ServiceHostFactoryObject, Spring.Services">
<property name="TargetName"
value="componentObj" />
</object>
</objects>
Getting a excpetion "Process is terminated due to StackOverflowException." If I comment out the <object id="componentServiceHost", the exception does not occur.
The VS console in debug shows
A first chance exception of type 'System.InvalidOperationException' occurred in System.ServiceModel.dll
A first chance exception of type 'Spring.Objects.Factory.ObjectCreationException' occurred in Spring.Core.dll
A first chance exception of type 'Spring.Objects.Factory.ObjectCreationException' occurred in Spring.Core.dll
Managed (v4.0.30319)' has exited with code -2147023895 (0x800703e9).
You can also place spring configuration in plain xml files and include those with your library. This way, you can easily share this configuration without the need of sharing an app.config.
You do have to explicitly reference this configuration file in the configuration of your host console application, but that's no duplication. The app.config of your console application host will look like this:
...
<spring>
<context>
<resource uri="file://services.xml"/>
<resource uri="assembly://MyAssembly/MyDataAccess/data-access.xml"/>
</context>
</spring>
See the spring.net docs how to configure a configuration in xml.

StructureMap, different implementation for different user

We are currently using StructureMap as the IoC container. All was working ok, but now we need to change the defaults in runtime.
What we need is ability to provide IEntityRepository, IEntityService based on a user. Having EntityRepositoryEur, EntityRepositoryRus...
Is there some way how to chnage Instances in runtime based on user setting? What is the best way to do that? Maybe is there some better IoC right now to do that?
I am not familiar with StructureMap but with Unity Application Block (called usually just Unity) you can register more concrete types (services) with single interface. You assign names to these services and at the time of resolution you receive the list of registered services. Then you can choose one based on the user settings.
This is example how to register named services using config file
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
</configSections>
<unity>
<containers>
<container>
<types>
<type name="OutputService1" type="InterfacesLibrary.IOutputService, InterfacesLibrary" mapTo="InputOutputLibrary.ConsoleOutputService, InputOutputLibrary" />
<type name="OutputService2" type="InterfacesLibrary.IOutputService, InterfacesLibrary" mapTo="InputOutputLibrary.MsgBoxOutputService, InputOutputLibrary" />
</types>
</container>
</containers>
</unity>
</configuration>
Or you can do the same thing from code
container.RegisterType<IOutputService, ConsoleOutputService>("OutputService1");
container.RegisterType<IOutputService, MsgBoxOutputService>("OutputService2");
At the time of resolution you resolve one or the other type based on user's requirements
IOutputService outputService;
if (user.LikesConsole == true)
outputService = container.Resolve<IOutputService>("OutputService1");
else
outputService = container.Resolve<IOutputService>("OutputService2");
Have a look at the series of videos on PRISM. The second video is introduction to Unity.

Strange exception coming out of OdbcConnection.Open()

Bashing our heads against the wall here
We are an ISV and have hundreds of companies using our software with no problems. The software is Winforms/C# on .NET 2.0.
One of our clients has installed our software and it crashes on startup on all of their machines, apart from on one guy's laptop where it works fine.
On calling OdbcConnection.Open(), we get the following exception:
The type initializer for 'System.Transactions.Diagnostics.DiagnosticTrace' threw an exception.
at System.Transactions.Diagnostics.DiagnosticTrace.get_Verbose()
at System.Transactions.Transaction.get_Current()
at System.Data.Common.ADP.IsSysTxEqualSysEsTransaction()
at System.Data.Common.ADP.NeedManualEnlistment()
at System.Data.Odbc.OdbcConnection.Open()
at OurCompany.OurForm.connectionTestWorker_DoWork(Object sender)
This has an InnerException:
Configuration system failed to initialize
at System.Configuration.ClientConfigurationSystem.EnsureInit(String configKey)
at System.Configuration.ClientConfigurationSystem.PrepareClientConfigSystem(String sectionName)
at System.Configuration.ClientConfigurationSystem.System.Configuration.Internal.IInternalConfigSystem.GetSection(String sectionName)
at System.Configuration.ConfigurationManager.GetSection(String sectionName)
at System.Configuration.PrivilegedConfigurationManager.GetSection(String sectionName)
at System.Diagnostics.DiagnosticsConfiguration.GetConfigSection()
Google just says "app.config is syntactically incorrect, rebuild it" yet the same app.config works fine on hundreds of other machines.
Here's app.config, as requested:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="OurApp.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<system.diagnostics>
</system.diagnostics>
<applicationSettings>
<OurApp.Properties.Settings>
<setting name="OurApp_WebServices_OurServiceName" serializeAs="String">
<value>http://ourdomain.com/OurService.asmx</value>
</setting>
</OurApp.Properties.Settings>
</applicationSettings>
<appSettings>
<add key="WorkflowEngine" value="old" />
<add key="ProductID" value="3" />
<add key="EnableMigrationWizard" value="false" />
<add key="UseAlternativeFtpPort" value="true" />
<add key="FeedbackWhileConnecting" value="true" />
</appSettings>
</configuration>
A repair of the .NET Framework hasn't fixed this. I'm at a total loss. Any ideas?
Check machine.config and user.config. Along with app.config, those are the 3 that make up the config sections.
Reflector shows EnsureInit has 2 exception paths:
catch (Exception exception) {
this._initError = new ConfigurationErrorsException(SR.GetString("Config_client_config_init_error"), exception);
throw this._initError;
} catch {
this._initError = new ConfigurationErrorsException(SR.GetString("Config_client_config_init_error"));
throw this._initError;
}
Since the 2nd would only handle a non-CLS exception, I'd guess that you're hitting the first one. If that's the case, you probably need to recursively go through InnerException to get the full details.
Just for anyone's future reference, I had this problem with a local app that I was developing on my desktop and found that the problem was simply that I had the case wrong in . Once that was fixed it worked like a charm again.
Solved this by overwriting machine.config with a known working copy from another machine at the same SP/patch level.
I had this exact same error occur when trying to open an OLE DB connection with ASP/VB.NET 3.5 SP1. If I add my URL to the list of trusted sites in IE, then the error goes away and the connection opens successfully. I don't know if this will fix things in other browsers.

Unity Configuration and Same Assembly

I'm currently getting an error trying to resolve my IDataAccess class.
The value of the property 'type' cannot be parsed. The error is: Could not load file or assembly 'TestProject' or one of its dependencies. The system cannot find the file specified.
(C:\Source\TestIoC\src\TestIoC\TestProject\bin\Debug\TestProject.vshost.exe.config line 14)
This is inside a WPF Application project.
What is the correct syntax to refer to the Assembly you are currently in? is there a way to do this? I know in a larger solution I would be pulling Types from seperate assemblies so this might not be an issue. But what is the right way to do this for a small self-contained test project. Note: I'm only interested in doing the XML config at this time, not the C# (in code) config.
UPDATE: see all comments
My XML config:
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
</configSections>
<unity>
<typeAliases>
<!-- Lifetime manager types -->
<typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity" />
<typeAlias alias="external" type="Microsoft.Practices.Unity.ExternallyControlledLifetimeManager, Microsoft.Practices.Unity" />
<typeAlias alias="IDataAccess" type="TestProject.IDataAccess, TestProject" />
<typeAlias alias="DataAccess" type="TestProject.DataAccess, TestProject" />
</typeAliases>
<containers>
<container name="Services">
<types>
<type type="IDataAccess" mapTo="DataAccess" />
</types>
</container>
</containers>
</unity>
</configuration>
In unity 5.7
The section line should be like this
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Unity.Configuration" />
This looks fine. Are you sure your assembly name is correct? Check the project preferences to make sure the name of your assembly is correct:
Right click your project and click Properties
Click on the Application tab on the left
Look at the value of the "Assembly Name" field.
Sometimes if you've renamed your project, this field will still be the old value.
It's possible that this is not the issue at all, but it is the simplest thing to check. If you find that this is not the issue, reply to this and I'll post any other ideas I have.
Also, you might consider posting your sample as a .zip file so we can take a look at it.
I just had the same issue. this works for me :
Turn "Copy local" to true in the properties of Microsoft.Practices.Unity.
You should also add a reference to Microsoft.Practices.ObjectBuilder2 (Microsoft.Practices.Unity depends of it)

Categories