Please can anyone advise if it is possible to switch connection strings for a DbContext using Ninject binding, based upon Current Culture? My current (non-working) cod is as below.
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
private static string GetCultureBasedConnectionString()
{
string culture = "de-DE"; // TODO Replce with Thread.CurrentThread.CurrentCulture.Name
string cultureBasedConnectionString = ConnectionStringHelper.GetConnectionStringWithCulture(culture);
return cultureBasedConnectionString;
}
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ApplicationDb>().To<ApplicationDb>()
.InRequestScope()
.WithConstructorArgument("connectionString", context => GetCultureBasedConnectionString());
.
.
.
}
This is based upon the example here, Ninject - dynamically specifying a connection string based on a sub domain, but it does not call through to my GetCultureBasedConnectionString() method on each request except when the application starts up...
I have read here on So that using NInjects Rebind() method is not good.
This SO thread also did not get me in the right direction, either.
Yes you are describing the expected behavior. The binding code is executed when.. well when you call Bind - and not every time the type is retrieved. The Func/Method specified in ToMethod would be executed every time the binding is applied.
Although i believe you can simplify your code to:
kernel.Bind<ApplicationDb>().To<ApplicationDb>()
.InRequestScope()
.WithConstructorArgument(
"connectionStringGetter",
context => GetCultureBasedConnectionString());
and thus get rid of ConnectionStringGetter().
A slight change to use a Func<string> which calls back to my GetCultureBasedConnectionString() method and this seems to defer execution of the GetCultureBasedConnectionString() method until the HttpRequest is made, which now appears to be working for me... Is that anticipated behviour?
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
private static string GetCultureBasedConnectionString()
{
string culture = Thread.CurrentThread.CurrentCulture.Name;
string cultureBasedConnectionString = ConnectionStringHelper.GetConnectionStringWithCulture(culture);
return cultureBasedConnectionString;
}
private static Func<string> ConnectionStringGetter()
{
var function = new Func<string>(GetCultureBasedConnectionString);
return function;
}
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ApplicationDb>().To<ApplicationDb>()
.InRequestScope()
.WithConstructorArgument("connectionStringGetter", context => ConnectionStringGetter());
Related
I am making use of Prism in my xamarin forms project.I was able to use dependency injection(constructor injection) in my View Model without any problems.I am also making use of background services to push long running tasks in the background.How do I inject dependency in my Background services?When I try to pass the interface object as a paramater to the constructor(SyncingBackgroundingCode) ,the object(SqliteService) is null.I have registered and resolved the objects in the dependency injection container.
How to handle this case?Can anybody provide an example or link to implement this scenario?
This is the piece of code where im trying to implement dependency injection.
This is in Droid :-
public class AndroidSyncBackgroundService : Service
{
CancellationTokenSource _cts;
public override IBinder OnBind (Intent intent)
{
return null;
}
public override StartCommandResult OnStartCommand (Intent intent, StartCommandFlags flags, int startId)
{
_cts = new CancellationTokenSource ();
Task.Run (() => {
try {
//INVOKE THE SHARED CODE
var oBackground = new SyncingBackgroundingCode();
oBackground.RunBackgroundingCode(_cts.Token).Wait();
}
catch (OperationCanceledException)
{
}
finally {
if (_cts.IsCancellationRequested)
{
var message = new CancelledTask();
Device.BeginInvokeOnMainThread (
() => MessagingCenter.Send(message, "CancelledTask")
);
}
}
}, _cts.Token);
return StartCommandResult.Sticky;
}
public override void OnDestroy ()
{
if (_cts != null) {
_cts.Token.ThrowIfCancellationRequested ();
_cts.Cancel ();
}
base.OnDestroy ();
}
}
This is in PCL:-
public class SyncingBackgroundingCode
{
public SQLiteConnection _sqlconnection;
SqliteCalls oSQLite = new SqliteCalls();
ISqliteService _SqliteService;
public SyncingBackgroundingCode(ISqliteService SqliteService)
{
//object is null
}
public async Task RunBackgroundingCode(CancellationToken token)
{
DependencyService.Get<ISQLite>().GetConnection();
await Task.Run (async () => {
token.ThrowIfCancellationRequested();
if (App.oSqliteCallsMainLH != null)
{
App.bRunningBackgroundTask = true;
oSQLite = App.oSqliteCallsMainLH;
await Task.Run(async () =>
{
await Task.Delay(1);
oSQLite.ftnSaveOnlineModeXMLFormat("Offline", 0);
oSQLite.SyncEmployeeTableData();
oSQLite.SaveOfflineAppCommentData();
oSQLite.SaveOfflineAdditionToFlowData();
await Task.Delay(500);
var msgStopSyncBackgroundingTask = new StopSyncBackgroundingTask();
MessagingCenter.Send(msgStopSyncBackgroundingTask, "StopSyncBackgroundingTask");
});
}
}, token);
}
}
Unfortunately Xamarin and Xamarin Forms don't give frameworks like Prism anywhere to tie into to handle IoC scenarios. There are a couple of ways you can handle this though.
First the Container is a public property on the PrismApplication in your background service you could do something like:
public class FooBackgroundService
{
private App _app => (App)Xamarin.Forms.Application.Current;
private void DoFoo()
{
var sqlite = _app.Container.Resolve<ISQLite>();
}
}
Another slightly more involved way would be to use the ServiceLocator pattern. You might have something like the following:
public static class Locator
{
private static Func<Type, object> _resolver;
public static T ResolveService<T>() =>
(T)_resolver?.Invoke(typeof(T));
public static void SetResolver(Func<Type, object> resolver) =>
_resolver = resolver;
}
In your app you would then simply set the resolver. Prism actually does something similar to this with the ViewModel locator, which then allows it to inject the correct instance of the NavigationService.
public class App : PrismApplication
{
protected override void OnInitialized()
{
SetServiceLocator();
NavigationService.NavigateAsync("MainPage");
}
protected override void RegisterTypes()
{
// RegisterTypes
}
private void SetServiceLocator()
{
Locator.SetResolver(type => Container.Resolve(type, true));
}
}
Finally your service would simply reference the Service Locator like:
public class BarBackgroundService
{
public void DoBar()
{
var sqlite = Locator.ResolveService<ISQLite>();
// do foo
}
}
I'm using mvc web api. I have a generic IRepository and IUnitOfWork library which works perfect in asp.net mvc but when I intended to use it in my mvc web api project my repository object becomes null and consequently leads to exception. my repository and UnitOfWork objects are being instantiated and initialized inside a constructor which takes one IunitOfWork object as a parameter
here is the code (constructor code)
private IRepository<AspNetUserAccount> AccountRepository;
private IRepository<Doctor> DoctorRepository;
private readonly IUnitOfWork UnitOfWork;
public AccountController(IUnitOfWork unitOfWork)
{
UnitOfWork = unitOfWork;
AccountRepository = unitOfWork.Repository<AspNetUserAccount>();
DoctorRepository = unitOfWork.Repository<Doctor>();
}
public AccountController()
{
}
and here is the usage of my Repository and UnitOfWork objects in Register action of Account controller.
[AllowAnonymous]
[Route("Register")]
public ResultViewModel Register([FromBody]UserBindingModel model)
{
if (!ModelState.IsValid)
{
return new ResultViewModel(400, "Model Is Not Valid");
}
using (DigiTebDBContext db = new DigiTebDBContext())
{
using (var Transaction = db.Database.BeginTransaction())
{
try
{
var user = new ApplicationUser()
{
UserName = model.UserName,
Email = model.Email
,
CreateTimeStamp = DateTime.Now,
LastModifiedTimeStamp = DateTime.Now
};
IdentityResult result = UserManager.Create(user, model.Password);
if (!result.Succeeded)
throw new Exception(((string[])result.Errors)[0]);
UserUtility.AssignRoleToUser(user.Id, "Operator");
var Account = new AspNetUserAccount
{
AccountTypeValue = AccountType.Demo,
CreateTimeStamp = DateTime.Now
,
CreateUserId = user.Id,
CurrentUserCount = 0,
MaxUserCount = 1,
IsMultiUser = false
,
ExpiryDate = DateTime.Now,
LastModifiedUserId = user.Id,
LastModifiedTimeStamp = DateTime.Now
};
AccountRepository.Insert(Account);
UnitOfWork.Save();
Transaction.Commit();
return new ResultViewModel(200, "Registeration was successfull");
}
catch(Exception ex)
{
Transaction.Rollback();
return new ResultViewModel(400, ex.Message);
}
finally
{
UnitOfWork.Dispose();
}
}
}
My problem is that my Repository (AccountRepository) and UnitOfWork (UnitOfWork) objects are being instantiated and initialized in a constructor that will never be called. when an action is called (no matter what) only parameterless constructor is being called and not my desired constructor with one parameter.
How can I change it so that the desired constructor being called instead of default parameterless constructor, in other word how can I determine which constructor is being called when an action is called in mvc web api???
I searched a bit about it and I figured that I can use the DI to resolve this issue, I used Ninject but I don't know how and where exactly I should write my codes (using Ninject) to change the default constructor of my Account class (Controller) and set it to another constructor
here is my Ninject modifications in NinjectWebCommon.cs in App_Start folder
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
private static void RegisterServices(IKernel kernel)
{
kernel.Bind(typeof(IRepository<AspNetUserAccount>)).To(typeof(Repository<AspNetUserAccount>)).InRequestScope();
kernel.Bind(typeof(IDataContext)).To(typeof(DigiTebDBContext)).InRequestScope();
kernel.Bind(typeof(IUnitOfWork)).To(typeof(UnitOfWork)).InRequestScope();
kernel.Bind<HttpContext>().ToMethod(ctx => HttpContext.Current).InTransientScope();
}
Thanks in advance
I found the answer the myself originally from this link MVC 4 Web Api Controller does not have a default constructor?
first the WebApiContrib.IoC.Ninject should be installed frm Nuget and then CreateKernel in NinjectWebCommon.cs function should be modified like below
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
//Note: Add the line below:
GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
by doing so when I comment the default parameterless constructor in my controller, the DI (in this case ninject) recognize the alternative constructor (in this case the constructor with one parameter) itself
We have a multi-database solution and are passing the connection string to a factory function like so:
container.Register<IDbContextFactory>(
f => new DynamicDbContextFactory(ClientConfig.GetConnectionString()),
new PerScopeLifetime());
ClientConfig contains a static dictionary that gets populated on app start that maps a sub domain to a connection string. It seems that this approach is causing a memory leak (not 100% sure about this causing the leak but there is a leak).
public class ClientConfig
{
private static ConcurrentDictionary<string, string> ConnectionStringManager
{
get;
set;
}
// etc.
}
My question is in MVC what is the best way to hold a list of connection strings that can be easily looked up on each request in order to pass that down the chain.
Edit : The question was initially tagged with Autofac
With Autofac you don't have to use a dictionary and something like that to do what you want. You can use a custom parameter :
public class ConnectionStringParameter : Parameter
{
public override Boolean CanSupplyValue(ParameterInfo pi,
IComponentContext context,
out Func<Object> valueProvider)
{
valueProvider = null;
if (pi.ParameterType == typeof(String)
&& String.Equals(pi.Name, "connectionString",
StringComparison.OrdinalIgnoreCase))
{
valueProvider = () =>
{
// get connectionstring based on HttpContext.Current.Request.Url.Host
return String.Empty;
};
}
return valueProvider != null;
}
}
Then register your Parameter using a Module
public class ConnectionStringModule : Autofac.Module
{
protected override void AttachToComponentRegistration(
IComponentRegistry componentRegistry, IComponentRegistration registration)
{
registration.Preparing += registration_Preparing;
}
private void registration_Preparing(Object sender, PreparingEventArgs e)
{
Parameter[] parameters = new Parameter[] { new ConnectionStringParameter() };
e.Parameters = e.Parameters.Concat(parameters);
}
}
Module you have to register inside your container using
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterModule(new ConnectionStringModule());
Each time Autofac have to resolve a parameter of type String named connectionString it will used the custom parameter and get your connectionstring based on what you want.
By the way this code sample use HttpContext.Current. In case of a multithreaded process it may return null. I don't recommend using HttpContext.Current for such things. You can use an intermediate class instead of accessing it, for example a IConnectionstringProvider interface.
public interface IConnectionstringProvider
{
String ConnectionString { get; }
}
public class ConnectionStringProvider : IConnectionstringProvider
{
public ConnectionStringProvider(Strong host)
{
// get connectionstring based on host
this._connectionString = String.Empty;
}
private readonly String _connectionString;
public String ConnectionString
{
get { return this._connectionString; }
}
}
Inside your Parameter you will have to change the valueProvider by
valueProvider = () =>
{
return context.Resolve<IConnectionstringProvider>().ConnectionString;
};
And finally you will have to register your IConnectionstringProvider at the beginning of the request lifetimescope :
class Program
{
static void Main(string[] args)
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterModule(new ConnectionStringModule());
IContainer container = builder.Build();
container.ChildLifetimeScopeBeginning += container_ChildLifetimeScopeBeginning;
}
private static void container_ChildLifetimeScopeBeginning(
Object sender, LifetimeScopeBeginningEventArgs e)
{
String host = HttpContext.Current.Request.Url.Host;
ContainerBuilder childLifetimeScopeBuilder = new ContainerBuilder();
childLifetimeScopeBuilder.RegisterInstance(new ConnectionStringProvider(host))
.As<IConnectionstringProvider>()
.SingleInstance();
childLifetimeScopeBuilder.Update(e.LifetimeScope.ComponentRegistry);
}
}
Of course there is many way to do it but you have the idea
I am developing a Web Api and I decided to use custom DependencyResolver. I refer this [Dependency Injection for Web API Controllers] article. Everything is working well so far in the terms of dependency injection into controllers. Code snippet of my configuration from my Owin startup class
private void RegisterIoC(HttpConfiguration config)
{
_unityContainer = new UnityContainer();
_unityContainer.RegisterType<IAccountService, AccountService>();
.........
.........
config.DependencyResolver = new UnityResolver(_unityContainer);
}
But at the time when Api starts for the very first time some ResolutionFailedException thrown (but catched) inside the UnityResolver's GetService method. Here is the exception message
"Exception occurred while: while resolving.
Exception is: InvalidOperationException -
The current type, System.Web.Http.Hosting.IHostBufferPolicySelector,
**is an interface and cannot be constructed. Are you missing a type mapping?**"
Above same exception thrown following types
System.Web.Http.Hosting.IHostBufferPolicySelector
System.Web.Http.Tracing.ITraceWriter
System.Web.Http.Metadata.ModelMetadataProvider
System.Web.Http.Tracing.ITraceManager
System.Web.Http.Dispatcher.IHttpControllerSelector
System.Web.Http.Dispatcher.IAssembliesResolver
System.Web.Http.Dispatcher.IHttpControllerTypeResolver
System.Web.Http.Controllers.IHttpActionSelector
System.Web.Http.Controllers.IActionValueBinder
System.Web.Http.Validation.IBodyModelValidator
System.Net.Http.Formatting.IContentNegotiator
I know that these ResolutionFailedException are thrown because I did not provide mappings in my unity configuration for above types.
Now here is my question :-, If I implement custom unity DependencyResolver I need to define mappings of above types and if need to define what will be their corresponding default implementation types OR is there some alternative way to implement DependencyResolver. I am really concerned even though application is running fine now, failing to resolve above type can cause serious issue later. Please help.
One final Addition:-
For following types, same ResolutionFailedException thrown when I make request for any action into the my web api
System.Web.Http.Dispatcher.IHttpControllerActivator
System.Web.Http.Validation.IModelValidatorCache
System.Web.Http.Controllers.IHttpActionInvoker
I was running in to the same issue using Unity with WebApi and OWIN/Katana.
The solution for me was to use the UnityDependencyResolver defined in the Unity.WebApi Nuget package instead of my own custom implementation (like #Omar Alani above)
Install-Package Unity.WebAPI
Note that the package will try and add a file named UnityConfig.cs in App_Start (the filename I used myself).
In that UnityConfig.cs file the package will add code to register the container against the GlobalConfiguration.Configuration.DependencyResolver which is not what we want with OWIN.
So instead of using:
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
Change to use:
config.DependencyResolver = new UnityDependencyResolver(container);
For completeness:
My UnityConfig.cs
public static class UnityConfig
{
public static void Register(HttpConfiguration config)
{
var container = new UnityContainer();
// Your mappings here
config.DependencyResolver = new UnityDependencyResolver(container);
}
}
My Startup.cs
[assembly: OwinStartup(typeof(UnityTest.BusinessLayer.Api.ApiStartup))]
namespace UnityTest.BusinessLayer.Api
{
public partial class ApiStartup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
HttpConfiguration httpConfig = new HttpConfiguration();
UnityConfig.Register(httpConfig);
ConfigureAuth(app); //In App_Start ->Startup.Auth
WebApiConfig.Register(httpConfig);
app.UseWebApi(httpConfig);
}
}
}
In case any of the above solutions still don't work for people, here's how I solved it.
After spending a day chasing down this error, it turned out to be some sort of VS caching issue. Out of desperation, I deleted all .suo files and force-get-latest, which seems to have resolved the issue.
This has been asked a long time ago, but I encountered a solution that wasn't mentioned here so maybe someone is still interested.
In my case, these exceptions were already caught internally by Unity (or whatever), but my Exception Settings in Visual Studio made them still show up. I just had to uncheck the "Break when this exception type is shown" check box and the application went on functioning normally.
The implementation of Unity.WebAPI is not very different from the one mentioned in the question. I liked the version referred to by the OP as it ignores only ResultionFailedException and lets the rest propagate up the stack. Unity.WebAPI suppresses all exceptions. What I'd do is ignore errors that we know are safe to do so and log (or rethrow) others.
public object GetService(Type serviceType)
{
try
{
return container.Resolve(serviceType);
}
catch(ResolutionFailedException ex)
{
if (!(typeof(System.Web.Http.Tracing.ITraceWriter).IsAssignableFrom(serviceType))
|| typeof(System.Web.Http.Metadata.ModelMetadataProvider).IsAssignableFrom(serviceType)
//...
))
{
// log error
}
}
return null;
}
Normally, you don't need to with Unity.
I use this implementation for IDependencyResolver with unity, and I don't have to register or map other than my interfaces/services.
public class UnityDependencyInjectionResolver : Disposable, IDependencyResolver
{
protected IUnityContainer Container;
public UnityDependencyInjectionResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
Container = container;
}
public object GetService(Type serviceType)
{
try
{
return Container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public T GetService<T>()
{
try
{
var serviceType = typeof(T);
return (T)Container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return default(T);
}
}
public T GetService<T>(string name)
{
try
{
var serviceType = typeof (T);
return (T) Container.Resolve(serviceType, name);
}
catch (ResolutionFailedException)
{
return default(T);
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return Container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return new List<object>();
}
}
public IDependencyScope BeginScope()
{
var child = Container.CreateChildContainer();
return new UnityDependencyInjectionResolver(child);
}
protected override void DisposeManagedResources()
{
if (Container == null)
{
return;
}
Container.Dispose();
Container = null;
}
}
where Disposable is just a base class implements IDispoable.
Hope that helps.
As this seems to still get disputed, here's my version of the code...
/// <summary>
/// Specifies the Unity configuration for the main container.
/// </summary>
public class UnityConfig
{
private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
/// <summary>
/// Gets the configured Unity container.
/// </summary>
public static IUnityContainer GetConfiguredContainer()
{
return container.Value;
}
public static void RegisterTypes(IUnityContainer container)
{
// Keeping this separate allows easier unit testing
// Your type mappings here
}
}
and
[assembly: OwinStartup(typeof(UnityTest.BusinessLayer.Api.ApiStartup))]
namespace UnityTest.BusinessLayer.Api
{
public static HttpConfiguration Config { get; private set; }
public partial class ApiStartup
{
public void Configuration(IAppBuilder app)
{
// IoC
var container = UnityConfig.GetConfiguredContainer();
var resolver = new UnityHierarchicalDependencyResolver(container); // Gets us scoped resolution
app.UseDependencyResolverScope(resolver); // And for the OWIN
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
// NB Must be before WebApiConfig.Register
ConfigureAuth(app); //In App_Start ->Startup.Auth
// See http://stackoverflow.com/questions/33402654/web-api-with-owin-throws-objectdisposedexception-for-httpmessageinvoker
// and http://aspnetwebstack.codeplex.com/workitem/2091
#if SELFHOST
// WebAPI configuration
Config = new HttpConfiguration
{
DependencyResolver = resolver
};
WebApiConfig.Register(Config);
app.UseWebApi(Config);
#else
GlobalConfiguration.Configuration.DependencyResolver = resolver;
// http://stackoverflow.com/questions/19907226/asp-net-webapi-2-attribute-routing-not-working
// Needs to be before RouteConfig.RegisterRoutes(RouteTable.Routes);
GlobalConfiguration.Configure(WebApiConfig.Register);
Config = GlobalConfiguration.Configuration;
#endif
// Now do MVC configuration if appropriate
}
}
}
Finally bits are the extensions to use the scoped container in the Owin middleware as well as straight WebAPI
public static class AppBuilderExtensions
{
public static IAppBuilder UseDependencyResolverScope(this IAppBuilder app, IDependencyResolver resolver)
{
return app.Use<DependencyResolverScopeMiddleware>(resolver);
}
}
/// <summary>
/// Wraps middleware in a <see cref="IDependencyResolver"/> scope.
/// </summary>
public class DependencyResolverScopeMiddleware : OwinMiddleware
{
private readonly IDependencyResolver resolver;
public DependencyResolverScopeMiddleware(OwinMiddleware next, IDependencyResolver resolver) : base(next)
{
this.resolver = resolver;
}
public override async Task Invoke(IOwinContext context)
{
using (var scope = resolver.BeginScope())
{
context.SetDependencyScope(scope);
await Next.Invoke(context);
}
}
}
The rationale for this is the original MVC Work Item where we see
kichalla wrote Oct 27, 2014 at 4:34 PM
Yes...right...UseWebApi extension should be used only with
self-hosting scenarios...since we are all on the same page, I am
closing this issue as by-design...please let us know if you have any
more questions...
Thanks, Kiran
and
kichalla wrote Oct 29, 2014 at 5:28 PM
#thebothead: Thanks for finding this out!...right, this sample
shouldn't have been using Microsoft.AspNet.WebApi.Owin in IIS as it
was never intended to be used in that host...we will investigate the
issue further to see why this exception happens...but meanwhile you
could follow the approach mentioned in the sample that I provided
earlier...
Thanks, Kiran
From my own experience if you don't use this form of the code, it will work in debug etc but will not scale and start behaving strangely.
I has deleted dependencyResolver and this problem was solved
public static class UnityConfig
{
public static void Register(HttpConfiguration config)
{
var container = new UnityContainer();
// Your mappings here
config.DependencyResolver = null;
}
}
I'm trying to write an MSpec test that instantiates one of my controllers with all the correct Ninject bindings. How do I go about doing that? This is what I have so far:
[Subject(Concern.Initialization)]
public class when_permanent_employee_page_is_loaded_for_first_time
{
private static PermanentEmployeeController controller;
Establish context = () =>
{
NinjectControllerFactory controllerFactory = new NinjectControllerFactory();
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
controller = (PermanentEmployeeController)controllerFactory.CreateController(new RequestContext(), "PermanentEmployee");
};
private Because of = () => controller.Index();
private It should_load_all_available_jobs = () =>
{
var blah = controller;
var blah3 = 3;
};
It should_load_all_available_locations;
It should_load_all_available_departments;
}
In the above code I'm simply trying to see if I can instantiate my controller with all the Ninject bindings in tact. The NinjectControllerFactory class looks like this:
public class NinjectControllerFactory : DefaultControllerFactory
{
private IKernel kernel = new StandardKernel(new DefaultModule());
public IKernel Kernel
{
get
{
return kernel;
}
set
{
this.kernel = value;
}
}
protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
return null;
}
return (IController)kernel.Get(controllerType);
}
}
And the DefaultModule class like this:
public class DefaultModule : NinjectModule
{
/// <summary>
/// Performs the binding of interfaces to their respective implementations. 'Tis very cool.
/// </summary>
public override void Load()
{
// Data service bindings
Bind<IJobService>().To<JobServiceImpl>().InTransientScope();
Bind<IJobWsWrapper>().To<JobWsWrapperImpl>().InTransientScope();
// View model factory bindings
Bind<IPermanentEmployeeViewModelFactory>().To<PermanentEmployeeViewModelFactoryImpl>().InTransientScope();
}
}
So my question is: is there a way to specify the bindings of my Ninject module in my MSpec test and then have my instantiated controller use those bindings? I want to avoid instantiating my Controller like this: var controller = new Controller() since that doesn't allow me to test the Ninject bindings. I've also looked into the TestControllerBuilder class from the MvcContrib library but I haven't figured out how to instantiate controllers with Ninject bindings with it. Thanks for the help!
Ok I figured out how to initialize my controller along with the Ninject Bindings in my MSpec tests! Well I didn't figure it out. A coworker did but that's irrelevant now. Here is how it's done:
public class when_permanent_employee_page_is_loaded_for_first_time
{
private static Mock<IJobService> jobServiceMock;
private static Mock<IUtilsService> utilsServiceMock;
private static PermanentEmployeeController controller;
private static ContextMocks mocks;
private static IList<Job> jobs = new List<Job>();
private static IList<string> departments = new List<string>();
private static IList<string> locations = new List<string>();
private static PermanentEmployeeJobsViewModel viewModel;
Establish context = () =>
{
jobServiceMock = new Mock<IJobService>();
jobServiceMock.Setup(x => x.GetJobs(1)).Returns(jobs);
jobServiceMock.Setup(x => x.GetDepartmentsFromJobs(jobs)).Returns(departments);
jobServiceMock.Setup(x => x.GetLocationsFromJobs(jobs)).Returns(locations);
utilsServiceMock = new Mock<IUtilsService>();
var kernel = new StandardKernel(new DefaultModule());
kernel.Rebind<IJobService>().ToConstant(jobServiceMock.Object);
kernel.Rebind<IUtilsService>().ToConstant(utilsServiceMock.Object);
controller = kernel.Get<PermanentEmployeeController>();
mocks = new ContextMocks(controller);
};
Because of = () =>
{
PartialViewResult view = (PartialViewResult)controller.Index();
viewModel = (PermanentEmployeeJobsViewModel)view.ViewData.Model;
};
It should_load_all_available_jobs = () =>
{
jobServiceMock.Verify(x => x.GetJobs(1));
jobServiceMock.Verify(x => x.GetDepartmentsFromJobs(jobs));
jobServiceMock.Verify(x => x.GetLocationsFromJobs(jobs));
viewModel.Departments.ShouldEqual(departments);
};
It should_load_all_available_locations;
It should_load_all_available_departments;
}
Ok that's it :). Hopefully someone else can benefit from this answer. Special thanks to my coworker for figuring this out. You know who you are :D