Parameterless constructor issue within webapi application using owin and ninject - c#

I have a web api application in which I'd like to use Owin, Oauth and Ninject , So I have this configuration
Dependency injector
public class NinjectDependencyResolver : IDependencyResolver
{
private static IKernel kernel;
public NinjectDependencyResolver()
{
kernel = new StandardKernel();
// AddBindings();
}
public object GetService(Type serviceType)
{
return kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return kernel.GetAll(serviceType);
}
private static void AddBindings()
{
kernel.Bind<INotifier>().To<Notifier>();
kernel.Bind<IEventRepository>().To<EventRepository>();
kernel.Bind<ICrud<Config>>().To<CrudConfig>();
kernel.Bind<ICrud<Evenement>>().To<CrudEvent>();
kernel.Bind<IAccount>().To<Account>();
}
public static Lazy<IKernel> CreateKernel = new Lazy<IKernel>(() =>
{
//var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
AddBindings();
return kernel;
});
}
StartUp class
public partial class Startup
{
public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
public static string PublicClientId { get; private set; }
// For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
public static void ConfigureAuth(IAppBuilder app)
{
// Configure the db context and user manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Configure the application for OAuth based flow
PublicClientId = "self";
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
// In production mode set AllowInsecureHttp = false
AllowInsecureHttp = true
};
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);
//app.UseNinjectMiddleware(CreateKernel);
}
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseNinjectMiddleware(() => NinjectDependencyResolver.CreateKernel.Value);
app.UseNinjectWebApi(config);
ConfigureAuth(app);
}
}
Global.cs
protected void Application_Start()
{
DependencyResolver.SetResolver(new NinjectDependencyResolver());
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
I have this class also
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
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;
}
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
}
}
and I have this api controller :
public class AccountController : BaseController
{
#region ctors
public AccountController()
{
}
[Inject]
public AccountController(INotifier _notifierParam, IAccount _IAccount)
{
Notifier = _notifierParam;
Account = _IAccount;
}
#endregion
}
which derived from BaseController which is a class with no contructor.
the problem is when I make a call to service of the account controller I get this exception :
"Message":"An error has occurred.", "ExceptionMessage":"An error
occurred when trying to create a controller of type
'AccountController'. Make sure that the controller has a parameterless
public constructor.",
"ExceptionType":"System.InvalidOperationException", "StackTrace":" à
System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage
request, HttpControllerDescriptor controllerDescriptor, Type
controllerType)\r\n à
System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage
request)\r\n à
System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()",
"InnerException":{
"Message":"An error has occurred.",
"ExceptionMessage":"Error activating INotifier\r\nNo matching bindings are available, and the type is not
self-bindable.\r\nActivation path:\r\n 4) Injection of dependency
INotifier into parameter _notifierParam of constructor of type
AccountController\r\n 3) Injection of dependency AccountController
into parameter resolutionRoot of constructor of type NamedScope\r\n
2) Injection of dependency NamedScope into parameter resolutionRoot of
constructor of type OwinNinjectDependencyResolver\r\n 1) Request for
IDependencyResolver\r\n\r\nSuggestions:\r\n 1) Ensure that you have
defined a binding for INotifier.\r\n 2) If the binding was defined in
a module, ensure that the module has been loaded into the kernel.\r\n
3) Ensure you have not accidentally created more than one kernel.\r\n
4) If you are using constructor arguments, ensure that the parameter
name matches the constructors parameter name.\r\n 5) If you are using
automatic module loading, ensure the search path and filters are
correct.\r\n",
"ExceptionType":"Ninject.ActivationException",
"StackTrace":" à Ninject.KernelBase.Resolve(IRequest request)\r\n à Ninject.Planning.Targets.Target1.GetValue(Type
service, IContext parent)\r\n à
Ninject.Planning.Targets.Target1.ResolveWithin(IContext parent)\r\n
à Ninject.Activation.Providers.StandardProvider.GetValue(IContext
context, ITarget target)\r\n à
Ninject.Activation.Providers.StandardProvider.<>c__DisplayClass4.b__2(ITarget
target)\r\n à
System.Linq.Enumerable.WhereSelectArrayIterator2.MoveNext()\r\n à
System.Linq.Buffer1..ctor(IEnumerable1 source)\r\n à
System.Linq.Enumerable.ToArray[TSource](IEnumerable1 source)\r\n à
Ninject.Activation.Providers.StandardProvider.Create(IContext
context)\r\n à Ninject.Activation.Context.ResolveInternal(Object
scope)\r\n à Ninject.Activation.Context.Resolve()\r\n à
Ninject.KernelBase.<>c__DisplayClass15.b__f(IBinding
binding)\r\n à
System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext()\r\n
à System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable1
source)\r\n à
Ninject.Web.WebApi.NinjectDependencyScope.GetService(Type
serviceType)\r\n à
System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage
request, Type controllerType, Func`1& activator)\r\n à
System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage
request, HttpControllerDescriptor controllerDescriptor, Type
controllerType)"} }
So I need to know :
What is the reason of this error?
How can I fix it?

You are mixing Dependency Injection approaches. Your are using OWIN for setting the ninject middleware for Web API but then you are managing Web API outside of OWIN (using the IIS pipeline):
protected void Application_Start()
{
//..
GlobalConfiguration.Configure(WebApiConfig.Register);
//..
}
The second mistake is that you are creating multiple Kernels, and your exception message is warning you to avoid this:
Ensure you have not accidentally created more than one kernel
Start by refactoring your code. Manage Web API using only OWIN:
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseNinjectMiddleware(() => NinjectDependencyResolver.CreateKernel.Value);
ConfigureAuth(app);
app.UseNinjectWebApi(config);
}
and remove this line from Global.asax.cs:
GlobalConfiguration.Configure(WebApiConfig.Register);
Then ensure you are creating only one Kernel for the entire application lifetime. You should have only one static instance of the Kernel, and reference it from any other object that needs it.

Related

How IServiceProvider get injected by default?

we can access the IServiceProvider as:
public class ProductService
{
private readonly IProductRepository _productRepository;
public ProductService(IServiceProvider serviceProvider)
{
_productRepository = serviceProvider.GetRequiredService<IProductRepository>();
}
...
}
so it is obvious that .net registers IServiceProvider as a service by default, but I checked the source code:https://github.com/aspnet/Hosting/blob/master/src/Microsoft.Extensions.Hosting/HostBuilder.cs#L198
private void CreateServiceProvider() {
var services = new ServiceCollection();
services.AddSingleton(_hostingEnvironment);
services.AddSingleton(_hostBuilderContext);
services.AddSingleton(_appConfiguration);
services.AddSingleton<IApplicationLifetime, ApplicationLifetime>();
services.AddSingleton<IHostLifetime, ConsoleLifetime>();
services.AddSingleton<IHost, Host>();
services.AddOptions();
services.AddLogging();
foreach (var configureServicesAction in _configureServicesActions) {
configureServicesAction(_hostBuilderContext, services);
}
var containerBuilder = _serviceProviderFactory.CreateBuilder(services);
foreach (var containerAction in _configureContainerActions) {
containerAction.ConfigureContainer(_hostBuilderContext, containerBuilder);
}
_appServices = _serviceProviderFactory.CreateServiceProvider(containerBuilder); // _appServices is IServiceProvider
if (_appServices == null) {
throw new InvalidOperationException($"The IServiceProviderFactory returned a null IServiceProvider.");
}
}
so we can see that for example:
services.AddSingleton(_appConfiguration);
register IConfiguration (ConfigurationRoot instance under the hood), that's why we can use it in the startup.cs:
public class Startup {
public Startup(IConfiguration configuration) {
Configuration = configuration;
}
public IConfiguration Configuration { get; }
but I can't see the source code register _appServices(IServiceProvider) anywhere, there is no sth like services.AddSingleton(_appServices); in the source code
So how we still can access IServiceProvider automatically? or I must be missing somewhere, the source code does register IServiceProvider somewhere else?
When BuildServiceProvider extension is eventually invoked on the service collection
/// <summary>
/// Creates a <see cref="ServiceProvider"/> containing services from the provided <see cref="IServiceCollection"/>
/// optionally enabling scope validation.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> containing service descriptors.</param>
/// <param name="options">
/// Configures various service provider behaviors.
/// </param>
/// <returns>The <see cref="ServiceProvider"/>.</returns>
public static ServiceProvider BuildServiceProvider(this IServiceCollection services, ServiceProviderOptions options)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
return new ServiceProvider(services, options);
}
Source
The ServiceProvider instance, adds itself as a service.
internal ServiceProvider(ICollection<ServiceDescriptor> serviceDescriptors, ServiceProviderOptions options)
{
// note that Root needs to be set before calling GetEngine(), because the engine may need to access Root
Root = new ServiceProviderEngineScope(this, isRootScope: true);
_engine = GetEngine();
_createServiceAccessor = CreateServiceAccessor;
_realizedServices = new ConcurrentDictionary<Type, Func<ServiceProviderEngineScope, object>>();
CallSiteFactory = new CallSiteFactory(serviceDescriptors);
// The list of built in services that aren't part of the list of service descriptors
// keep this in sync with CallSiteFactory.IsService
CallSiteFactory.Add(typeof(IServiceProvider), new ServiceProviderCallSite());
CallSiteFactory.Add(typeof(IServiceScopeFactory), new ConstantCallSite(typeof(IServiceScopeFactory), Root));
CallSiteFactory.Add(typeof(IServiceProviderIsService), new ConstantCallSite(typeof(IServiceProviderIsService), CallSiteFactory));
if (options.ValidateScopes)
{
_callSiteValidator = new CallSiteValidator();
}
if (options.ValidateOnBuild)
{
List<Exception> exceptions = null;
foreach (ServiceDescriptor serviceDescriptor in serviceDescriptors)
{
try
{
ValidateService(serviceDescriptor);
}
catch (Exception e)
{
exceptions = exceptions ?? new List<Exception>();
exceptions.Add(e);
}
}
if (exceptions != null)
{
throw new AggregateException("Some services are not able to be constructed", exceptions.ToArray());
}
}
DependencyInjectionEventSource.Log.ServiceProviderBuilt(this);
}
Source

Can't get Unity Bootstrapper for MVC working

I have created a basic Web API project with a single controller and trying to use the Unity MVC Bootstrapper package from NuGet. Unfortunately when I try and visit the URL http://localhost/api/runtypes it throws the error
{"Message":"An error has occurred.","ExceptionMessage":"Type
'SE.FlexApplication.WebApi.Controllers.RunTypeController' does not
have a default
constructor","ExceptionType":"System.ArgumentException","StackTrace":"
at System.Linq.Expressions.Expression.New(Type type)\r\n at
System.Web.Http.Internal.TypeActivator.Create[TBase](Type
instanceType)\r\n at
System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage
request, Type controllerType, Func`1& activator)\r\n at
System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage
request, HttpControllerDescriptor controllerDescriptor, Type
controllerType)"}
My controller class
public class RunTypeController : ApiController
{
private readonly IStaticTypesRepository _staticTypesRepository;
private readonly IDataModelConverter _dataModelConverter;
private readonly IBusinessModelConverter _businessModelConverter;
public RunTypeController(IStaticTypesRepository staticTypesRepository, IDataModelConverter dataModelConverter, IBusinessModelConverter businessModelConverter)
{
_staticTypesRepository = staticTypesRepository;
_dataModelConverter = dataModelConverter;
_businessModelConverter = businessModelConverter;
}
public RunType[] Get()
{
return _staticTypesRepository.GetRunTypes().Select(r => _dataModelConverter.Convert(r)).ToArray();
}
public HttpResponseMessage Post(RunType type)
{
_staticTypesRepository.AddRunType(_businessModelConverter.Convert(type));
_staticTypesRepository.Save();
var response = Request.CreateResponse(System.Net.HttpStatusCode.Created, type);
return response;
}
}
And the Unity activator
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(SE.FlexApplication.WebApi.App_Start.UnityWebActivator), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(SE.FlexApplication.WebApi.App_Start.UnityWebActivator), "Shutdown")]
namespace SE.FlexApplication.WebApi.App_Start
{
/// <summary>Provides the bootstrapping for integrating Unity with ASP.NET MVC.</summary>
public static class UnityWebActivator
{
/// <summary>Integrates Unity when the application starts.</summary>
public static void Start()
{
var container = UnityConfig.GetConfiguredContainer();
FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container));
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
/// <summary>Disposes the Unity container when the application is shut down.</summary>
public static void Shutdown()
{
var container = UnityConfig.GetConfiguredContainer();
container.Dispose();
}
}
}
Unity Config class
public class UnityConfig
{
#region Unity Container
private static readonly 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;
}
#endregion
/// <summary>Registers the type mappings with the Unity container.</summary>
/// <param name="container">The unity container to configure.</param>
/// <remarks>There is no need to register concrete types such as controllers or API controllers (unless you want to
/// change the defaults), as Unity allows resolving a concrete type even if it was not previously registered.</remarks>
public static void RegisterTypes(IUnityContainer container)
{
try
{
//container.RegisterInstance<IUnitOfWork>(new ProdUnitOfWork());
container.RegisterType<IEventRepository, EventRepository>();
container.RegisterType<IModelRepository, ModelRepository>();
container.RegisterType<ISecurityRepository, SecurityRepository>();
container.RegisterType<IStaticTypesRepository, StaticTypesRepository>();
container.RegisterType<IDataModelConverter, DataToModelConverter>();
container.RegisterType<IBusinessModelConverter, ModelToDataConverter>();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
It seems like the Controller isn't picking up that it should be using the Unity Dependency resolver for constructor injection. I've followed all the steps on the tutorials online. Have I missed something basic?

Add claims with Owin Middleware

Is it possible with an Owin Middleware implementation to add claims prior to the execution of a Web API controller?
Created an OwinMiddleware implementation and added an identity:
var id = new ClaimsIdentity();
id.AddClaim(new Claim("Whatever", "is possible"));
context.Authentication.User.AddIdentity(id);
await Next.Invoke(context);
However, even this Invoke method call the identities are not updated (just the internal claims array). And the controller when executed of course never gets the new dummy claim.
Ideas?
There's already a class that can provide claims enrichment ClaimsAuthenticationManager, which you can extend so it handles your domain-specific claims, for example...
public class MyClaimsAuthenticationManager : ClaimsAuthenticationManager
{
public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
{
if (!incomingPrincipal.Identity.IsAuthenticated)
{
return base.Authenticate(resourceName, incomingPrincipal);
}
return AddApplicationClaims(incomingPrincipal);
}
private ClaimsPrincipal AddApplicationClaims(ClaimsPrincipal principal)
{
// TODO: Add custom claims here based on current principal.
return principal;
}
}
Next task is to provide appropriate middleware to invoke this. For my projects I've written the following classes...
/// <summary>
/// Middleware component to apply claims transformation to current context
/// </summary>
public class ClaimsTransformationMiddleware
{
private readonly Func<IDictionary<string, object>, Task> next;
private readonly IServiceProvider serviceProvider;
public ClaimsTransformationMiddleware(Func<IDictionary<string, object>, Task> next, IServiceProvider serviceProvider)
{
this.next = next;
this.serviceProvider = serviceProvider;
}
public async Task Invoke(IDictionary<string, object> env)
{
// Use Katana's OWIN abstractions
var context = new OwinContext(env);
if (context.Authentication != null && context.Authentication.User != null)
{
var manager = serviceProvider.GetService<ClaimsAuthenticationManager>();
context.Authentication.User = manager.Authenticate(context.Request.Uri.AbsoluteUri, context.Authentication.User);
}
await next(env);
}
}
And then a wiring extension...
public static class AppBuilderExtensions
{
/// <summary>
/// Add claims transformation using <see cref="ClaimsTransformationMiddleware" /> any depdendency resolution is done via IoC
/// </summary>
/// <param name="app"></param>
/// <param name="serviceProvider"></param>
/// <returns></returns>
public static IAppBuilder UseClaimsTransformation(this IAppBuilder app, IServiceProvider serviceProvider)
{
app.Use<ClaimsTransformationMiddleware>(serviceProvider);
return app;
}
}
I know this is service locator anti-pattern but using IServiceProvider is container neutral and seems to be the accepted way of putting dependencies into Owin middleware.
Last you need to wire this up in your Startup, example below presumes Unity and registering/exposing a IServiceLocator property...
// Owin config
app.UseClaimsTransformation(UnityConfig.ServiceLocator);
You may find useful inheriting from Authorizate Attribute and extending it to meet your requirements:
public class DemoAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext){
if (Authorize(actionContext)){
return;
}
HandleUnauthorizedRequest(actionContext);
}
protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext){
var challengeMessage = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized;
//Adding your code here
var id = new ClaimsIdentity();
id.AddClaim(new Claim("Whatever", "is possible"));
context.Authentication.User.AddIdentity(id);
challengeMessage.Headers.Add("WWW-Authenticate", "Basic");
throw new HttpResponseException(challengeMessage);
}
private bool Authorize(System.Web.Http.Controllers.HttpActionContext actionContext){
try{
var someCode = (from h in actionContext.Request.Headers where h.Key == "demo" select h.Value.First()).FirstOrDefault();
// or check for the claims identity property.
return someCode == "myCode";
}
catch (Exception){
return false;
}
}
}
And in your controller:
[DemoAuthorize]
public class ValuesController : ApiController{
Here is a link on other custom implemenation for WebApi Authorizations:
http://www.piotrwalat.net/basic-http-authentication-in-asp-net-web-api-using-membership-provider/
This is how I ended up adding a new claim in owin middleware, based on the OP's comment about hooking into UseOAuthBearerAuthentication. It uses IdentityServer3.AccessTokenValidation, which calls UseOAuthBearerAuthentication internally and passes the OAuthBearerAuthenticationProvider through to it.
using System.Security.Claims;
using System.Threading.Tasks;
using IdentityServer3.AccessTokenValidation;
using Owin;
using Microsoft.Owin.Security.OAuth;
//...
public void Configuration(IAppBuilder app)
{
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = "http://127.0.0.1/identityserver",
TokenProvider = new OAuthBearerAuthenticationProvider
{
OnValidateIdentity = AddClaim
}
});
}
private Task AddClaim(OAuthValidateIdentityContext context)
{
context.Ticket.Identity.AddClaim(new Claim("test", "123"));
return Task.CompletedTask;
}

