Cannot auth or inject dependency with webapi, oauth, owin and ninject - asp.net-web-api

I have the following startup code
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
var kernel = NinjectConfig.CreateKernel();
app.UseNinjectMiddleware(() => kernel);
app.UseNinjectWebApi(GlobalConfiguration.Configuration);
OAuthConfig.Configure(app, kernel);
WebApiConfig.Register(config);
app.UseWebApi(config);
}
with this I can authorize without problems but I cannot inject dependency it throws
An error occurred when trying to create a controller of type 'DummyController'. Make sure that the controller has a parameterless public constructor
if I use this setup in the startup method
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
var kernel = NinjectConfig.CreateKernel();
app.UseNinjectMiddleware(() => kernel);
app.UseNinjectWebApi(config); //THIS LINE CHANGED
OAuthConfig.Configure(app, kernel);
WebApiConfig.Register(config);
//app.UseWebApi(config);
}
the authorization fails, but if I remove the authorization attribute from the controller de dependency injection works
What am I missing in the configuration?

The right config
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
var kernel = NinjectConfig.CreateKernel();
app.UseNinjectMiddleware(() => kernel);
OAuthConfig.Configure(app, kernel);
WebApiConfig.Register(config);
app.UseNinjectWebApi(config);
}
Just call UseNinjectWebApi at the end of the Configuration this method calls UseWebApi, now is all okay

Related

owin map extension return 404

I tried to implement a middleware just for my web API actions, so i found Map that is a extension method of IAppBuilder inerface. i checked katana source code [1], this method return an IAppBuilder same as Use method.
but in owin/WebAPI i don't know why controllers dose not resolve after mapping?
its clear after invoking next middleware, owin should run next middleware, but after mapping it seems there is no next middleware, where is my mistake?
StartUp:
public void Configuration(IAppBuilder app)
{
ConfigureOAuth(app);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app = app.Map("/api", application => {
ConfigurationAPI(application);
});
app.Use<ExceptionMiddleware>();
//app.UseWebApi(config);
}
public void ConfigurationAPI(IAppBuilder app)
{
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
FilterConfig.RegisterHttpFilters(GlobalConfiguration.Configuration.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
SimpleInjectorBootstrapper.Initialize();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(SharedLayer.Core.CoreObject.container));
config.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(SharedLayer.Core.CoreObject.container);
app = app.Use<ExceptionMiddleware>();
app = app.Use<AuthenticateMiddleware>();
app.UseWebApi(config);
}
but when I add following run block, all requests return "test"!!
app.Run(async context =>
{
await context.Response.WriteAsync("test");
});
app.UseWebApi(config);
Do your route definitions include the /api segment? Map removes that from the path for it's branch of the pipeline (ConfigurationAPI).

Integration Test - WebApi - in memory hosting returning 404 error

