C# WebApi DI not working - c#

Hello i need some assistance. I'm struggling on this second day and can't find a source of the problem. I'm working on web api with token authorization , identity and ninject.
This is my kernel :
public IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<AppContext>().ToSelf().InRequestScope();
kernel.Bind(x => { x.From(typeof(UserService).Assembly).SelectAllClasses().EndingWith("Service").BindDefaultInterface(); });
kernel.Bind(typeof(IUserStore<AppIdentityUser>)).To(typeof(UserStore<AppIdentityUser>)).InRequestScope()
.WithConstructorArgument("context", kernel.Get<AppContext>());
kernel.Bind(typeof(UserManager<AppIdentityUser>)).To(typeof(UserManager<AppIdentityUser>)).InRequestScope()
.WithConstructorArgument("store", kernel.Get<IUserStore<AppIdentityUser>>());
kernel.Bind(typeof(IRoleStore<IdentityRole, string>)).To(typeof(RoleStore<IdentityRole>)).InRequestScope().WithConstructorArgument("context", kernel.Get<AppContext>());
kernel.Bind(typeof(RoleManager<IdentityRole>)).To(typeof(RoleManager<IdentityRole>)).InRequestScope().WithConstructorArgument("store", kernel.Get<IRoleStore<IdentityRole, string>>());
kernel.Bind<IOAuthAuthorizationServerProvider>().To<AuthorizationServerProvider>();
kernel.Bind<IOAuthAuthorizationServerOptions>().To<MyOAuthAuthorizationServerOptions>();
return kernel;
}
This is my api controller :
public UsersController(IUserService userService)
{
this._userService = userService;
}
public IHttpActionResult Login()
{
//get user method
}
this is my service :
public UserService(UserManager<AppIdentityUser> userMenager, RoleManager<IdentityRole> roleManager)
{
this._userMenager = userMenager;
this._roleManager = roleManager;
}
public AppIdentityUser GetUser(string name, string password)
{
return _userMenager.Find(name, password); // here I recive error on second time
}
Problem is that this works only once. When i open application and perform one get action it works on the second time when i try after few seconds i get exception that Context in user Store is disposed. I suspect that it's problem with my ninject configuration but don't see any error.
Edit: this is my Owin Startup Class
public void Configuration(IAppBuilder app)
{
config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
config.EnableCors();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
var kernel = ConfigureNinject(app);
ConfigureOAuth(app, kernel);
config.DependencyResolver = new NinjectResolver(kernel);
//app.UseWebApi(config);
app.UseNinjectMiddleware(() => kernel);
app.UseNinjectWebApi(config);
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AutoMapperConfiguration.Configure();
}
public void ConfigureOAuth(IAppBuilder app, IKernel kernel)
{
app.UseOAuthBearerTokens(kernel.Get<IOAuthAuthorizationServerOptions>().GetOptions());
}

Related

Authenticated user is lost in web api owin middleware

I'm using owin middleware and Jwt Bearer Aurhentication alongside Autofac that help my Webapi to handle requests.
JwtBearerAuthentication middleware works fine and set HttpContext.Current.User.Identity.IsAuthenticated to true and it persist until pipeline reaches to webapi middleware , in my webapi authenticated user is lost
order of middlewares are as follows:
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
WebApiConfig.Register(config);
#region Autofac config
var container = AutofacWebapiConfig.Initialize(GlobalConfiguration.Configuration);
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
#endregion
#region RoutConfig
RouteConfig.RegisterRoutes(RouteTable.Routes);
#endregion
//Register middlewares
app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseJwtBearerAuthentication(new MyJwtAuthenticationOptions());
app.Use<RedirectUnAuthenticateRequestsMiddleware>();
app.Use<ReadBodyMiddleware>();
app.UseWebApi(config); //in this middleware authenticated user is lost
}
Here is my WebApiConfig class:
public static void Register(HttpConfiguration config)
{
// Owin auth
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter("Signature"));
GlobalConfiguration.Configuration.IncludeErrorDetailPolicy =
IncludeErrorDetailPolicy.Always;
// Web API routes
config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
config.MapHttpAttributeRoutes();
config.Services.Insert(typeof(ModelBinderProvider), 0,
new SimpleModelBinderProvider(typeof(DocumentModel), new FromFormDataBinding()));
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Have you any idea?
Update:
Inside my owin middleware after authentication middleware, IsAuthenticated is set to true
public override async Task Invoke(IOwinContext context)
{
var isAuth=context.Request.User.Identity.IsAuthenticated;//It is true as expected.
await Next.Invoke(context);
return;
}
but when it reaches to my controller
HttpContext.Current.User.Identity.IsAuthenticated;//It is false.
Problem was from this line in WebApiConfig class;
config.SuppressDefaultHostAuthentication();
When i commented,issue disappeared and authenticated user persisted in webapi.

