I'm new to StuctureMap and I am writing a WCF service. In the existing code the previous developer used SturctureMap.
I get this error:
StructureMap Exception Code: 202
No Default Instance defined for PluginFamily MyCompany.SMS.Data.DataEntitys, MyCompany.SMS.Data, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Here is the Code:
class a
{ method aa
{
var db = ObjectFactory.GetInstance<nsclaimsEntities>();
}
}
When we are calling this code from an aspx.cs file it is working fine without any error, but I tried to wrap this code in a WCF webservice and it is throwing this exception.
Here is the stack trace:
at StructureMap.BuildSession.<.ctor>b__0(Type t)
at StructureMap.Util.Cache`2.get_Item(KEY key)
at StructureMap.BuildSession.CreateInstance(Type pluginType)
at StructureMap.Container.GetInstance(Type pluginType)
at StructureMap.Container.GetInstance[T]()
at StructureMap.ObjectFactory.GetInstance[PLUGINTYPE]()
at NicorNational.SMS.CustDemographic.GetByAccountNumber(String acctNum) in C:\\Projects\\NicorNational.SMS\\CustDemographic.cs:line 105
at NicorNational.Services.eCommerce.EligibilityService.GetEligibilityById(String accountId) in C:\\Projects\\Solutions\\NicorNational.Services.eCommerce\\EligibiltyService.svc.cs:line 23
at SyncInvokeGetEligibilityById(Object , Object[] , Object[] )
at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)"
Why do I get this exception?
As you've already found out, the problem migrating straight from a web application to a WCF service is where to place the bootstrapping code.
I just wanted to point out that you should move away from the service location behaviour and introduce dependency injection instead to have loose coupling and make your service easier to maintain/change.
Jimmy Bogard has written an excellent blog entry on how to bootstrap a WCF service using Structure Map. He uses a custom ServiceHostFactory instead of a static constructor to bootstrap the registry.
Related
We're using ASP.NET core and are running into the problem, that some registered services (from third-party libraries) request a specific 'service' (based on an interface) that has been deprecated.
The problem is that we don't know which libraries are using this deprecated service interface.
What we've done so far is:
create a custom implementation for the service interface
and registered this custom implementation (class) with DI
// Registration
services.AddTransient<IServiceInterface>((services) => new CustomCustomService(Log.Logger));
// Custom implementation
internal class CustomService : IServiceInterface
{
public CustomService (ILogger logger)
{
logger.Warning("!!! CustomService is still being used !!!");
}
}
So now we can see that the unwanted service is being used 'somewhere'.
But is it in some way possible to detect for which service the deprecated service has been created?
I've tried listing the stack trace using
var st = new System.Diagnostics.StackTrace();
logger.Warning("!!! CustomService is still being used !!!" + Environment.NewLine + "{stacktrace}", st.ToString());
But that doesn't seem to give information about the service using the deprecated service...
You can try the following:
var registrationsDependingOnMyService =
from descriptor in services
where descriptor.ImplementationType != null
let dependencies =
from ctor in descriptor.ImplementationType!.GetConstructors()
from param in ctor.GetParameters()
select param.ParameterType
where dependencies.Contains(typeof(IServiceInterface))
select descriptor;
This will query the IServiceCollection for registrations whose implementation type have a constructor argument of type IServiceInterface.
This might not be a bulletproof solution, as types or registrations can more sneakily depend on the service collection (e.g. by calling back into the IServiceProvider from within a registration delegate), but this is likely the best you can do with MS.DI.
So basically - as expected - it's not possible to exactly know which libraries (for which you don't have the code) use a certain dependency.
It's just trial and error ;)
Thanks for the ideas everyone.
I'm using Patterns and Practices' Unity to inject dependencies into my objects and have hit a weird (to me, anyway) issue. Here's my class definitions:
public class ImageManager : IImageManager
{
IImageFileManager fileManager;
public ImageManager(IImageFileManager fileMgr)
{
this.fileManager = fileMgr;
}
}
public class ImageFileManager : IImageFileManager
{
public ImageFileManager(string folder)
{
FileFolder = folder;
}
}
And here's the code to register my classes
container.RegisterInstance<MainWindowViewModel>(new MainWindowViewModel())
.RegisterType<IPieceImageManager, PieceImageManager>(
new InjectionConstructor(typeof(string)))
.RegisterType<IImageFileManager, ImageFileManager>()
.RegisterType<IImageManager, ImageManager>(
new InjectionConstructor(typeof(IImageFileManager)));
I originally resolved this in the code behind (I know, it defeats the purpose. Bear with me.) of the XAML file like this
IImageManager imageManager = MvvmViewModelLocator.Container.Resolve<IImageManager>(
new ParameterOverride("folder", "/images"));
And it worked. But I created a view model for my main view and when I copied the same line into it, I get an exception. Here are the two most inner exceptions:
InnerException: Microsoft.Practices.Unity.ResolutionFailedException
HResult=-2146233088
Message=Resolution of the dependency failed, type = "SwapPuzzleApp.Model.IImageManager", name = "(none)".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The type IImageManager does not have an accessible constructor.
At the time of the exception, the container was:
Resolving SwapPuzzleApp.Model.IImageManager,(none)
Source=Microsoft.Practices.Unity
TypeRequested=IImageManager
StackTrace:
at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides)
at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, String name, IEnumerable`1 resolverOverrides)
at Microsoft.Practices.Unity.UnityContainer.Resolve(Type t, String name, ResolverOverride[] resolverOverrides)
at Microsoft.Practices.Unity.UnityContainerExtensions.Resolve[T](IUnityContainer container, ResolverOverride[] overrides)
at SwapPuzzleApp.ViewModel.MainWindowViewModel..ctor() in c:\Users\Carole\Documents\Visual Studio 2012\Projects\SwapPuzzle\SwapPuzzle\ViewModel\MainWindowViewModel.cs:line 17
at SwapPuzzleApp.ViewModel.MvvmViewModelLocator..cctor() in c:\Users\Carole\Documents\Visual Studio 2012\Projects\SwapPuzzle\SwapPuzzle\ViewModel\MvvmViewModelLocator.cs:line 51
InnerException: System.InvalidOperationException
HResult=-2146233079
Message=The type IImageManager does not have an accessible constructor.
Source=Microsoft.Practices.Unity
StackTrace:
StackTrace:
at Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.ThrowForNullExistingObject(IBuilderContext context)
at lambda_method(Closure , IBuilderContext )
at Microsoft.Practices.ObjectBuilder2.DynamicBuildPlanGenerationContext.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides)
InnerException:
I'm not sure what the problem is, as ImageManager clearly has a public constructor. I thought it might be due to an invalid path, but if I concretely instantiate the object, everything works.
// this line has no problems
IImageManager imageManager = new ImageManager(new ImageFileManager("/images"));
I also wondered if I needed to pass in new InjectionConstructor(typeof(string)) when I register IImageManager, but it doesn't seem to help and why would it be needed now and not before? So I'm stumped. This is my first attempt at using Dependency Injection, so it's probably something basic. I'm just not seeing what, though.
Look very closely at the error message. Notice this part:
Message=The type IImageManager does not have an accessible constructor.
Notice the type name is IImageManager, not ImageManager. Somewhere along the line you lost your type mapping.
Your registration of FileImageManager has a problem as well, since you don't specify the folder parameter in the registration, so Unity has no idea what string to pass.
I was using the examples in this article as my guide. Either the examples in there are way too advanced for an introduction, or there's misinformation in that topic.
After consulting other sources (mainly PluarlSight), I came up with a much simpler and more logical solution.
container.RegisterInstance<TimerViewModel>(new TimerViewModel());
container.RegisterType<IPieceImageManager, PieceImageManager>();
container.RegisterType<IImageFileManager, ImageFileManager>
(new InjectionConstructor("/images"));
container.RegisterType<IImageManager, ImageManager>();
I ran into a similar issue with this error tied directly to a Mock (using automoq) that I was doing for an operation. In this case it turned out that because there were a number of member methods that get called with the object being mocked, that I had to define all of those in the automoq chain to get it to resolve properly
I realize this is an example in instance code, but it could occur in Moqs also. So if you read this and are wondering about an example related to Moqs, look into that first.
I'm having problems resolving a repository when calling it from a console app. Everything works fine when running the application (.NET 4, C#, Entity Framework, Unity) as normal, but I've created a standalone console app that will be run from the task scheduler to import feeds. I'm very close to giving up and do a dirty hack and write a script to call a webpage instead of using a console app, but I thought I'd at least try to understand why it isn't working first.
I'm new to both Entity Framework and Unity, so please bear with me and let me know if I've left out any important information.
This is the error I'm getting:
Resolution of the dependency failed, type = "MyNamespace.Domain.Template.IRepository`2[MyNamespace.Domain.Employees.OrganisationalUnit,System.Guid]", name = "(none)".
Exception occurred while: while resolving.
Exception is: NullReferenceException - Object reference not set to an instance of an object.
at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides)
at Microsoft.Practices.Unity.UnityContainer.Resolve(Type t, String name, ResolverOverride[] resolverOverrides)
at Microsoft.Practices.Unity.UnityContainerExtensions.Resolve[T](IUnityContainer container, ResolverOverride[] overrides)
at MyNamespace.Infrastructure.FeedDefinition.GetOrganisationalUnit(String name, OrganisationalUnit parent) in C:\FeedDefinition.cs:line 552
This is the console app code:
static void Main(string[] args)
{
if (args.Length > 0)
{
MyNamespace.Appliance.Configuration.Initialise.InitialiseContainer();
ImportFeedProcessor importFeedProcessor = new ImportFeedProcessor();
importFeedProcessor.Run(args[0]);
}
}
And this is where it fails:
IRepository<OrganisationalUnit, Guid> organisationalUnitRepository =
Context.Instance.Container.Resolve<IRepository<OrganisationalUnit, Guid>>();
If anyone can help me understand what's going wrong I'd be very grateful!
UPDATE:
Here's the (important) bits from the initialise class:
public static void InitialiseContainer()
{
UnityContainer container = new UnityContainer();
// Use HttpContext for registering instances against for live
IContext context = HttpContextWrapper.Instance;
// Register the HttpContext as the default context to use
container.RegisterInstance<IContext>(HttpContextWrapper.Instance);
// repositories
container.RegisterType<IRepository<Employee, Guid>, EmployeeRepository>(
new UnityContextLifetimeManager(context),
new InjectionConstructor(true, "OrganisationalUnit.Parent.Parent"));
container.RegisterType<IRepository<OrganisationalUnit, Guid>, EntityFrameworkRepository<OrganisationalUnit, Guid>>(
new UnityContextLifetimeManager(context),
new InjectionConstructor("Parent.Parent"));
// Create and populate a new Unity container from configuration
Context.Instance.Container = container;
}
Is it perhaps the HttpContext that does it?
Thanks,
Annelie
One option you could consider is creating two different Initialise classes (I'm guessing that is your Unity bootstrapper class).
The one you have can be used for your web application.
The other one should be non-web specific. Remove any reference to HttpContext (it won't be available in a Console app) and UnityContextLifetimeManager (assuming this is HttpContext specific as well).
I'm in the process of learning WCF, and as a practical exercise I've decided to write generic wrapper for the ServiceHost class. The idea is to have a class like the one below :
public class Host<I(nterface), S(ervice)>
where S : I, new()
{
/**/
ServiceHost mServiceHost;
S mServiceInstance = new S();
}
Where the I type is the interface with the [ServiceContract] attribute & the S type is the Service that's implementing the forementioned interface.
I've created an auxiliary hello-world type service in the mean time to test my class on the go.
In the Host's constructor I've instantiated the internal ServiceHost like this :
mServiceHost = new ServiceHost(mServiceInstance);
I've added a service endpoint :
mServiceHost.AddServiceEndPoint(typeof(I), new BasicHttpBinding(), new Uri("http://localhost:40000/MyTestService"));
a bit later I've opened the host, launched my application and attempted to see if my browser will indicate a service present under the "http://localhost:40000/MyTestService" - I got a blank page and all attempts to add a service reference failed.
I've later added the same Uri to the ServiceHost's constructor :
mServiceHost = new ServiceHost(mServiceInstance, new Uri("http://localhost:40000/MyTestService"));
That constructor's 2nd argument is either :
params string[] baseAddresses
or
params Uri[] baseAddresses
In any case, the presence of the "params" keyword tells me that this parameter is OPTIONAL.
I've reacitvated my app, and (using the browser) navigated to the uri. The service page popped up. All in all - it's working but not the way I expected, I seem to be missing something.
Questions :
Why did the service fail when I did not supply the optional baseAddresses parameter in the ServiceHost constructor - while attempting to feed the addresses while adding service endpoints?
Can I achieve my goal "the way I initially wanted it to be" ?
Best regards, and hoping to hear from any WCF experts soon(tm).
Greg Sansom answered your first question.
As for the second it can be done: please get a look at Juval Lowy's ServiceModelEx classes (especially ServiceHost) download here it contains several useful classes for WCF
I'm getting an error:
StructureMap Exception Code: 202
No Default Instance defined for PluginFamily MVCPoco.Services.IService, MVCPoco.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Line 96: {
Line 97: Type controllerType = base.GetControllerType(context, controllerName);
Line 98: return ObjectFactory.GetInstance(controllerType) as IController;
Line 99: }
Line 100: }
the error occurs in line 98
Any ideas?
I'm using asp.net mvc 2 preview 2 that ships with visual studio 2010.
The controller you are trying to instantiate has a constructor dependency on IService. You have to make sure that you register a concrete implementation of IService when you configure StructureMap.
The DefaultConventionScanner will only register implementations that have the same name as their interface (without the leading I). So, unless your implementation of IService is named Service, it will not be registered automatically. To register it explicitly, add something like this to your inititalization script:
x.For<IService>().Use<MyService>();
Alternatively, if you are running StructureMap from the latest source code, you can make use of the SingleImplementationScanner in your Scan() expression:
y.With(new SingleImplementationScanner());
and that will automatically register concrete types if they are the only implementation of an interface in the scanned code, regardless of name.
You must register the types to be injected at application start within the ObjectFactory.Configure function. Check out the documents over on Structure Map's site for Configuring your IOC Container.
Andrew
Well, i've set up correctly the structuremap i've just switched to the method
public static void Configure()
{
ObjectFactory.Initialize(x =>
x.AddRegistry(new IOCRegistry())); // in here i have registered my dependencies with for method.
}