如何在 Startup class 中使用或解析服务(或依赖项)
How to use or resolve a service(or dependency) in the Startup class
使用 IdentityServerBearerTokenAuthentication 中间件时,我想访问在我的 WebApi 配置中注册的服务。具体来说,我想调用一个服务来给我默认的用户 ID,并将其添加到请求中的 Claims 中。在下面的 OnValidateIdentity
lambda 示例代码中查看我的 TODO
。
//startup.cs
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = ConfigurationManager.AppSettings["Federation.IdentityServerPath"]
});
// azure functions will authenticate using Azure AD Tokens
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Audience = ConfigurationManager.AppSettings["ida:Audience"],
Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
Provider = new OAuthBearerAuthenticationProvider()
{
OnValidateIdentity = context =>
{
//add the account id claim if it's specified in the header
var accountIdString = context.Request.Headers["X-AccountId"];
if (!string.IsNullOrWhiteSpace(accountIdString) && Guid.TryParse(accountIdString, out var _))
{
context.Ticket.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, accountIdString));
}
else
{
//TODO: Need to pull the system user or admin user and jam that account id into NameIdentifier.
var systemDefaultId = "";
// How do I get a dependency from HttpContext or context.OwinContext?????
context.Ticket.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, systemDefaultId));
}
context.Ticket.Identity.AddClaim(new Claim("cl_aad_user", "true"));
return Task.FromResult<object>(null);
}
}
}
);
}
}
}
应用程序服务已使用 autofac 构建器模式注册。
例如
builder.RegisterType<AccountInfoService>().As<IAccountInfoService>().InstancePerRequest();
在全局调用的静态方法中 class (Global.asax).
// Global.asax.cs
...
private void Application_Start(object sender, EventArgs e)
{
// ... truncated code
// registers the services
GlobalConfiguration.Configure(WebApiConfig.Register);
}
我尝试从 HttpContext 中获取服务,但它总是解析为 null
。 (即 var db = (IOutcomesContext)HttpContext.Current.Request.RequestContext.HttpContext.GetService(typeof(IAccountService));
)
我也检查了 this answer,但我没有使用那个中间件。
这就是我注册依赖项的方式。
// WebApiConfig.cs
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
RegisterIoc(config);
}
private static void RegisterIoc(HttpConfiguration config)
{
ContainerBuilder builder = GetIocContainerBuilder();
builder.RegisterWebApiFilterProvider(config);
//all the external dependencies
builder.RegisterType<InstitutionRequestContext>().As<IInstitutionRequestContext>().InstancePerRequest();
Autofac.IContainer container = builder.Build();
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
internal static ContainerBuilder GetIocContainerBuilder()
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// ... truncated service list
builder.RegisterType<AccountInfoService>().As<IAccountInfoService>().InstancePerRequest();
return builder;
}
}
感谢您的帮助。
我最终通过将应用程序切换为使用 this answer 中所述的 app.UseAutofacMiddleware(container);
中间件解决了上述问题。
对于我的特定用例,它只涉及一些更改,特别是...
- 正在从全局配置文件中删除 autofac(例如 Global.asax)
- 正在将我的 WebApiConfig 更新为 return
Autofac.IContainer
- 向 Startup.Configure class 添加 3 个左右的方法调用,如 their documentation
中所述
使用 IdentityServerBearerTokenAuthentication 中间件时,我想访问在我的 WebApi 配置中注册的服务。具体来说,我想调用一个服务来给我默认的用户 ID,并将其添加到请求中的 Claims 中。在下面的 OnValidateIdentity
lambda 示例代码中查看我的 TODO
。
//startup.cs
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = ConfigurationManager.AppSettings["Federation.IdentityServerPath"]
});
// azure functions will authenticate using Azure AD Tokens
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Audience = ConfigurationManager.AppSettings["ida:Audience"],
Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
Provider = new OAuthBearerAuthenticationProvider()
{
OnValidateIdentity = context =>
{
//add the account id claim if it's specified in the header
var accountIdString = context.Request.Headers["X-AccountId"];
if (!string.IsNullOrWhiteSpace(accountIdString) && Guid.TryParse(accountIdString, out var _))
{
context.Ticket.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, accountIdString));
}
else
{
//TODO: Need to pull the system user or admin user and jam that account id into NameIdentifier.
var systemDefaultId = "";
// How do I get a dependency from HttpContext or context.OwinContext?????
context.Ticket.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, systemDefaultId));
}
context.Ticket.Identity.AddClaim(new Claim("cl_aad_user", "true"));
return Task.FromResult<object>(null);
}
}
}
);
}
}
}
应用程序服务已使用 autofac 构建器模式注册。
例如
builder.RegisterType<AccountInfoService>().As<IAccountInfoService>().InstancePerRequest();
在全局调用的静态方法中 class (Global.asax).
// Global.asax.cs
...
private void Application_Start(object sender, EventArgs e)
{
// ... truncated code
// registers the services
GlobalConfiguration.Configure(WebApiConfig.Register);
}
我尝试从 HttpContext 中获取服务,但它总是解析为 null
。 (即 var db = (IOutcomesContext)HttpContext.Current.Request.RequestContext.HttpContext.GetService(typeof(IAccountService));
)
我也检查了 this answer,但我没有使用那个中间件。
这就是我注册依赖项的方式。
// WebApiConfig.cs
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
RegisterIoc(config);
}
private static void RegisterIoc(HttpConfiguration config)
{
ContainerBuilder builder = GetIocContainerBuilder();
builder.RegisterWebApiFilterProvider(config);
//all the external dependencies
builder.RegisterType<InstitutionRequestContext>().As<IInstitutionRequestContext>().InstancePerRequest();
Autofac.IContainer container = builder.Build();
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
internal static ContainerBuilder GetIocContainerBuilder()
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// ... truncated service list
builder.RegisterType<AccountInfoService>().As<IAccountInfoService>().InstancePerRequest();
return builder;
}
}
感谢您的帮助。
我最终通过将应用程序切换为使用 this answer 中所述的 app.UseAutofacMiddleware(container);
中间件解决了上述问题。
对于我的特定用例,它只涉及一些更改,特别是...
- 正在从全局配置文件中删除 autofac(例如 Global.asax)
- 正在将我的 WebApiConfig 更新为 return
Autofac.IContainer
- 向 Startup.Configure class 添加 3 个左右的方法调用,如 their documentation 中所述