Can't integrate autofac with both web api 2 and mvc

this thing takes one week from me
i have done many methods to find a solution
mvc fully integrated with autofac, but web api NO and NO! :-(
here is my codes:
AutofacDi
public static class AutofacDi
{
public static ValueTuple<IContainer, HttpConfiguration> Initialize()
{
var assembly = Assembly.GetExecutingAssembly();
var builder = new ContainerBuilder();
var config = GlobalConfiguration.Configuration;
builder.RegisterControllers(assembly);
builder.RegisterApiControllers(assembly).PropertiesAutowired();
builder.RegisterHttpRequestMessage(config);
builder.RegisterAssemblyModules(assembly);
builder.RegisterAssemblyTypes(assembly).PropertiesAutowired();
builder.RegisterFilterProvider();
builder.RegisterWebApiFilterProvider(config);
builder.RegisterModelBinders(assembly);
builder.RegisterWebApiModelBinderProvider();
builder.RegisterModelBinderProvider();
builder.RegisterModule<AutofacWebTypesModule>();
builder.RegisterSource(new ViewRegistrationSource());
builder.RegisterType<T4MVC.Dummy>().AsSelf();
builder.RegisterType<FoodDbContext>()
.As<IUnitOfWork>()
.InstancePerLifetimeScope();
builder.Register(context => (FoodDbContext)context.Resolve<IUnitOfWork>())
.As<FoodDbContext>()
.InstancePerLifetimeScope();
builder.RegisterType<ApplicationDbContext>().As<DbContext>().InstancePerLifetimeScope();
builder.RegisterType<UserStore<ApplicationUser>>().As<IUserStore<ApplicationUser>>();
builder.RegisterType<ApplicationUserManager>();
builder.RegisterType<ApplicationSignInManager>();
builder.Register(c => new IdentityFactoryOptions<ApplicationUserManager>()
{
DataProtectionProvider = new DpapiDataProtectionProvider("FoodBaMa")
});
builder.Register(c => HttpContext.Current.GetOwinContext().Authentication).InstancePerLifetimeScope();
builder.RegisterType<RoleStore<IdentityRole>>().As<IRoleStore<IdentityRole, string>>();
builder.RegisterAssemblyTypes(typeof(MvcApplication).Assembly)
.Where(t => t.Name.EndsWith("Service"))
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
return new ValueTuple<IContainer, HttpConfiguration>(container, config);
}
}
OWIN Startup
[assembly: OwinStartup(typeof(FoodBaMa.Startup))]
namespace FoodBaMa
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
var iOc = AutofacDi.Initialize();
app.UseAutofacMiddleware(iOc.Item1);
app.UseAutofacMvc();
app.UseWebApi(iOc.Item2);
app.UseAutofacWebApi(iOc.Item2);
WebApiConfig.Register(iOc.Item2);
app.UseCors(CorsOptions.AllowAll);
ConfigureAuth(app);
}
}
}
Global
public class MvcApplication : HttpApplication
{
protected void Application_Start()
{
RouteConfig.RegisterRoutes(RouteTable.Routes);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new RazorViewEngine());
ModelBinders.Binders.Add(typeof(string), new PersianModelBinder());
MvcHandler.DisableMvcResponseHeader = true;
DbInterception.Add(new ElmahEfInterceptor());
DbInterception.Add(new YeKeInterceptor());
GlobalConfiguration.Configuration.EnsureInitialized();
}
}
ApiController
[AutofacControllerConfiguration]
[WebApiCompress]
[RoutePrefix("api/v1")]
public class AppController : ApiController
{
private readonly IApiV1Service _apiService;
public AppController(
IApiV1Service apiService
)
{
_apiService = apiService;
}
[HttpPost]
[Route("app/mainview")]
public virtual async Task<IHttpActionResult> MainView([FromBody] Request model)
{
var Result = new Models.API.V1.App.MainView.Response { Status = CheckTokenEnum.Error };
try
{
if (ModelState.IsValid)
Result = await _apiService.MainView(model).ConfigureAwait(false);
}
catch (Exception ex)
{
ErrorLog.GetDefault(null).Log(new Error(ex));
}
return Json(Result, R8.Json.Setting);
}
}
WebApiConfig
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.JsonIntegration();
config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
config.MessageHandlers.Add(new CachingHandler(new InMemoryCacheStore()));
config.MessageHandlers.Add(new PreflightRequestsHandler());
config.Filters.Add(new ElmahHandleErrorApiAttribute());
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
RouteConfig
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//routes.IgnoreRoute("{*browserlink}", new { browserlink = #".*/arterySignalR/ping" });
routes.MapMvcAttributeRoutes();
AreaRegistration.RegisterAllAreas();
//routes.LowercaseUrls = true;
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional
},
namespaces: new[] { "FoodBaMa.Controllers" }
);
}
}
on each web api request, returns:
HTTP Error 404.0 - Not Found
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
Module: IIS Web Core
Notification: MapRequestHandler
Handler: StaticFile
Error Code: 0x80070002
It's a killing problem for me because it's two weeks that making my website application unusable.
i don't know what to do.
help me !!!
i fixed that issue by commenting:
builder.RegisterWebApiFilterProvider(config);
and
builder.RegisterHttpRequestMessage(config);
in AutofacDi
It appears you may have gotten past your issue, which I hope is true. There's a lot to digest in here, but I do see a common mistake in the very start with respect to OWIN integration and Web API as documented in the Autofac docs:
A common error in OWIN integration is use of the GlobalConfiguration.Configuration. In OWIN you create the configuration from scratch. You should not reference GlobalConfiguration.Configuration anywhere when using the OWIN integration.
You may run into additional/other challenges in your setup as it sits; if you do, try getting rid of the use of GlobalConfiguration.Configuration.