Unable to register Api Controller using Simple Injector?

I have a WebApi that uses Simple Injector that was working perfectly fine, but i had to implement OAuth in to the project. Now i have done that and my ApiControllers give me an error like Simple Injector has now been setup correctly
I have my Start.cs file
public class Startup
{
public void Configuration(IAppBuilder app)
{
// Web API configuration and services
HttpConfiguration config = new HttpConfiguration();
Container container = SimpleInjectorConfig.Initialize(app);
ConfigureAuth(app, container);
WebApiConfig.Register(config);
app.UseWebApi(config);
}
public void ConfigureAuth(IAppBuilder app, Container container)
{
var OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = container.GetInstance<IOAuthAuthorizationServerProvider>()
};
// Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
In my SimpleInjectorConfig file i have
public class SimpleInjectorConfig
{
public static Container Initialize(IAppBuilder app)
{
var container = GetInitializeContainer(app);
container.Verify();
GlobalConfiguration.Configuration.DependencyResolver =
new SimpleInjectorWebApiDependencyResolver(container);
return container;
}
public static Container GetInitializeContainer(IAppBuilder app)
{
var container = new Container();
container.RegisterSingle<IAppBuilder>(app);
container.Register<IOAuthAuthorizationServerProvider,
ApiAuthorizationServerProvider>();
// myService
container.Register<IService, MyService>();
// myRepository
container.Register<IRepository, MyRepository>();
// This is an extension method from the integration package.
container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
return container;
}
}
public class ApiAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
private IService _service;
public ApiAuthorizationServerProvider(IService service)
{
_service = service;
}
public override async Task ValidateClientAuthentication(
OAuthValidateClientAuthenticationContext context)
{
context.Validated();
}
public override async Task GrantResourceOwnerCredentials(
OAuthGrantResourceOwnerCredentialsContext context)
{
context.OwinContext.Response.Headers
.Add("Access-Control-Allow-Origin", new[] { "*" });
User user = _service.Query(e => e.Email.Equals(context.UserName) &&
e.Password.Equals(context.Password)).FirstOrDefault();
if (user == null)
{
context.SetError("invalid_grant",
"The user name or password is incorrect.");
return;
}
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim("sub", context.UserName));
identity.AddClaim(new Claim("role", "user"));
context.Validated(identity);
}
}
Now my project builds fine, but i cannot test if OAuth is working yet, because i cannot connect to my ApiController. I have not added the [Authorize] tag to the Controller yet, so i should be able to access it.
Here is my controller
public class MyController : ApiController
{
private IService _service;
public MyController(IService service)
{
_service = service;
}
public IHttpActionResult Get()
{
// get all entities here via service
return Ok(list);
}
}
The error message i get says
An error occurred when trying to create a controller of type
'MyController'. Make sure that the controller has a parameterless
public constructor.
I thought this would be registered via
container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
In .NET Core add:
// Sets up the basic configuration that for integrating Simple Injector with
// ASP.NET Core by setting the DefaultScopedLifestyle, and setting up auto
// cross wiring.
services.AddSimpleInjector(_container, options =>
{
// AddAspNetCore() wraps web requests in a Simple Injector scope and
// allows request-scoped framework services to be resolved.
options.AddAspNetCore()
.AddControllerActivation();
});
via https://simpleinjector.readthedocs.io/en/latest/aspnetintegration.html

