I am using the new OrmLiteAuthRespositoryMultiTenancy so it uses the AppHost.GetDbConnection() method so the db can bet set on each request. When I’m using the RequiredPermissionAttribute, it works fine if the user has the permission, but if they don’t have the required permission I get the following:
ExecuteReader requires an open and available Connection. The connection’s current state is closed.
Stack trace below:
Re the “RoleBasedAuthRepository”, this is my custom AuthRepository which derives from OrmLiteAuthRepositoryMultitenancy. It is failing while calling base.GetUserAuth(userAuthId).
ServiceStack.Auth.OrmLiteAuthRepositoryBase`2.<>c__DisplayClass21_0.<GetUserAuth>b__0(IDbConnection db) at ServiceStack.Auth.OrmLiteAuthRepositoryMultitenancy`2.Exec[T](Func`2 fn) at ServiceStack.Auth.OrmLiteAuthRepositoryBase`2.GetUserAuth(String userAuthId) at RoleBasedAuthRepository.HasPermission(String userAuthId, String permission) in RoleBasedUserAuthRepository.cs:line 51 at ServiceStack.AuthUserSession.HasPermission(String permission, IAuthRepository authRepo) at ServiceStack.RequiredPermissionAttribute.<>c__DisplayClass8_0.<HasAllPermissions>b__0(String x) at System.Linq.Enumerable.All[TSource](IEnumerable`1 source, Func`2 predicate) at ServiceStack.RequiredPermissionAttribute.HasAllPermissions(IAuthSession session, IAuthRepository authRepo) at ServiceStack.RequiredPermissionAttribute.HasAllPermissions(IRequest req, IAuthSession session, IAuthRepository authRepo) at ServiceStack.RequiredPermissionAttribute.Execute(IRequest req, IResponse res, Object requestDto) at ServiceStack.RequestFilterAttribute.RequestFilter(IRequest req, IResponse res, Object requestDto) at ServiceStack.Host.ServiceRunner`1.Execute(IRequest request, Object instance, TRequest requestDto)
Not sure what the request is but we don’t stand a chance to be able to reproduce this without access to the missing classes in the StackTrace that’s causing the exception.
I have re-plumbed to purely use OrmLiteAuthRepositoryMultTenancy natively (rather than my own derivative), and below is the stack trace of the error.
System.InvalidOperationException: ExecuteReader requires an open and available Connection. The connection’s current state is closed.
at System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader() at ServiceStack.OrmLite.OrmLiteCommand.ExecuteReader() at ServiceStack.OrmLite.OrmLiteReadCommandExtensions.ExecReader(IDbCommand dbCmd, String sql) at ServiceStack.OrmLite.OrmLiteResultsFilterExtensions.ConvertTo[T](IDbCommand dbCmd, String sql) at ServiceStack.OrmLite.OrmLiteReadCommandExtensions.SingleById[T](IDbCommand dbCmd, Object value) at ServiceStack.OrmLite.OrmLiteReadApi.<>c__DisplayClass19_01.b__0(IDbCommand dbCmd)
at ServiceStack.OrmLite.OrmLiteExecFilter.Exec[T](IDbConnection dbConn, Func2 filter) at ServiceStack.OrmLite.OrmLiteReadExpressionsApi.Exec[T](IDbConnection dbConn, Func2 filter)
at ServiceStack.OrmLite.OrmLiteReadApi.SingleById[T](IDbConnection dbConn, Object idValue)
at ServiceStack.Auth.OrmLiteAuthRepositoryBase2.<>c__DisplayClass21_0.<GetUserAuth>b__0(IDbConnection db) at ServiceStack.Auth.OrmLiteAuthRepositoryMultitenancy2.Exec[T](Func2 fn) at ServiceStack.Auth.OrmLiteAuthRepositoryBase2.GetUserAuth(String userAuthId)
at ServiceStack.Auth.OrmLiteAuthRepositoryBase2.HasPermission(String userAuthId, String permission) at ServiceStack.AuthUserSession.HasPermission(String permission, IAuthRepository authRepo) at ServiceStack.RequiredPermissionAttribute.<>c__DisplayClass8_0.<HasAllPermissions>b__0(String x) at System.Linq.Enumerable.All[TSource](IEnumerable1 source, Func2 predicate) at ServiceStack.RequiredPermissionAttribute.HasAllPermissions(IAuthSession session, IAuthRepository authRepo) at ServiceStack.RequiredPermissionAttribute.HasAllPermissions(IRequest req, IAuthSession session, IAuthRepository authRepo) at ServiceStack.RequiredPermissionAttribute.Execute(IRequest req, IResponse res, Object requestDto) at ServiceStack.RequestFilterAttribute.RequestFilter(IRequest req, IResponse res, Object requestDto) at ServiceStack.Host.ServiceRunner1.Execute(IRequest request, Object instance, TRequest requestDto
Hi, yes my code is identical. My point is that in SessionExtensions.UpdateFromUserAuthRepo method (which is called when evaluating the RequiredPermissionAttribute), the following code is called:
using (userAuthRepo as IDisposable)
{
var userAuth = userAuthRepo.GetUserAuth(session, null);
session.UpdateSession(userAuth);
}
This will call Dispose() on userAuthRepo, which in the case of OrmLiteAuthRepositoryMultitenancy will call _db.Close(), leaving this connection unusable.
but to no avail. I do have types with SqlExpression as properties, but they are excluded via [DataContract] & not having [DataMember] attributes & these have been in place for ages. Has anything changed in 4.5.13 wrt what types exposed?
Service method returns list of MapViewBase derivatives:
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using HarbourAssist.Infrastructure.Entities;
using ServiceStack.Data;
using ServiceStack.OrmLite;
namespace HarbourAssist.Dtos.Data.Geo
{
[DataContract]
public abstract class MapViewBase : IMapView
{
public IDbConnectionFactory DbConnectionFactory { get; set; }
[DataMember]
public abstract string Key { get; }
[DataMember]
public abstract string MapPopupView { get; }
public abstract Dictionary<string, MapSqlExpression<Mooring>> Icons { get; }
public abstract Dictionary<string, MapSqlExpression<Mooring>> Colours { get; }
public abstract Dictionary<string, SqlExpression<Mooring>> Filters { get; }
[DataMember]
public List<string> FilterNames => Filters?.Select(d => d.Key).ToList();
[DataMember]
public Dictionary<string, string> IconLegendInfo => Icons?.ToDictionary(d => d.Key, d => d.Value.LegendText);
[DataMember]
public Dictionary<string, string> ColourLegendInfo => Colours?.ToDictionary(d => d.Key, d => d.Value.LegendText);
[DataMember]
public abstract bool ShowDatePicker { get; }
[DataMember]
public abstract bool IsDraggable { get; }
}
}
MapSqlExpression is just:
using ServiceStack.OrmLite;
namespace HarbourAssist.Dtos
{
public class MapSqlExpression<T>
{
public string LegendText { get; set; }
public SqlExpression<T> Expression { get; set; }
}
}
Re. generated typescirpt, can I email you this for the sake of not exposing entire app object structure?
Yes I appreciate that, but I thought that the DataContract would (and has) stopped anything functional being serialised, IMapView is below. I will refactor all out to have a clean DTO as this should resolve?
That looks like the issue then, since Interfaces are now being generated and your interface contains non-serializable types. You can disable interfaces from being generated with:
var nativeTypes = this.GetPlugin<NativeTypesFeature>();
nativeTypes.MetadataTypesConfig.ExcludeImplementedInterfaces = true;