OAuth Bearer Token Not Working for WebApi

I have gone through a lot of docs but it seems my problem is strange.
I have configured Oauth but I am not able to get the bearer token back. whenever I hit api to get the token, I get 200 but nothing back in response(I am expecting bearer token). Below is the config:
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
OAuthAuthorizationServerOptions oAuthOptions = new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(20),
Provider = new ApplicationOAuthProvider()
};
app.UseOAuthAuthorizationServer(oAuthOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
{
Provider = new OAuthBearerAuthenticationProvider()
});
HttpConfiguration config = new HttpConfiguration();
//config.Filters.Add(new );
//config.MapHttpAttributeRoutes();
// There can be multiple exception loggers. (By default, no exception loggers are registered.)
//config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler());
WebApiConfig.Register(config);
//enable cors origin requests
app.UseCors(CorsOptions.AllowAll);
app.UseWebApi(config);
}
}
public static class WebApiConfig
{
/// <summary>
///
/// </summary>
/// <param name="config"></param>
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
config.MapHttpAttributeRoutes();
config.Filters.Add(new HostAuthenticationAttribute("bearer")); //added this
config.Filters.Add(new AuthorizeAttribute());
config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new { id = RouteParameter.Optional }
);
var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
}
public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
{
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var form = await context.Request.ReadFormAsync();
if (myvalidationexpression)
{
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Role, "AuthorizedUser"));
context.Validated(identity);
}
else
{
context.SetError("invalid_grant", "Provided username and password is incorrect");
}
}
}
Now when I launch the APi and hit /token, I get this as below:
API Request
I think that code you have written in WebApiConfig.cs to suppress host authentication and some other code is creating the issue.
I have a working example for bearer token generation in web API, which is working properly and generating token.
WebApiConfig.cs file code:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Startup.cs Code:
[assembly: OwinStartup(typeof(WebAPI.Startup))]
namespace WebAPI
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
ConfigureOAuth(app);
WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
}
public void ConfigureOAuth(IAppBuilder app)
{
OAuthAuthorizationServerOptions
OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(60),
Provider=new ApplicationOAuthProvider(),
//AuthenticationMode = AuthenticationMode.Active
};
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions {
Provider = new OAuthBearerAuthenticationProvider()
}
);
}
}
}
Controller to check authorization call after adding bearer token in the request.
public class TokenTestController : ApiController
{
[Authorize]
public IHttpActionResult Authorize()
{
return Ok("Authorized");
}
}
install the following package
Microsoft.Owin.Host.SystemWeb

