I have a C#.net application in which I'm writing to a sql server database. The SQL Server tables all have common record management columns (DateCreated, DateLastUpdated, CreatedUserId etc...) and I wish to abstract the population of these fields into an InsertFilter and UpdateFilter.
Here's a cut down version of the AppHost's Configure method..
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();
}
};
}
When executing I get the following exception on the first line of the OrmLiteConfig.InsertFilter delegate. Does anyone have any better ideas for how I can retrieve the current user session id for insertion into the db?
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
The User Session can only be accessed within the context of a request since it's dependent on the Session Cookies of the Current Request.
Only ASP.NET Hosts have access to the HttpContext.Current
singleton to access the current request. You will get this exception when trying to access the Users Session in HTTP Listener Self Hosts without injecting the current HTTP Request
, e.g:
var userSession = SessionFeature
.GetOrCreateSession<AuthUserSession>(CacheClient, Request);
I recommend against trying to access to access the Users Session like this and instead create an extension method on IRecordManagement
that populates the POCO similar to what your InsertFilter
is doing, e.g:
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;
}
}
Whilst I don't recommend relying on RequestContext singleton, you can use it in this case to set the current UserId for the Request in a Request Filter, e.g:
GlobalRequestFilters.Add((req, res, requestDto) => {
RequestContext.Instance.Items["userId"] = req.GetSession().UserAuthId;
});
Which you would then be able to access from your filter, e.g:
OrmLiteConfig.InsertFilter = (dbCmd, row) => {
...
recordMgt.CreatedUserId = RequestContext.Instance.Items["userId"];
}