Asp.net core 如何直接从ConfigureServices方法注入HttpContextAccessor
我的目标是根据我将要处理的环境设置用户名字符串,该字符串必须是: 开发和登台环境的任意字符串 生产中的HttpContext.User.Identity.Name。 这是因为我必须能够模拟不同类型的用户,我通过使用此用户名字符串作为参数在自定义的UserIdentity实现上调用FindByIdAsync方法来实现这一点,如下所示:Asp.net core 如何直接从ConfigureServices方法注入HttpContextAccessor,asp.net-core,dependency-injection,Asp.net Core,Dependency Injection,我的目标是根据我将要处理的环境设置用户名字符串,该字符串必须是: 开发和登台环境的任意字符串 生产中的HttpContext.User.Identity.Name。 这是因为我必须能够模拟不同类型的用户,我通过使用此用户名字符串作为参数在自定义的UserIdentity实现上调用FindByIdAsync方法来实现这一点,如下所示: public class HomeController : Controller { UserManager<AppUser> userMana
public class HomeController : Controller
{
UserManager<AppUser> userManager;
AppUser connectedUser;
public HomeController(UserManager<AppUser> usrMgr, IContextUser ctxUser)
{
connectedUser = usrMgr.FindByNameAsync(ctxUser.ContextUserId).Result;
}
}
而生产环境配置文件没有此密钥
我创建了一个简单的界面
public interface IContextUser
{
public string ContextUserId { get; }
}
及其实施:
public class ContextUser : IContextUser
{
string contextUser;
IHttpContextAccessor contextAccessor;
public ContextUser(IHttpContextAccessor ctxAccessor, string ctxUser = null)
{
contextUser = ctxUser;
contextAccessor = ctxAccessor;
}
public string ContextUserId => contextUser ?? contextAccessor.HttpContext.User.Identity.Name;
}
现在,我只想在Startup类中配置ConfigureServices方法:
但它需要一个IHttpContextAccessor对象,该对象在应用程序的这个阶段似乎不可用。如何解决此问题?HttpContextAccessor在封面下使用静态AsyncLocal属性,这意味着任何HttpContextAccessor实现都将访问相同的数据。这意味着您可以简单地执行以下操作:
services.AddSingletonc=>newcontexternewhttpcontextaccessor,ctxUser;
//别忘了叫这个;否则,HttpContext属性将被删除
//生产时为空。
services.AddHttpContextAccessor;
如果您发现这一点过于含蓄,或者HttpContextAccessor实现不会在将来中断,您还可以执行以下操作:
var访问器=新的HttpContextAccessor;
services.addSingleton访问器;
services.AddSingletonc=>新上下文Accessor,ctxUser;
或者,您可以从ServiceCollection类中取出已注册的实例:
services.AddHttpContextAccessor;
var accessor=IHttpContextAccessorservices.Last
s=>s.ServiceType==TypeOfHittpContextAccessor.ImplementationInstance;
services.AddSingletonc=>新上下文Accessor,ctxUser;
然而,我发现一个更令人愉快的解决方案,特别是从设计的角度来看,就是拆分ContextUser类;它目前似乎实施了两种不同的解决方案。您可以拆分这些:
公共密封类HttpContextUser:IContextser
{
专用只读IHttpContextAccessor访问器;
公共HttpContextSerieHttpContextAccessor访问器=>
this.accessor=accessor??抛出新参数NullExceptionAccessor;
公共字符串contextSerID=>this.accessor.HttpContext.User.Identity.Name;
}
公共密封类FixedContextUser:IContextUser
{
public FixedContextSerString用户ID=>
this.contextSerid=userId??抛出新的ArgumentNullExceptionuserId;
公共字符串上下文ID{get;}
}
现在,根据您运行的环境,您可以注册其中一个:
公共无效配置服务服务服务收集服务
{
services.AddHttpContextAccessor;
如果这是.Configuration.IsProduction
{
services.AddSingleton;
}
其他的
{
字符串ctxUser=Configuration[数据:ConnectedUser];
services.addSingleTonew FixedContextUserctxUser;
}
}
HttpContextAccessor在封面下使用静态AsyncLocal属性,这意味着任何HttpContextAccessor实现都将访问相同的数据。这意味着您可以简单地执行以下操作:
services.AddSingletonc=>newcontexternewhttpcontextaccessor,ctxUser;
//别忘了叫这个;否则,HttpContext属性将被删除
//生产时为空。
services.AddHttpContextAccessor;
如果您发现这一点过于含蓄,或者HttpContextAccessor实现不会在将来中断,您还可以执行以下操作:
var访问器=新的HttpContextAccessor;
services.addSingleton访问器;
services.AddSingletonc=>新上下文Accessor,ctxUser;
或者,您可以从ServiceCollection类中取出已注册的实例:
services.AddHttpContextAccessor;
var accessor=IHttpContextAccessorservices.Last
s=>s.ServiceType==TypeOfHittpContextAccessor.ImplementationInstance;
services.AddSingletonc=>新上下文Accessor,ctxUser;
然而,我发现一个更令人愉快的解决方案,特别是从设计的角度来看,就是拆分ContextUser类;它目前似乎实施了两种不同的解决方案。您可以拆分这些:
公共密封类HttpContextUser:IContextser
{
专用只读IHttpContextAccessor访问器;
公共HttpContextSerieHttpContextAccessor访问器=>
this.accessor=accessor??抛出新参数NullExceptionAccessor;
公共字符串contextSerID=>this.accessor.HttpContext.User.Identity.Name;
}
公共密封类FixedContextUser:IContextUser
{
public FixedContextSerString用户ID=>
this.contextSerid=userId??抛出新的ArgumentNullExceptionuserId;
公共字符串上下文ID{get;}
}
现在,根据您运行的环境,您可以注册其中一个:
公共无效配置服务服务服务收集服务
{
services.AddHttpContextAccessor;
如果这是.Configuration.IsProduction
{
services.AddSingleton;
}
其他的
{
字符串ctxUser=Configuration[数据:ConnectedUser];
services.addSingleTonew FixedContextUserctxUser;
}
}
我非常喜欢您分割ContextUser类的替代解决方案,我就是这么做的。谢谢。我非常喜欢你的拆分ContextUser类的替代解决方案,我就是这么做的。谢谢
public class ContextUser : IContextUser
{
string contextUser;
IHttpContextAccessor contextAccessor;
public ContextUser(IHttpContextAccessor ctxAccessor, string ctxUser = null)
{
contextUser = ctxUser;
contextAccessor = ctxAccessor;
}
public string ContextUserId => contextUser ?? contextAccessor.HttpContext.User.Identity.Name;
}
public void ConfigureServices(IServiceCollection services)
{
// --- add other services --- //
string ctxUser = Configuration["Data:ConnectedUser"];
services.AddSingleton(service => new ContextUser( ??? , ctxUser ));
}