We are creating a web api and I am trying to setup integration testing for the web api, so we don't have to use PostMan to verify if it's working.
When I run the webapi and use PostMan, I am getting the expected result. However, when I try to use in memory hosting and run the webapi for integration testing, it is always returning 404.
Using XUnit - the test class is below.
public class UnitTest1
{
private readonly TestServer _server;
private readonly HttpClient _client;
public UnitTest1()
{
var host = new WebHostBuilder()
.UseStartup<Startup>();
this._server = new TestServer(host);
this._client = _server.CreateClient();
}
[Fact]
public async void TestMethod1()
{
var response = await this._client.GetAsync("api/objects");
response.EnsureSuccessStatusCode();
var responseString = await response.Content.ReadAsStringAsync();
List<obj> result = JsonConvert.DeserializeObject<IEnumerable<obj>>(responseString).ToList();
Assert.Equal(3, result.Count);
}
}
The startup class:
public class Startup
{
public void Configuration(IAppBuilder app)
{
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=316888
GlobalConfiguration.Configure(WebApiConfig.Register);
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
public void Configure()
{
var config = new HttpConfiguration();
WebApiConfig.Register(config);
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
}
I had to add the configure method in the startup, otherwise test would fail while the class was being initialized.
You can try something like :
using (HttpConfiguration config = new HttpConfiguration())
{
config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
WebApiConfig.Register(config); // If Needed
FilterConfig.RegisterGlobalFilters(GlobalConfiguration.Configuration.Filters); // If Needed
If need more details, you can find here:
https://stackoverflow.com/a/49202654/2928038

ObjectDisposedException when trying to use Dependency Injection with CreatePerOwinContext

I am trying to use DI with the the OWIN CreatePerOwinContext extension. I am also using the OAuthAuthorizationServerProvider. Inside the OAuthAuthorizationServerProvider I am trying to get and instance of my user manager using: OAuthGrantResourceOwnerCredentialsContext.OwinContext.GetUserManager.
Start UP file:
public void Configuration(IAppBuilder app)
{
DataProtectionProvider = app.GetDataProtectionProvider();
var config = new HttpConfiguration {DependencyResolver = new UnityDependencyResolver(UnityRegistrations.GetConfiguredContainer())};
WebApiConfig.Register(config);
//Allow Cross Domain Calls
app.UseCors(CorsOptions.AllowAll);
//I verified that my AppUserManager is getting constructed properly
//var manager = UnityRegistrations.GetConfiguredContainer().Resolve<AppUserManager>();
app.CreatePerOwinContext(() => UnityRegistrations.GetConfiguredContainer().Resolve<AppUserManager>());
OAuthOptions = new OAuthAuthorizationServerOptions
{
// Point at which the Bearer token middleware will be mounted
TokenEndpointPath = new PathString("/token"),
// An implementation of the OAuthAuthorizationServerProvider which the middleware
// will use for determining whether a user should be authenticated or not
Provider = new OAuthProvider("self"),
// How long a bearer token should be valid for
AccessTokenExpireTimeSpan = TimeSpan.FromHours(24),
// Allows authentication over HTTP instead of forcing HTTPS
AllowInsecureHttp = true
};
app.UseOAuthBearerTokens(OAuthOptions);
app.UseWebApi(config);
}
This is the GetConfiguredContainer method :
private static readonly Lazy<IUnityContainer> Container = new
public static IUnityContainer GetConfiguredContainer()
{
return Container.Value;
}
Lazy<IUnityContainer>(() => {
var container = new UnityContainer();
//Registers the Types
Register(container);
return container;
});
Inside the GrantResourceOwnerCredentials of my OAuthAuthorizationServerProvider implementation I try to get an instance of the AppUserManager:
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
//Inspecting the _userManager I see the ObjectDisposedException
_userManager = context.OwinContext.GetUserManager<AppUserManager>();
var user = await _userManager.FindByNameAsync(context.UserName);
}
Is what I am trying to do even possible with Web API and Owin?
I made a rookie mistake. For some reason on my AppUserManager Unity registration I added a HierarchicalLifetimeManager. This was, obviously, a mistake. It was disposing prematurely. My DbContext also has a HierarchicalLifetimeManager on its registration. Hours of fun!
WRONG
_unityContainer.RegisterType<AppUserManager>(new HierarchicalLifetimeManager());
Correct
_unityContainer.RegisterType<AppUserManager>();

Autofac not resolving constructor parameter for WebAPI2 controllers

I'm trying to use Autofac for DI container for an Asp.Net MVCApplication with WebApi2 and OWIN. My global.asax.cs has nothing in the Application_Start(). My startup.cs has the following Configuration:
public void Configuration(IAppBuilder app)
{
DependencyInjectionConfig.Configure(app);
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
And DependencyInjectionConfig.Configure is:
public static void Configure(IAppBuilder app)
{
var config = new HttpConfiguration(); //this means webapi controllers don't use DI container
//var config = GlobalConfiguration.Configuration; //this makes MVC view controllers fail to do anything
var builder = new ContainerBuilder();
var assm = Assembly.GetExecutingAssembly();
//MVC and WebAPI Controllers
builder.RegisterControllers(assm);
builder.RegisterApiControllers(assm);
WebApiConfig.Register(config);
//Model Binders
builder.RegisterModelBinders(assm);
builder.RegisterModelBinderProvider();
//Modules
builder.RegisterModule<AutofacWebTypesModule>();
//MVC Views
builder.RegisterSource(new ViewRegistrationSource());
//MVC and WebAPI Filters
builder.RegisterFilterProvider();
builder.RegisterWebApiFilterProvider(config);
//Finally, Any custom registrations
RegisterComponents(builder, assm);
/* My items show in the builder as expected at this point */
//build the container
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
//Special OWIN bits
app.UseAutofacMiddleware(container);
app.UseAutofacMvc();
app.UseAutofacWebApi(config);
app.UseWebApi(config);
}
My problem is that Autofac does not seem do any parameter resolution regardless of if I use var config = new HttpConfiguration(); or var config = GlobalConfiguration.Configuration;. bonus, if I use GlobalConfiguration.Configuration MVC controllers for views completely fails.
The ApiController is pretty straight-forward:
public class MessagesController : ApiController
{
private IMesageHandler MessageHandler {get; set;}
public MessagesController(IMessageHandler messageHandler)
{
this.MessageHandler = messageHandler;
}
[HttpGet]
public string Get()
{
return "Hello World";
}
}
The exception is that it can't find a parameterless constructor (because the Autofac container appears to be napping).

Structure Map parameterless constructor error

I am trying to set up structure map ver 3.0.5.0 with Web API 2.
I have followed this implementation: Configuring dependency injection with ASP.NET Web API 2.1
However, I am getting this error when doing a get against my ComplexesController:
An error occurred when trying to create a controller of type 'ComplexesController'. Make sure that the controller has a parameterless public constructor.
Can anyone see what is wrong with my structuremap config? The Create method never gets called.
This is my implementation:
public class StructureMapControllerActivator : IHttpControllerActivator
{
private readonly IContainer _container;
public StructureMapControllerActivator(IContainer container)
{
if (container == null) throw new ArgumentNullException("container");
_container = container;
}
public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
try
{
var scopedContainer = _container.GetNestedContainer();
scopedContainer.Inject(typeof(HttpRequestMessage), request);
request.RegisterForDispose(scopedContainer);
return (IHttpController)scopedContainer.GetInstance(controllerType);
}
catch (Exception e)
{
// TODO : Logging
throw e;
}
}
}
This method is in my startup...
public void InitializeContainer()
{
// STRUCTURE MAP
Container container = new Container();
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new StructureMapControllerActivator(container));
container.Configure(x => x.For<IForumRepository>().Use<ForumRepository>());
container.Configure(x => x.For<IComplexRepository>().Use<ComplexRepository>());
}
.. and this is the controller:
public class ComplexesController : ApiController
{
private IComplexRepository _repo;
public ComplexesController(IComplexRepository repo)
{
_repo = repo;
}
// GET: api/Complexes
public IList<Complex> GetComplexes()
{
var complexes = _repo.GetList();
return complexes;
}
...
My full Startup class
[assembly: OwinStartup(typeof(AngularJSAuthentication.API.Startup))]
namespace AngularJSAuthentication.API
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config);
}
}
}
The problem here is that you are registering your service activator with a GlobalConfiguration object and not your HttpConfiguration object. In this scenario The GlobalConfiguration object is never used as it is replaced by the HttpConfiguration object. In order to solve your issue you should replace your InitializeContainer() method with the following.
public void InitializeContainer(HttpConfiguration config)
    {
        // STRUCTURE MAP
        Container container = new Container();
        config.Services.Replace(typeof(IHttpControllerActivator), new StructureMapControllerActivator(container));
        container.Configure(x => x.For<IForumRepository>().Use<ForumRepository>());
        container.Configure(x => x.For<IComplexRepository>().Use<ComplexRepository>());        
    }
you should then pass the HttpConfiguration object from your Startup class to the new InitializeContainer() method.
Hope this helps.
-B
I am trying to gain a solid understanding of the complete lifecycle. I think my setup may be slightly different to the above. Here is what worked for me.
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
var container = IocConfig.Setup();
// Allow a controller to be declared without a parameterless constructor
config.DependencyResolver = new DependencyResolver(container);
config.Services.Add( typeof(IExceptionLogger), new GlobalExceptionLogger( container.GetInstance<ILoggingService>()));
// Web API routes
config.MapHttpAttributeRoutes();
// Setup Authentication
ConfigureOAuth(app, container);
var corsOptions = CorsOptions.AllowAll;
app.UseCors(corsOptions);
// Add ASP.Net Web API to OWIN pipeline
app.UseWebApi(config);
}
}
It worked after I added this line:
// Allow a controller to be declared without a parameterless constructor
config.DependencyResolver = new DependencyResolver(container);
You have to get that my var container loads from a static class called IocConfig with a static Setup method. This is where the interfaces are mapped to their concrete implementations.
Also, you can probably ignore the GlobalExceptionLogger line if you want to use my complete example.

Resources