MVC5 and Ninject:Parameterless constructor error

In MVC 5 we get this account controller that looks like this.
public class AccountController : Controller
{
public AccountController()
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new DatePickerDbContext())))
{
}
public AccountController(UserManager<ApplicationUser> userManager)
{
UserManager = userManager;
}
}
I installed Ninject to handle my dependency injection. I have two repositories, that I want to use in my AccountController
and the code now looks like this
public class AccountController : Controller
{
private readonly ILicenserepository _licenserepository;
private readonly IUserRepository _userRepository;
public AccountController(ILicenserepository licenserepository, IUserRepository userRepository)
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new DatePickerDbContext())))
{
_licenserepository = licenserepository;
_userRepository = userRepository;
}
public AccountController(UserManager<ApplicationUser> userManager)
{
UserManager = userManager;
}
}
in ninject.web.common this is what i've done
private static void RegisterServices(IKernel kernel)
{
kernel.Bind(typeof (ILicenserepository)).To(typeof (Licenserepository));
kernel.Bind(typeof (IUserRepository)).To(typeof (UserRepository));
}
but when I run the application i get the error on browser that says no parametereless constructor found. And if i create parameter less constructor my repositories doesn't get instantiated. So wherever i called the method from repository the value is null.
How can I solve this problem? Or make MVC or Ninject know which constructor to call?
You need a DependencyResolver registered in Global.asax.cs
Registration would look something like this:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
RegisterDependencyResolver();
}
private void RegisterDependencyResolver()
{
var kernel = new StandardKernel();
// you may need to configure your container here?
RegisterServices(kernel);
DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
}
And the DependencyResolver
public class NinjectDependencyResolver : IDependencyResolver
{
private readonly IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
{
this.kernel = kernel;
}
public object GetService(Type serviceType)
{
return this.kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return this.kernel.GetAll(serviceType);
}
catch (Exception)
{
return new List<object>();
}
}
}
This is an update:
If your are using MVC5 and WebAPI 2 then all you need to do is use NuGet Manager and add NinjectMVC5 and NinjectWebApi2 into your project. Then the error goes away. (Using Visual Studio 2013)
Cheers
I just got this working without issue using .NET MVC 5 and Ninject 3.3.4.
Steps Taken:
Install Ninject 3.3.4
Install Ninject.Web.Common 3.3.1
Install Ninject.Web.Common.WebHost 3.3.1
Install Ninject.MVC5 3.3.0 (for use with an MVC Controller)
(Optional) Api Controller Steps
Install Ninject.Web.WebApi 3.3.0 (for use with an api ApiController)
Install Ninject.Web.WebApi.WebHost (for use with an ApiController)
The important distinction here is whether your project uses Api Controllers or Mvc Controllers. If you are unfamiliar with the difference please check out the below post:
Difference between ApiController and Controller in ASP.NET MVC.
Note: I did not have to do any extra configuration to my Ninject.Web.Common.cs file. Below is my configuration omitting my bindings
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(YourProject.Web.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(YourProject.Web.App_Start.NinjectWebCommon), "Stop")]
namespace YourProject.Web.App_Start
{
using System;
using System.Web;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
using Ninject.Web.Common.WebHost;
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
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;
}
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
// Common
// Repositories
// Services
// Factories
// Misc
}
}
}

Categories