I'm currently overriding the default ModelMetadataProvider in the Global.asax file using this
ModelMetadataProviders.Current = new RedSandMetadataProvider(ModelMetadataProviders.Current);
and this works perfectly. But I'd like to use the IDependancyResolver feature of MVC3 to let IoC provide the ModelMetadataProvider implementation instead. I'm using StructureMap to do it (Just installed it into the project using NuGet) but for some reason it not behaving as expected.
x.For<ModelMetadataProvider>().Use(new RedSandMetadataProvider(ModelMetadataProviders.Current));
I put a breakpoint on the constructor of RedSandMetadataProvider() and it is getting hit. And I also put a breakpoint on the GetServices() function of the automatically added SmDependencyResolver.cs file to make sure it was IoC that was calling my constructor, and everything seems fine, the constructor gets called on the second page load I think, but it never calls my GetMetadataForProperty() function of my MetadataProvider. Now I KNOW this gets called correcetly when I set it up in the Global.asax, but every time I try to achieve the same result using IoC, I see the constructor called on my class and that's it. I tried adding a .Singleton() to the StrctureMap registration of the type and that causes my constructor to get called much sooner but it still never actually USES the object after it's constructed.
Am I missing something?
You need to implement IMvcServiceLocator and call MvcServiceLocator.SetCurrent() to tell MVC to use StructureMap: http://bradwilson.typepad.com/blog/2010/07/service-location-pt2-controllers.html
I solved my problem with this issue in another question.
Setting up DependancyResolver in MVC3 using StructureMap for ModelMetadataProvider & ModelValidatorProvider
Please see it if you're encountering problems with this as well.
Related
I see defaut template use ServiceProvder.GetService<ApplicationDbCotnext>() to initialize a DbContext,
But when you inside a Static Method, I have no idea how to get a DbContext, because there is no ServiceProvider.
Is there a way to get the ServiceProvider ?
Well, first of all, this has nothing to do with asp.net-core per se. This has more to do with how Dependency Injection works. You have to ask yourself why your method is static. Is that really necessary?
If you can't get rid of your static method, you might as well go all the way and introduce another anti-pattern, the Service Locator Pattern. In short: In the Startup class you put a reference to the ServiceProvider in a static property (call it for instance "ServiceProviderSingleton") of a static class (for instance "ServiceProviderProvider"). This way you can just call "ServiceProviderProvider.ServiceProviderSingleton.GetService()".
Again, i suggest giving your overal design a critical look. But if this is what you need/want then I hope it helped.
If we have a look at Microsoft's static methods (extension) - they seem not to use logging there - just throw appropriate Exception, for example in UseMvc method (for StartUp class):
https://github.com/aspnet/Mvc/blob/760c8f38678118734399c58c2dac981ea6e47046/src/Microsoft.AspNetCore.Mvc.Core/Builder/MvcApplicationBuilderExtensions.cs
I've been using MvcSiteMapProvider based on authorize attributes and it was all right until we introduced a new class derived from AuthorizeAttribute. Main difference is in its constructor signature:
public MyAuthorizeAttribute(param RoleCode[] roles) {
Roles = string.join(",", roles.Select(r => r.ToString());
}
And... MvcSiteMapProvider shown unexpected result: only actions marked by MyAuthorizeAttribute became invisible. I've checked that by disabling this constructor - everything went as it had been before adding a parameter to the constructor. Also - it's not params specific - any parameter (event int) leads to such behaviour.
AS I understood from MvcSiteMapProvider sources, it emits some code to emulate authorize attributes - but looks like it's impossible to save assembly generated by external code. I know that there is a workaround - use some kind of enumerable property, but have you got any suggestions how to make it work with constructor parameters? Do you know why MvcSiteMapProvider behaves like that?
So, after spending some time in debugging, I realized the answer: dynamic proxies.
The problem is that during request execution inside MVC framework there is no easy way to find out how a class derived from AuthorizeAttribute performs its work. In case of access check failure some could throw exception, some - return 401 status code, some redirect to login page at once, and so on.
But MvcSiteMapProvides does that! It uses the following workaround:
if class is AuthorizeAttribute:
create an instance of InternalAuthorize class which is fairly simple.
copy all properties there and
invoke AuthorizeCore method which returns boolean value.
else
generate a proxy class derived from a type of attribute,
create instance, /// << here we get an exception
copy all properties there and
invoke AuthorizeCore method which returns boolean value.
As it is clear, that's not an easy task to make a proxy, which is aware of your constructor parameters. Exception about default constructor absence is thrown, of course, but it is then consumed by empty catch clause. That is really sad - at least a single debug trace would have saved me a couple of hours.
So the answer at last:
Obviously you should use parameterless attribute constructor (why oh why that's not mentioned anywhere?)
Make custom acl provider: implement IAclModule interface and unleash your knowledge about your own authorize attributes within it.
I have a bit of a dilemma, which to be honest is a fringe case but still poses an issue.
Currently I am using Ninject MVC and bind all my controllers like so:
Kernel.Bind<SomeController>.ToSelf();
Which works a treat for 99% of things that I have needed to do, however at the moment I am doing some wacky stuff around dynamic routing and dynamic controllers which require me to manually write a method to get the type of a controller from ninject. Now initially I thought it would be easy, but its not... I was expecting that I could get the controller based on its name, but that didnt work.
Kernel.Get<IController>("SomeController");
That got me thinking that its probably because it only knows about a binding to SomeController, not IController. So I thought, I can just write all my bindings like so:
Kernel.Bind<IController>.To<SomeController>().Named("SomeController");
This way it should be easy to get the type of the controller from the name doing the previous code, however if I were to bind this way, I would have a problem when I come to unbind the controllers (as plugins can be loaded and unloaded at runtime). So the normal:
Kernel.Unbind<SomeController>()
Which was great, will no longer work, and I would have to do:
Kernel.Unbind<IController>();
However then I realised that I need to give it some constraint to tell it which binding for this type I want to unbind, and there seems to be no overloads or DSL available to do this...
So I am trapped between a rock and a hard place, as I need to satisfy the ControllerLookup method, but also need to keep it so I can add and remove bindings easily at runtime.
protected override Type GetControllerType(RequestContext requestContext, string controllerName) {
//... find and return type from ninject
}
Anyone have any ideas?
(Just incase anyone questions why I am doing this, its because of the way I am loading plugins, Ninject knows about the types and the namespaces, but within the context of creating a controller it doesn't know the namespace just the controller name, so I do this to satisfy the isolation of the plugin, and the location of the dynamic controller, it is a roundabout way of doing it, but it is what people have done with AutoFac before Example of similar thing with AutoFac)
In my opinion the bindings should be created once at application startup and not change anymore after the first resolve. Everything else can lead to strange issues. Unless you have proper isolation using an AppDomain for each plugin you can not really unload them anyway. Instead of unloading bindings you can make them conditional and disable them using some configuration.
If you really want to unload bindings then I suggest not to do it for single bindings but take advantage of modules. Load all bindings belonging to one plugin together in one or several modules and unload those modules instead of the single bindings.
I've ran into a rather hairy problem. There is probably a simple solution to this but I can't find it!
I have a custom HttpHandler that I want to process a request, log certain info then enter the details in the database. I'm using NUnit and Castle Windsor.
So I have two interfaces; one for logging the other for data entry, which are constructor injected. I quickly found out that there is no way to call the constructor as the default parameterless constructor is always called instead.
So I thought I would use Setter injection and let Castle windsor sort it out. This actually works as when I use container.Resolve<CustomHttpHandler>(); I can check that the logger is not null. (In Application_Start in Global.asax.cs)
The problem is although Castle Windsor can create the instance the http application is not using it??? I think??
Basically the whole reason for doing it this way was to be able to test the logger and data repository code in isolation via mocking and unit testing.
Any ideas how I can go about solving this problem?
Thanks!
Not possible, at least not directly. IHttpHandler objects are instantiated by the ASP.NET runtime and it doesn't allow Windsor to get involved in its creation. You can either:
Pull dependencies, by using the container as a service locator.
Set up a base handler that creates, injects and delegates to your own handlers (see how Spring does it)
Use the container as a service locator for another service that handles the entire request (as saret explained)
What you could do is have the HttpHandler call out to another object that actually handles the request. so in your HttpHandler's ProcessRequest method you would do something like this:
public void ProcessRequest(HttpContext context)
{
var myHandlerObject = container.Resolve<HandlerObject>();
myHandlerObject.ProcessRequest(context or some state/info that is required)
}
im calling an actionscript class from my main mxml file. the actionscript class is responsible for calling a web service and handling the response, however im having trouble and keep getting the following error; (im new to flex btw)
Error #1009: Cannot access a property or method of a null object reference.
my code goes as follows;
public function getSites(argWsdl:String):void{
ws = new WebService();
ws.loadWSDL(argWsdl);
ws.getSites.addEventListener(ResultEvent.RESULT,echoResultHandler);
ws.getSites();
}
public function echoResultHandler(event:ResultEvent):void {
var siteField:ArrayCollection = event.result as ArrayCollection;
Application.application.setSiteField(siteField);
}
when i run the debugger the code never reaches the result hanlder and i see the #1009 error in the variable list.
any ideas?
looks like you have it sorted, but just to add more information in case someone else comes along to this question, you generally see this error when you are trying to use something that hasn't been created yet. A lot of the time you will see it when trying to access UI components that have not yet been created (its good to rely on the creationComplete event for these sort of things), but in this case it looks like you are using the webservice before it is completely ready (the wsdl hasnt been loaded yet).
Just so you know, you can also define your webservices in mxml (mx:webservice) and specify the wsdl there or you can also load the wsdl later on from a configuration file afterwards just by referencing the ID.
sorted it out,
i needed to created a loadEvent and loadhandler. Once loadWsdl is called the loadhandler specifies the laodHandler to use, inside the loadHandler i call the method name as seen in the wsdl
thanks Ryan,
the main reason im using a seperate actionscript class is so i can reuse the same web service calls across my components without having to retype the same code. I couldnt think of a better way to do this - maybe a could have done the same with a custom component