webadvanced / structuremap.mvc5 Goto Github PK
View Code? Open in Web Editor NEWLicense: Apache License 2.0
License: Apache License 2.0
With the release of StructureMap4 it appears that the ControllerConvention registration class requires a minor update.
This is how I have changed it, not sure if this is the best way to go:
public void ScanTypes(TypeSet types, Registry registry)
{
types.AllTypes().ForEach(type =>
{
if (type.CanBeCastTo<Controller>() && !type.IsAbstract)
{
registry.For(type).LifecycleIs(new UniquePerRequestLifecycle());
}
});
}
Just 2 things, and I think the first one is nitpicking.
I am getting this error once in a while and it is automatically fixed by itself. Any ideas?
Value cannot be null.
Parameter name: httpContext
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.ArgumentNullException: Value cannot be null.
Parameter name: httpContext
[ArgumentNullException: Value cannot be null.
Parameter name: httpContext]
System.Web.HttpContextWrapper..ctor(HttpContext httpContext) +11702970
StrategicUnderwriterAig.DependencyResolution.StructureMapDependencyScope.get_HttpContext() in C:\myproject\DependencyResolution\StructureMapDependencyScope.cs:69
StrategicUnderwriterAig.DependencyResolution.StructureMapDependencyScope.get_CurrentNestedContainer() in C:\myproject\DependencyResolution\StructureMapDependencyScope.cs:55
StrategicUnderwriterAig.DependencyResolution.StructureMapDependencyScope.DoGetAllInstances(Type serviceType) in C:\myproject\DependencyResolution\StructureMapDependencyScope.cs:105
System.Web.Http.Services.DefaultServices.GetServices(Type serviceType) +136
Full error detail:
https://jsfiddle.net/L9poaesu/
The IoC class explicitly registers DefaultRegistry rather than calling a scanner to look for all registries. While the DefaultRegistry has a commented out place to put your explicit type registrations (For.Use), this still means that you have to edit DefaultRegistry in order to add classes, or to tell it to look for other registries. This causes a manual merge issue if the StructureMap.MVC package is ever updated.
Instead of explicitly adding just the one registry (DefaultRegistry), if IoC.Initialize scanned the calling assembly looking for other registries then it would pick up on DefaultRegistry, as well as any others that are added to the project. In this way, developers could add their configurations to the mix without having to edit any of the files that came from the package, thus eliminating future merge/overwrite issues. In fact, you can eliminate DefaultRegistry entirely and absorb it back into IoC.Initialize.
Here is my current IoC.Initialize method, for example:
public static IContainer Initialize()
{
return new Container(c => c.Scan(scan =>
{
scan.TheCallingAssembly();
scan.LookForRegistries();
scan.WithDefaultConventions();
scan.With(new ControllerConvention());
}));
}
Hi,
Thanks for this Library.
I have same problem that described in this issue
I belived this problem Related with Structuremap.MVC5 container's lifecycle cache.
I'm looking at SM.MVC5 to ensure I'm following the best practices with nested containers and avoiding anything to do with HttpContext lifecyles.
Would it be safe to remove Structuremap.Web and HttpContextLifecycle.DisposeAndClearAll();?
When I first start debugging a project using IIS Express I get an ArgumentNullException
in StructureMapDependencyScope.HttpContext
, as System.Web.HttpContext.Current
is null.
I'm not sure, but this might be because I'm trying to resolve dependencies in Application_Start
for use in authorisation filters by calling DependencyResolver.Current.GetService<>
- maybe this is too early for the HttpContext
to exist?
In any case, it means that StructureMap is not created HTTP-scoped instances; I can end up with multiple instances of my DbContext
, for example, despite the fact it should be HTTP-scoped.
Hello,
When I added the following on DefaultRegistry:
For<IExample>().HttpContextScoped().Use<Example>();
I get the following error when using container.AssertConfigurationIsValid():
An exception of type 'System.InvalidOperationException' occurred in System.Core.dll but was not handled in user code.
I know that if I remove HttpContextScoped() it works. Why is that?
Thank You
Everything works fine in local dev, however when I deploy to a server (literally changing nothing) I get the parameterless constructor error:
`[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, StackCrawlMark& stackMark) +138
System.Activator.CreateInstance(Type type, Boolean nonPublic) +105
System.Activator.CreateInstance(Type type) +12
System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +73
[InvalidOperationException: An error occurred when trying to create a controller of type 'XXX.XXX.Web.Controllers.HomeController'. Make sure that the controller has a parameterless public constructor.]
System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +240
System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +103
Castle.Proxies.Invocations.IControllerFactory_CreateController.InvokeMethodOnTarget() +154
Castle.DynamicProxy.AbstractInvocation.Proceed() +111
Glimpse.Core.Extensions.AlternateMethodContextExtensions.TryProceedWithTimer(IAlternateMethodContext context, TimerResult& timerResult) +64
Glimpse.Core.Extensibility.AlternateMethod.NewImplementation(IAlternateMethodContext context) +32
Castle.DynamicProxy.AbstractInvocation.Proceed() +448
Castle.Proxies.IControllerFactoryProxy.CreateController(RequestContext requestContext, String controllerName) +270
System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +268
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +95
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +923
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +137`
Running: -
structuremap v3.1.1.134
StrucureMap.MVC5 v3.1.1.134
Structuremap.web v3.1.0.133
Has anyone else got this problem?
In previous version, I have to specify HttpContextScoped. I can still do it in 3.1 but if this is done in a Registry in a library, it has to reference StructureMap.Web, seems defeat the purpose of that separation. Is this no longer necessary because I read something about container per request?
For<IDatabase>().Use(() => new Database("DefaultDb"))
.LifecycleIs<HttpContextLifecycle>();
Another thing, one of the mediator interface (MediatR) I use take input parameter.
public class Mediator : IMediator {
public Mediator(ServiceLocatorProvider serviceLocatorProvider) {
_serviceLocatorProvider = serviceLocatorProvider;
}
If I left everything default, when injected, it will complain no parameter-less constructor. Somehow through trial and error, I manage to get it work by changing the IoC initialize to the following. But I have no idea if it's the right way. Can someone help take a look?
public static IContainer Initialize()
{
Container container = new Container(x => x.AddRegistry<DefaultRegistry>());
container.Configure(cfg => cfg.For<ServiceLocatorProvider>()
.Use(new ServiceLocatorProvider(() => new StructureMapDependencyScope(container))));
return container;
}
Hi there,
I just started upgrading some projects to MVC5 and discovered your Nuget package. It's been a welcome addition to the toolbox.
It has worked without inicident across most of the projects, but then I hit a project where I'm using Html.RenderAction. This causes an exception with this message:
A single instance of controller 'HomeController' cannot be used to handle multiple requests. If a custom controller factory is in use, make sure that it creates a new instance of the controller for each request.
I think that this may have something to do the use of StructureMap's nested containers, but I'm not sure. Have you tried testing this with a [ChildActionOnly] method on the same controller as the page you are calling RenderAction?
Thanks,
Pete
Locally this works as expected using IISExpress however, when deoployed to a Win2k8 R2 server (IIS 7) i'm getting an ArgumentNullException for httpContext in this method
private HttpContextBase HttpContext
{
get
{
var ctx = Container.TryGetInstance();
return ctx ?? new HttpContextWrapper(System.Web.HttpContext.Current);
}
}
Obviously System.Web.HttpContext is null but i'm not sure why. Any thoughts would be appreciated.
This happens for all requests. Full stack trace below (Company information sanitized)
************* UPDATE *****************
This only seems to be a problem when built in release configuration.
Kind regards,
Alex
[ArgumentNullException: Value cannot be null.
Parameter name: httpContext]
System.Web.HttpContextWrapper..ctor(HttpContext httpContext) +4992306
COMP.PROJ.Web.DependencyResolution.StructureMapDependencyScope.DoGetAllInstances(Type serviceType) +106
System.Web.Http.Services.DefaultServices.GetServices(Type serviceType) +321
System.Web.Http.ServicesExtensions.GetServices(ServicesContainer services) +62
COMP.PROJ.Web.DependencyResolution.IoC.Initialize() +127
COMP.PROJ.Web.App_Start.StructuremapMvc.Start() +11
[TargetInvocationException: Exception has been thrown by the target of an invocation.]
System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) +0
System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) +229
System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) +193
System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) +35
WebActivatorEx.ActivationManager.RunActivationMethods(Boolean designerMode) +445
WebActivatorEx.ActivationManager.Run() +105
[InvalidOperationException: The pre-application start initialization method Run on type WebActivatorEx.ActivationManager threw an exception with the following error message: Exception has been thrown by the target of an invocation..]
System.Web.Compilation.BuildManager.InvokePreStartInitMethodsCore(ICollection1 methods, Func
1 setHostingEnvironmentCultures) +12969195
System.Web.Compilation.BuildManager.InvokePreStartInitMethods(ICollection`1 methods) +12968904
System.Web.Compilation.BuildManager.CallPreStartInitMethods(String preStartInitListPath, Boolean& isRefAssemblyLoaded) +280
System.Web.Compilation.BuildManager.ExecutePreAppStart() +172
System.Web.Hosting.HostingEnvironment.Initialize(ApplicationManager appManager, IApplicationHost appHost, IConfigMapPathFactory configMapPathFactory, HostingEnvironmentParameters hostingParameters, PolicyLevel policyLevel, Exception appDomainCreationException) +1151
[HttpException (0x80004005): The pre-application start initialization method Run on type WebActivatorEx.ActivationManager threw an exception with the following error message: Exception has been thrown by the target of an invocation..]
System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +12968244
System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +159
System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +12807949
Hello,
After installing SM.MVC5 package got next exception System.InvalidOperationException Stack empty. in case when you try to display circular object dependency with partial view.
Ex.
@model WebApplication.Models.Test
or just @Html.DisplayFor(model=>model.Tests)
Object example:
public class Test
{
public ICollection Tests { get; set; }
}
Any thoughts how it is possible to resolve?
Thanks.
I appreciate the fact that the StructureMap.MVC package now gives us a container-per-request pattern out of the box, but there is a problem with the implementation of StructureMapScopeModule. Because its Init method is hit so early in the lifecycle of the application, its subscription to the EndRequest method is the first one registered, trumping all others. In itself, this isn't a problem, but it means that the nested container gets disposed before the Application_EndRequest in Global.asax gets called. If you needed anything out of the container in that method, you'll just get a null reference exception because the container is long gone by then.
It is possible to work around this by using the main Container for stuff that happens in Global.asax, but in the case of things like logging something to a database, you'd now hold a database reference at the main container level, defeating the benefit of the nested container.
I could move the nested container disposal to Global.asax, and control the lifecycle from there, but that means individually and carefully merging any future updates to the Structuremap.MVC5 NuGet package, and re-applying this move.
Moving the nested container handling into a module does a nice job of making it "free" and invisible to developers, but causes problems in situations like this, which I don't think will be that uncommon. People want to clean things up in EndRequest. Often that will require items from the container. Hopefully you can find an approach that works here.
I'm using Structuremap as IOC container.
In old version of Structremap I used ObjectFactory, now I have updated to Structremap.Mvc5 But I can't create an instance of 'ISettingService' in my BuildRegistration method.
My SettingConvention class is:
`public class SettingsConvention : IRegistrationConvention
{
static readonly MethodInfo BuildMethod = typeof(SettingsConvention).GetMethod(
"BuildRegistration",
BindingFlags.Static | BindingFlags.NonPublic);
static ISettings BuildRegistration<TSettings>() where TSettings : ISettings, new()
{
// It's work in old version but now It's not working
// How I should create an Instance Here...
// var settingService = ObjectFactory.Resolve<ISettingService>();
return settingService.LoadSetting<TSettings>();
}
public void ScanTypes(TypeSet types, StructureMap.Registry registry)
{
// Only work on concrete types
types.FindTypes(TypeClassification.Concretes | TypeClassification.Closed).ForEach(type =>
{
// Register against all the interfaces implemented
// by this concrete class
type.GetInterfaces().ForEach(@interface =>
{
if (type.CanBeCastTo(typeof(ISettings)) && typeof(ISettings).IsAssignableFrom(type))
{
var buildMethod = BuildMethod.MakeGenericMethod(type);
registry.For(type).Use(buildMethod.Invoke(null, null));
}
});
});
}
}`
How can I create an instance of 'ISettingService' instead of writing 'ObjectFactory.Resolve()' ?
Thanks everyone for taking the time to try and help explain.
Currently the way this package works is it hooks into via an HttpModule, which is dependent on IIS / IIS Express. Is there anyway to support OWIN, which can be self hosted?
I installed both StructureMap.MVC5 and StructureMap.WebApi2 in the same project. Doing so, caused IoC.Initialize() to be called twice. As a result, it seems that my singleton was created twice, leading to same strange results later on. I wrapped the method with a static _IsInitialized variable check, which solved the problem.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.