Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何从.NETCore中的单独类库中获取经过身份验证的用户_C#_Asp.net Mvc_Asp.net Core_.net Core_Asp.net Core Mvc - Fatal编程技术网

C# 如何从.NETCore中的单独类库中获取经过身份验证的用户

C# 如何从.NETCore中的单独类库中获取经过身份验证的用户,c#,asp.net-mvc,asp.net-core,.net-core,asp.net-core-mvc,C#,Asp.net Mvc,Asp.net Core,.net Core,Asp.net Core Mvc,我有一个引用.NET核心类库的MVC核心应用程序。所有的数据访问和业务逻辑都在类库中。如何从类库访问经过身份验证的用户 在过去使用.NET Framework时,您可以使用 string UserName = System.Web.HttpContext.Current.User.Identity.Name 从类库中的方法内部获取用户名。在.NETCore中,HttpContext似乎不再具有Current或User属性 这里有一个简单的用例。假设我有一个数据实体和服务,在将实体保存到数据库之

我有一个引用.NET核心类库的MVC核心应用程序。所有的数据访问和业务逻辑都在类库中。如何从类库访问经过身份验证的用户

在过去使用.NET Framework时,您可以使用

string UserName = System.Web.HttpContext.Current.User.Identity.Name
从类库中的方法内部获取用户名。在.NETCore中,
HttpContext
似乎不再具有
Current
User
属性

这里有一个简单的用例。假设我有一个数据实体和服务,在将实体保存到数据库之前用日期和用户名“标记”实体

这些将位于外部类库中:

public interface IAuditable{
    DateTime CreateDate{get;set;}
    string UserName{get;set;}
}

public class MyEntity:IAuditable{
    public int ID{get;set;}
    public string Name{get;set;}
    public string Information{get;set;}
}

public static class Auditor{
    public static IAuditable Stamp(IAuditable model){            
        model.CreateDate=DateTime.UtcNow;
        model.CreatedBy=System.Web.HttpContext.Current.User.Identity.Name;
        return model;
    }
}

public sealed class MyService:IDisposable{
    MyDb db=new MyDb();
    public async Task<int> Create(MyEntity model){
        Auditor.Stamp(model);
        db.MyEntities.Add(model);
        return await db.SaveAsync();
    }
    public void Dispose(){
        db.Dispose();
    }
}
但我还有另一个相同问题的版本:如何从类库中获取
IHttpContextAccessor
对象

我的大多数搜索结果只处理如何从MVC控制器方法中获取用户名的问题。在过去,我为每个服务的每个方法都传递了一个用户对象,但这需要很多额外的输入——我宁愿有一些我可以输入一次的东西(可能在启动时?),然后忘记它


我确实想要一些可以模拟单元测试的东西,但老实说,我认为在可以模拟的东西中包装System.Web.HttpContext.Current.User.Identity.Name非常简单。

这个版本中仍然存在同样的灵活性

插入
IHttpContextAccessor
,您就可以访问所需内容

重构静态的
审计员
,使其更具可注入性

public interface IAuditor {
    IAuditable Stamp(IAuditable model);
}

public class Auditor : IAuditor {
    private readonly IHttpContextAccessor accessor;

    public Auditor(IHttpContextAccessor accessor) {
        this.accessor = accessor;
    }

    public IAuditable Stamp(IAuditable model){            
        model.CreateDate = DateTime.UtcNow;
        model.CreatedBy = accessor.HttpContext.User?.Identity?.Name;
        return model;
    }
}
然后,服务将依赖于新的抽象

public interface IMyService : IDisposable {
    Task<int> Create(MyEntity model);
}

public sealed class MyService : IMyService {
    MyDb db = new MyDb();
    private readonly IAuditor auditor;

    public MyService(IAuditor auditor) {
        this.auditor = auditor;
    }

    public async Task<int> Create(MyEntity model) {
        auditor.Stamp(model);
        db.MyEntities.Add(model);
        return await db.SaveAsync();
    }

    public void Dispose() {
        db.Dispose();
    }
}
然后,您可以从根项目中调用启动

public void ConfigureServices(IServiceCollection services) {

    //...

    services.AddMyLibrary();

    //...
}

通过这些抽象和使用DI应用程序的部分是解耦的,可以单独测试。

只需插入
IHttpContextAccessor
,您就可以访问所需的内容。
public interface IMyService : IDisposable {
    Task<int> Create(MyEntity model);
}

public sealed class MyService : IMyService {
    MyDb db = new MyDb();
    private readonly IAuditor auditor;

    public MyService(IAuditor auditor) {
        this.auditor = auditor;
    }

    public async Task<int> Create(MyEntity model) {
        auditor.Stamp(model);
        db.MyEntities.Add(model);
        return await db.SaveAsync();
    }

    public void Dispose() {
        db.Dispose();
    }
}
public static IServiceCollection AddMyLibrary(this IServiceCollection services) {

    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    services.AddSingleton<IAuditor, Auditor>();  
    services.AddScoped<IMyService, MyService>();

    //...add other services as needed

    return services.  
}
public void ConfigureServices(IServiceCollection services) {

    //...

    services.AddMyLibrary();

    //...
}