I'm trying to do some testing with castle windsor involved, in one of my tests I want to check the windsor installers, so I check that the container can resolve my components given its interface.
So far, so good, the problem starts when the component has PerWebRequest lifestyle in its installer, at first it complained about HttpContext.Current is null, having that one solved creating a fake Context in test setup I'm now having this exception in nunit test
System.Exception : Looks like you forgot to register the http module Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule
Add '' to the section on your web.config. If you're running IIS7 in Integrated Mode you will need to add it to section under
As I'm running this from NUnit, how I can register the module or class in windsor so it works, or how can be mocked, as in this test is not really a web request, just checking that the container resolve the type.
And also this same thing will happen if I make any integration tests with this component outside a real webrequest, is there any way to make this work or really mock a web request so this tests can be run?
Tranks in advance
Fer
In your test you could subscribe to the ComponentModelCreated event and change the lifestyle of your per-web-request components to something else. (example).
If you're writing an integration test with the scope of a single request, singleton should do.
If you're writing an integration test that spans multiple requests, you could use a contextual lifestyle to simulate the scope of requests.
Edit: including code from example (which is no longer available):
container.Kernel.ComponentModelCreated += Kernel_ComponentModelCreated;
…
void Kernel_ComponentModelCreated(Castle.Core.ComponentModel model)
{
if (model.LifestyleType == LifestyleType.Undefined)
model.LifestyleType = LifestyleType.Transient;
}
From version 5 of Windsor the accepted answer doesn't work if you are using Castle.Facilities.AspNet.SystemWeb.WebRequestScopeAccessor because the PerWebRequest lifestyle is already a scoped lifestyle.
I got it to work by changing the the ComponentModelCreated delegate to the following:
void Kernel_ComponentModelCreated(Castle.Core.ComponentModel model)
{
const string CastleScopeAccessorType = "castle.scope-accessor-type";
if (model.ExtendedProperties.Contains(CastleScopeAccessorType))
{
model.ExtendedProperties.Remove(CastleScopeAccessorType);
}
}
I ended up implementing this extension. ATTN: Must call before loading components with the PerWebRequest lifestyle:
public static class WindsorContainerExtensions
{
public static IWindsorContainer OverridePerWebRequestLifestyle(this IWindsorContainer container)
{
container.Kernel.ComponentModelCreated += model =>
{
if (model.IsPerWebRequestLifestyle())
{
model.LifestyleType = LifestyleType.Transient;
}
};
return container;
}
private static bool IsPerWebRequestLifestyle(this ComponentModel model)
{
return model.LifestyleType == LifestyleType.Scoped
&& model.HasAccessorType(typeof(WebRequestScopeAccessor));
}
private static bool HasAccessorType(this ComponentModel model, Type type)
=> model.HasExtendedProperty("castle.scope-accessor-type", type);
private static bool HasExtendedProperty<T>(this ComponentModel model, object key, T expected)
{
return model.ExtendedProperties[key] is T actual
&& EqualityComparer<T>.Default.Equals(actual, expected);
}
}
Requires these imports:
using System;
using System.Collections.Generic;
using Castle.Core;
using Castle.Facilities.AspNet.SystemWeb;
using Castle.Windsor;
If you also want to check if the type of scope is per web request you could also do this
var isPerWebRequestScope = JsonConvert.SerializeObject(model.ExtendedProperties).Contains("Castle.Facilities.AspNet.SystemWeb.WebRequestScopeAccessor")
Related
I would like to reuse a library class that I made for some projects in Asp .Net Framework within an Asp .Net Core project on which I am now working.
For that project I have to use a MySQL database so I added the MySqlConnector NuGet package to my library class.
As the registered .NET Data Providers are not automatically added to the Global Assembly Cache I must register it manually thanks the call of that method DbProviderFactories.RegisterFactory("MySqlConnector", MySqlClientFactory.Instance) during application startup as mentionned here.
It's my first .Net core project so I don't know if that's how I should do it but I called that method in the Startup.cs file like this :
It is working but I am wondering if it's the right way to do it. Would you advise me another proper way to do it?
Thanks
There is nothing fundamentally wrong with your approach, IMO.
One problem I see is the task you're trying to run takes too long, in which case you're better off spawning a task.
The other is reusability, your code is coupled together. You could solve that by wrapping it in a class and injecting it into a middleware component by interface, and then calling a method. For example:
public interface ITask { void Run(); }
class RegisterMySqlTask : ITask { public void Run() { DbProviderFactories.RegisterFactory("MySqlConnector", MySqlClientFactory.Instance); } }
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ITask, RegisterMySqlTask>();
//rest goes here
}
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
context.RequestServices.GetRequiredService<ITask>().Run();
await next(context);
});
//rest goes here
}
Note, however, that this may be overcomplicating things. As I said, I believe that you are not doing anything wrong.
I have ASP.NET Core API. I have already gone through documentation here that shows how to do integration testing in asp.net core. The example sets up a test server and then invoke controller method.
However I want to test a particular class method directly (not a controller method)? For example:
public class MyService : IMyService
{
private readonly DbContext _dbContext;
public MyService(DbContext dbContext)
{
_dbContext = dbContext;
}
public void DoSomething()
{
//do something here
}
}
When the test starts I want startup.cs to be called so all the dependencies will get register. (like dbcontext) but I am not sure in integration test how do I resolve IMyService?
Note: The reason I want to test DoSomething() method directly because this method will not get invoked by any controller. I am using Hangfire inside this API for background processing. The Hangfire's background processing job will call DoSomething() method. So for integration test I want to avoid using Hangfire and just directly call DoSomething() method
You already have a TestServer when you run integration tests, from here you can easily access the application wide container. You can't access the RequestServices for obvious reason (it's only available in HttpContext, which is created once per request).
var testServer = new TestServer(new WebHostBuilder()
.UseStartup<Startup>()
.UseEnvironment("DevelopmentOrTestingOrWhateverElse"));
var myService = testServer.Host.Services.GetRequiredService<IMyService>();
My current setup is using Ninject for simple IoC, everything goes fine, but I'm not able to resolve one of the classes I need inside my AuthorizeAttribute. I need to access a class that does ClaimsVerification:
Here's my code:
IoC Config:
var kernel = new StandardKernel(); // Ninject IoC
// These registrations are "per instance request".
// See http://blog.bobcravens.com/2010/03/ninject-life-cycle-management-or-scoping/
kernel.Bind<RepositoryFactories>().To<RepositoryFactories>()
.InSingletonScope();
kernel.Bind<IRepositoryProvider>().To<RepositoryProvider>();
kernel.Bind<ISmartDocumentorUow>().To<SmartDocumentorUow>();
kernel.Bind<IClaimsVerification>().To<ClaimsVerification>();
// kernel
//kernel.BindFilter<MyAuthorizeAttribute>(FilterScope.Controller, 0).WhenControllerHas<RequireRolesAttribute>();
// Tell WebApi how to use our Ninject IoC
config.DependencyResolver = new NinjectDependencyResolver(kernel);
MyAuthorizeAttribute:
public class MyAuthorizeAttribute : AuthorizeAttribute
{
[Inject]
IClaimsVerification clamisverify { get; set; }
public MyAuthorizeAttribute()
{
//var x = System.Web.Mvc.DependencyResolver.Current.(typeof(IClaimsVerification));
}
Yap, sorry, the problem was injecting the iClaimsverification that isn't working in web api..
I tryed with the public property and still it didn't work.
the bindfilter is commented out, because it doesn't exist in the core NInject api (dll), it does exists in the MVC dll of ninject but it works for Action filters in the web mvc, and not in the api mvc for what i can tell..
i do solved the issue like this, though i don't like a lot of this fix:
private IClaimsVerification verifier
{
get
{
return (GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IClaimsVerification)) as IClaimsVerification);
}
}
The property you have marked with Inject is private - you need to initialize Ninject with a custom configuration to opt into what would be a much less efficient process
(You didnt state the problem in your question. I see you were trying BindFilter, but it's commented out (why?) - this is the correct approach. I recommend reading the Ninject.MVC3 wiki article on BindFilter for an example)
I am trying to create an IOC container in Castle Windsor that's configuration is shared across assemblies.
(What follows is an example of how this works in Unity. What I want to do is to make it work the same way using Castle Windsor)
I have the following project configuration...
TestCompany.Services.Host
(Web project hosting a number of .svc files)
PrintService.svc
Web.Config
Unity.Config
TestCompany.Services.PrintService
IPrintService.cs
PrintService.cs
The actual implementation of my "PrintService" is not implemented inside my Services.Host but in the TestCompany.Services.PrintService assembly.
As part of my shared project code (not shown) I have a container helper which is responsible for loading the unity configuration...
public static IUnityContainer GetContainer()
{
// Checks for existance of container (_container == null) ommitted.
var section = ConfigurationManager.GetSection("unity") as UnityConfigurationSection;
section.Configure(_container, name);
...
...
}
This method loads the unity configuration section from the Unity.Config and uses it to configure the container.
The advantage of this method is that one Unity.Config loaded inside (I presume) the AppDomain can service a number of assemblies. Simply calling GetContainer() from any of the assemblies consumed by my service host will return a container populated with the same type resolution's etc.
I really want to use the fluent configuration in Castle Windsor but I dont see how without this "shared" configuration file that can be acheived. PrintService and any future services will all need to resolve the same dependencies and I dont want to have to repeat my fluent configuration between these services.
Ideally I need some sort of container configured in the service host app that can "flow" into all of the assemblies that it makes use of.
Thanks.
I think I may not be understanding your question but I think I understand your scenario and here is how I do something similar, if it helps at all...
My Philosophy:
Each part of the application should be in charge of registering what
it knows about and nothing more, so there is no need for a single
central configuration file and things that are shared between
components are registered in one place and their interfaces are
available everywhere via a common library.
So let's take an example...
First of all, let us just say (for the purposes of my example) that IPrintService is something that you want to register an implementation of once and use throughout the application and that we have some other component that needs to be implemented by some external module from the main application. We, therefore, create an assembly called Common like so:
Common
public interface IPrintService
{
void Print();
}
public interface IMyService
{
void DoSomething();
}
Now let us think about the main part of the application (maybe it is an ASP .NET application, maybe justa console application, does not really matter). Here we construct the container and ask it to find all the possible components. We can do that like so:
Main Application
// Could be the Global.asax code behind but for simplicity this is
// just a console application
class Program
{
private static readonly IWindsorContainer Mycontainer
= BootstrapContainer();
// Allow access to the raw container - this is probably a bad idea but
// in the rare case that you need it you can get it from here
public static IWindsorContainer Container { get { return Mycontainer; } }
private static IWindsorContainer BootstrapContainer()
{
// Here we will just install every IWindsorInstaller found in any
// assembly in the same folder as the application (so no need for
// references or anything).
var c = new WindsorContainer();
string folder = Path.GetDirectoryName(
Assembly.GetExecutingAssembly().Location);
c.Install(FromAssembly.InDirectory(new AssemblyFilter(folder)));
return c;
}
}
// Here is the print service implementation
public class MyPrintService : IPrintService
{
public void Print()
{
// Print!
}
}
// This is the installer for the main module - here we are saying exactly
// what is implementing the interface
public class MainApplicationInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container,
IConfigurationStore store)
{
container
.Register(Component
.For<IPrintService>()
.ImplementedBy<MyPrintService>());
}
}
So now we have a common library with our shared inetrfaces and a main application that will register an implementation for our shared interface and also load up any other modules in the system.
The only thing, therefore, left to do is to consume that print service and use it. We can do this anywhere that is using the container so let's create a third assembly that references only Common (we will call it test module.
Test Module
// This installer installs just the things inside this module since that
// is all it knows about but those things can use things that are
// registered in the container by anybody.
public class TestModuleInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container,
IConfigurationStore store)
{
container
.Register(Component
.For<IMyService>()
.ImplementedBy<MyServiceThatDoesSomething>());
}
}
public class MyServiceThatDoesSomething : IMyService
{
private readonly IPrintService _printService;
public MyServiceThatDoesSomething(IPrintService printService)
{
_printService = printService;
}
public void DoSomething()
{
// Use the print service!
_printService.Print();
}
}
Finally compile everything and copy the test module to the same folder as the main application and then from the main you can do this:
Container.Resolve<IMyService>().DoSomething();
And then the magic happens! Well, some code runs and you find that the print service is called by the class from the module even though it knows nothing about it.
Anyway, maybe that helps a little bit, maybe not, good luck!
I recently came across this article titled:
Linq to Sql and ASP.NET MVC – DataContext Per Request
at this link:
http://www.jeremyskinner.co.uk/2010/01/31/linq-to-sql-and-asp-net-mvc-datacontext-per-request/
I would like to set this up using ninject rather than structuremap preferably using the new mvc 3 dependency resolver as I'm using mvc 3 rtm.
The relevant part of the article is this:
Firstly, you’ll need to configure StructureMap by calling ObjectFactory.Configure inside your Global.asax passing in a custom Registry instance:
protected void Application_Start() {
RegisterRoutes(RouteTable.Routes);
ObjectFactory.Configure(cfg => {
cfg.AddRegistry(new MyRegistry());
});
}
The code for MyRegistry looks like this:
public class MyRegistry : Registry {
public MyRegistry() {
For<BlogDataContext>()
.HttpContextScoped()
.Use(c => new BlogDataContext());
Scan(scan => {
scan.AddAllTypesOf<Controller>();
});
}
}
Here I’m telling StructureMap to create one instance of my BlogDataContext per HTTP Request as well as registering each Controller instance with the container.
Next, we need to tell MVC to use StructureMap to instantiate our controllers. This can be done by creating a custom ControllerFactory:
public class StructureMapControllerFactory : DefaultControllerFactory {
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) {
return (IController) ObjectFactory.GetInstance(controllerType);
}
}
We can then replace the DefaultControllerFactory with the StructureMapControllerFactory in our Application_Start:
protected void Application_Start() {
RegisterRoutes(RouteTable.Routes);
ObjectFactory.Configure(cfg => {
cfg.AddRegistry(new MyRegistry());
});
ControllerBuilder.Current.SetControllerFactory(
new StructureMapControllerFactory());
}
I would like to do the same thing with ninject 2.0 rather than structure map. I'm building an mvc 3 site with ninject mvc3. I downloaded the ninject mvc 3 package from nuget and I have this file in my solution which handles wiring up ninject.
AppStart_NinjectMVC3.cs
I do not want to use structurmap and I know the same setup can be done with ninject, but I'm unsure how to wire it up.
Thank you.
I'd rather use the official mvc3 extension from the ninject project found at https://github.com/ninject/ninject.web.mvc. It comes with a full example application showing how to wire up an mvc3 application.