Disabling OData V4 meta data and controllers at runtime

We have several modules in our software that ship as a single product. When a module is activated, those features become available. We would like our OData APIs to follow the same pattern. However I can't figure out how to make the $metadata ignore controllers for modules that have been disabled. Basically I want to determine what is available at any time instead of application start time.
We are using the following type of cod to register the routes:
static public void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
var builder = new ODataConventionModelBuilder();
builder.EntitySet<Module1Entity>("Module1Entities");
builder.EntitySet<Module2Entity>("Module2Entities");
config.MapODataServiceRoute("odata", "api", builder.GetEdmModel());
}
protected void Application_Start(object sender, EventArgs e)
{
GlobalConfiguration.Configure(Register);
}
So we only want Module1Entity to show up in the metadata if the module has been activated. We already have code to disable the associated controller when the module is deactivated.
Any ideas?
I ended up finding a solution:
static public void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
var builder = new ODataConventionModelBuilder();
if (IsModule1Enabled)
{
builder.EntitySet<Module1Entity>("Module1Entities");
{
if (IsModule2Enabled)
{
builder.EntitySet<Module2Entity>("Module2Entities");
}
var conventions = ODataRoutingConventions.CreateDefault();
conventions.Insert(0, new MyAttributeRoutingConvention("odata", config));
config.MapODataServiceRoute("odata", "api", builder.GetEdmModel(), new DefaultODataPathHandler(), conventions);
}
public class MyAttributeRoutingConvention : AttributeRoutingConvention
{
public MyAttributeRoutingConvention(string routeName, HttpConfiguration configuration) : base(routeName, configuration)
{
}
public override bool ShouldMapController(HttpControllerDescriptor controller)
{
if (controller.ControllerType == typeof(Module1EntitiesController))
{
return IsModule1Enabled;
}
if (controller.ControllerType == typeof(Module2EntitiesController))
{
return IsModule2Enabled;
}
return base.ShouldMapController(controller);
}
}
protected void Application_Start(object sender, EventArgs e)
{
GlobalConfiguration.Configure(Register);
}
Finally i found easier way.
This startup code ovveride OData $metadata path and return response forbidden.
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.EnableDependencyInjection();
endpoints.Select().Filter().OrderBy().Count().MaxTop(24);
endpoints.MapODataRoute("ODataRoute", "odata", GetEdmModel());
endpoints.MapGet("/odata/$metadata", async context =>
{
context.Response.StatusCode = 403;
await context.Response.WriteAsync("Forbidden!");
});
endpoints.MapGet("/", context =>
{
context.Response.Redirect("/swagger");
return Task.CompletedTask;
});
});

How to integrate WebApi 2 with Spring.Net

Im trying to integrate WebApi 2 with Spring.Net with not success. This is what i have tried:
public class MvcApplication : SpringMvcApplication
{
protected void Application_Start()
{
XmlConfigurator.Configure();
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
When is creating the SpringWebApiDependencyResolver instance, i'm getting this exception:
Error creating context 'spring.root': Request is not available in this context
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.DependencyResolver = new SpringWebApiDependencyResolver(ContextRegistry.GetContext());
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Im using Spring.Net 2.0.1
Now is working, the following line was not needed:
config.DependencyResolver = new SpringWebApiDependencyResolver(ContextRegistry.GetContext());
This is my implementation based on Spring.Net example:
public class MvcApplication : SpringMvcApplication
{
protected void Application_Start()
{
// More config...
GlobalConfiguration.Configure(WebApiConfig.Register);
// More config...
}
protected override System.Web.Http.Dependencies.IDependencyResolver BuildWebApiDependencyResolver()
{
var resolver = base.BuildWebApiDependencyResolver();
var springResolver = resolver as SpringWebApiDependencyResolver;
if (springResolver != null)
{
var resource = new AssemblyResource(
"assembly://assemblyName/namespace/ChildControllers.xml");
springResolver.AddChildApplicationContextConfigurationResource(resource);
}
return resolver;
}
}
I prefered to keep the common WebApi configuration:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
For registration of controllers in the IoC container is the same as MVC integration:
<object type="namespace.PrefixController, assemblyName" singleton="false" >
<property name="Dependency1" ref="Dependency1" />
</object>

Categories

Resources