c# - ServiceStack:访问InsertFilter和UpdateFilter中的 session

标签 c# servicestack ormlite-servicestack

我有一个 C#.net 应用程序,我正在其中写入 SQL Server 数据库。 SQL Server 表都有公共(public)记录管理列(DateCreated、DateLastUpdated、CreatedUserId 等),我希望将这些字段的总体抽象到 InsertFilter 和 UpdateFilter 中。

这是 AppHost 的配置方法的简化版本..

public override void Configure(Container container)
{
    ICacheClient CacheClient = new MemoryCacheClient();
    container.Register(CacheClient);

    var connectionString = ConfigurationManager.ConnectionStrings["mydb"].ConnectionString;

    container.Register<IDbConnectionFactory>(c => new OrmLiteConnectionFactory(connectionString, SqlServerDialect.Provider));

    container.Register<IUserAuthRepository>(c => new OrmLiteAuthRepository(c.Resolve<IDbConnectionFactory>()));
    var authRepo = (OrmLiteAuthRepository)container.Resolve<IUserAuthRepository>();


    OrmLiteConfig.InsertFilter = (dbCmd, row) =>
    {
        var userSession = SessionFeature.GetOrCreateSession<AuthUserSession>(CacheClient);
        var recordManagementRow = row as IRecordManagement;
        if (recordManagementRow != null)
        {
            recordManagementRow.DateCreated = recordManagementRow.DateLastUpdated = DateTime.UtcNow;
            if (userSession != null)
                recordManagementRow.CreatedUserId = recordManagementRow.LastUpdatedUserId = userSession.Id.ToInt();
        }
    };
}

执行时,我在 OrmLiteConfig.InsertFilter 委托(delegate)的第一行出现以下异常。对于如何检索当前用户 session ID 以插入数据库,有人有更好的想法吗?

An exception of type 'System.NotImplementedException' occurred in ServiceStack.dll but was not handled in user code

Additional information: This AppHost does not support accessing the current Request via a Singleton

最佳答案

User Session只能在请求的上下文中访问,因为它依赖于 Session Cookies当前请求。

只有 ASP.NET 主机有权访问 HttpContext.Current 单例来访问当前请求。当尝试访问 HTTP 监听器自主机中的用户 session 而不注入(inject)当前的 HTTP Request 时,您将收到此异常,例如:

var userSession = SessionFeature
    .GetOrCreateSession<AuthUserSession>(CacheClient, Request);

我建议不要尝试像这样访问用户 session ,而是在 IRecordManagement 上创建一个扩展方法,该方法填充 POCO 类似于您的 InsertFilter 正在执行的操作,例如:

db.Insert(new Record { ... }.WithAudit(Request));

//Extension Method Example:
public static class RecordManagementExtensions
{
    public static T WithAudit<T>(this T row, IRequest req) where T : IRecordManagement => 
        row.WithAudit(Request.GetSession().UserAuthId);

    public static T WithAudit<T>(this T row, string userId) where T : IRecordManagement
    {
        row.UserId = userId;
        row.DateCreated = DateTime.UtcNow;
        return row;
    }
}

虽然我不建议依赖 RequestContext 单例,但在这种情况下您可以使用它来设置请求过滤器中请求的当前 UserId,例如:

GlobalRequestFilters.Add((req, res, requestDto) => {
    RequestContext.Instance.Items["userId"] = req.GetSession().UserAuthId;
});

然后您就可以从过滤器访问它,例如:

OrmLiteConfig.InsertFilter = (dbCmd, row) => {
    ...
    recordMgt.CreatedUserId = RequestContext.Instance.Items["userId"];
}

关于c# - ServiceStack:访问InsertFilter和UpdateFilter中的 session ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35629080/

相关文章:

c# - 如何获得事件的订阅者?

c# - 将 char 转换为小写的棘手方法 - 以及相反的方法

ravendb - 将 RavenDB 与 ServiceStack 一起使用

c# - Oracle 存储过程适用于 ADO.NET,但使用 OrmLite 会引发异常?

LINQ 查询失败,变量 ormlite 可为空

servicestack - ServiceStack.OrmLite是否支持乐观并发

java - 在哪里捕获和处理空参数?

c# - C# 中的串联

ServiceStack ORMLite 如何不序列化列表

servicestack - 如何从 ServiceStack API 中删除 AssignRoles 和 UnAssignRoles