Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions dotnet/src/dotnetcore/GxClasses/Helpers/CompatibilityExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,17 @@ public AssemblyLoader(string path)
}
internal static Type GetType(string typeFullName)
{
string typeName = typeFullName.Split(',').First();
string assemblyName = typeFullName.Substring(typeName.Length + 1);
AssemblyName assName = new AssemblyName(assemblyName);
return LoadContext.LoadFromAssemblyName(assName).GetType(typeName);
if (typeFullName.Contains(','))
{
string typeName = typeFullName.Split(',').First();
string assemblyName = typeFullName.Substring(typeName.Length + 1);
AssemblyName assName = new AssemblyName(assemblyName);
return LoadContext.LoadFromAssemblyName(assName).GetType(typeName);
}
else
{
return Type.GetType(typeFullName, true, true);
}
}
/*Try to resolve by name when resolution fails. Keep compatibility with previous resolver*/
private static Assembly LoadContext_Resolving(AssemblyLoadContext arg1, AssemblyName assemblyName)
Expand Down
145 changes: 113 additions & 32 deletions dotnet/src/dotnetcore/GxClasses/Services/Session/GXSessionFactory.cs
Original file line number Diff line number Diff line change
@@ -1,49 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using GeneXus.Configuration;
using GeneXus.Encryption;
using GxClasses.Helpers;
using log4net;

namespace GeneXus.Services
{
public class GXSessionServiceFactory
{
private static readonly ILog log = log4net.LogManager.GetLogger(typeof(GXSessionServiceFactory));
static string REDIS = "REDIS";
static string DATABASE = "DATABASE";
static string SESSION_ADDRESS = "SESSION_PROVIDER_ADDRESS";
static string SESSION_INSTANCE = "SESSION_PROVIDER_INSTANCE_NAME";
static string SESSION_PASSWORD = "SESSION_PROVIDER_PASSWORD";
static string SESSION_SCHEMA = "SESSION_PROVIDER_SCHEMA";
static string SESSION_TABLE_NAME = "SESSION_PROVIDER_TABLE_NAME";
static string SESSION_TIMEOUT = "SESSION_PROVIDER_SESSION_TIMEOUT";

public static ISessionService GetProvider()
{
GXService instance = GXServices.Instance?.Get(GXServices.SESSION_SERVICE);
if (instance != null)
ISessionService sessionService = null;
GXService providerService = GXServices.Instance?.Get(GXServices.SESSION_SERVICE);
if (providerService != null)
{
string password = instance.Properties.Get(SESSION_PASSWORD);
if (!string.IsNullOrEmpty(password))
{
password = CryptoImpl.Decrypt(password);
}
if (instance.Name.Equals(REDIS, StringComparison.OrdinalIgnoreCase))
try
{
string sessionTimeout = instance.Properties.Get(SESSION_TIMEOUT);
int timeout=0;
if (!string.IsNullOrEmpty(sessionTimeout))
int.TryParse(sessionTimeout, out timeout);

return new GxRedisSession(instance.Properties.Get(SESSION_ADDRESS),
password,
instance.Properties.Get(SESSION_INSTANCE),
timeout);
Type type = null;
string className = providerService.ClassName;
//Compatibility
if (string.IsNullOrEmpty(className))
{
if (providerService.Name.Equals(REDIS, StringComparison.OrdinalIgnoreCase))
type = typeof(GxRedisSession);
else if (providerService.Name.Equals(DATABASE, StringComparison.OrdinalIgnoreCase))
type = typeof(GxDatabaseSession);
}
else
{

GXLogging.Debug(log, "Loading Session provider:", className);
#if !NETCORE
type = Type.GetType(className, true, true);
#else
type = AssemblyLoader.GetType(className);
#endif
}
if (type != null)
{
sessionService = (ISessionService)Activator.CreateInstance(type, new object[] { providerService });
return sessionService;
}
}
else if (instance.Name.Equals(DATABASE, StringComparison.OrdinalIgnoreCase))
catch (Exception e)
{
return new GxDatabaseSession(instance.Properties.Get(SESSION_ADDRESS),
password,
instance.Properties.Get(SESSION_SCHEMA),
instance.Properties.Get(SESSION_TABLE_NAME));
GXLogging.Error(log, "Couldn´t create Session provider.", e.Message, e);
throw e;
}
}
return null;
Expand All @@ -52,6 +58,34 @@ public static ISessionService GetProvider()
}
public class GxRedisSession : ISessionService
{
internal static string SESSION_ADDRESS = "SESSION_PROVIDER_ADDRESS";
internal static string SESSION_INSTANCE = "SESSION_PROVIDER_INSTANCE_NAME";
internal static string SESSION_PASSWORD = "SESSION_PROVIDER_PASSWORD";
static string SESSION_TIMEOUT = "SESSION_PROVIDER_SESSION_TIMEOUT";

public GxRedisSession(GXService serviceProvider)
{
string password = serviceProvider.Properties.Get(SESSION_PASSWORD);
if (!string.IsNullOrEmpty(password))
{
password = CryptoImpl.Decrypt(password);
}
string host = serviceProvider.Properties.Get(SESSION_ADDRESS);
string instanceName = serviceProvider.Properties.Get(SESSION_INSTANCE);
ConnectionString = $"{host}";
if (!string.IsNullOrEmpty(password))
{
ConnectionString += $",password={password}";
}
InstanceName = instanceName;

int sessionTimeoutMinutes = Preferences.SessionTimeout;
string sessionTimeoutStrCompatibility = serviceProvider.Properties.Get(SESSION_TIMEOUT);
if (!string.IsNullOrEmpty(sessionTimeoutStrCompatibility))
int.TryParse(sessionTimeoutStrCompatibility, out sessionTimeoutMinutes);

SessionTimeout = sessionTimeoutMinutes;
}
public GxRedisSession(string host, string password, string instanceName, int sessionTimeout)
{
ConnectionString = $"{host}";
Expand All @@ -72,6 +106,53 @@ public GxRedisSession(string host, string password, string instanceName, int ses
}
public class GxDatabaseSession : ISessionService
{
internal static string SESSION_ADDRESS = "SESSION_PROVIDER_ADDRESS";
internal static string SESSION_PASSWORD = "SESSION_PROVIDER_PASSWORD";
internal static string SESSION_SCHEMA = "SESSION_PROVIDER_SCHEMA";
internal static string SESSION_TABLE_NAME = "SESSION_PROVIDER_TABLE_NAME";
internal static string SESSION_PROVIDER_SERVER = "SESSION_PROVIDER_SERVER";
internal static string SESSION_PROVIDER_DATABASE = "SESSION_PROVIDER_DATABASE";
internal static string SESSION_PROVIDER_USER = "SESSION_PROVIDER_USER";

public GxDatabaseSession(GXService serviceProvider)
{
string password = serviceProvider.Properties.Get(SESSION_PASSWORD);
if (!string.IsNullOrEmpty(password))
{
password = CryptoImpl.Decrypt(password);
}
string serverName = serviceProvider.Properties.Get(SESSION_PROVIDER_SERVER);
string userName = serviceProvider.Properties.Get(SESSION_PROVIDER_USER);
string database = serviceProvider.Properties.Get(SESSION_PROVIDER_DATABASE);
string schema = serviceProvider.Properties.Get(SESSION_SCHEMA);
string tableName = serviceProvider.Properties.Get(SESSION_TABLE_NAME);

string sessionAddresCompatibility = serviceProvider.Properties.Get(GxDatabaseSession.SESSION_ADDRESS);
if (!string.IsNullOrEmpty(sessionAddresCompatibility))
{
ConnectionString = sessionAddresCompatibility;
}

if (!string.IsNullOrEmpty(serverName))
{
ConnectionString += $"Data Source={serverName};";
}
if (!string.IsNullOrEmpty(database))
{
ConnectionString += $"Initial Catalog={database}";
}
if (!string.IsNullOrEmpty(password))
{
ConnectionString += $";password={password}";
}
if (!string.IsNullOrEmpty(userName))
{
ConnectionString += $";user={userName}";
}
Schema = schema;
TableName = tableName;
SessionTimeout = Preferences.SessionTimeout;
}
public GxDatabaseSession(string host, string password, string schema, string tableName)
{
ConnectionString = $"{host}";
Expand All @@ -90,7 +171,7 @@ public GxDatabaseSession(string host, string password, string schema, string tab

public string InstanceName => throw new NotImplementedException();

public int SessionTimeout => throw new NotImplementedException();
public int SessionTimeout { get; }
}

public interface ISessionService
Expand Down
11 changes: 6 additions & 5 deletions dotnet/src/dotnetcore/GxNetCoreStartup/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ public class Startup
{

static readonly ILog log = log4net.LogManager.GetLogger(typeof(Startup));
const int DEFAULT_SESSION_TIMEOUT_MINUTES = 20;
const long DEFAULT_MAX_FILE_UPLOAD_SIZE_BYTES = 528000000;
public static string VirtualPath = string.Empty;
public static string LocalPath = Directory.GetCurrentDirectory();
Expand Down Expand Up @@ -188,10 +187,7 @@ public void ConfigureServices(IServiceCollection services)
services.AddHttpContextAccessor();
services.AddSession(options =>
{
if (Config.GetValueOf("SessionTimeout", out string SessionTimeoutStr) && int.TryParse(SessionTimeoutStr, out int SessionTimeout))
options.IdleTimeout = TimeSpan.FromMinutes(SessionTimeout);
else
options.IdleTimeout = TimeSpan.FromMinutes(DEFAULT_SESSION_TIMEOUT_MINUTES);
options.IdleTimeout = TimeSpan.FromMinutes(Preferences.SessionTimeout);
options.Cookie.HttpOnly = true;
options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
options.Cookie.IsEssential = true;
Expand Down Expand Up @@ -268,6 +264,7 @@ private void ConfigureSessionService(IServiceCollection services, ISessionServic
{
services.AddStackExchangeRedisCache(options =>
{
GXLogging.Info(log, $"Using Redis for Distributed session, ConnectionString:{sessionService.ConnectionString}, InstanceName: {sessionService.InstanceName}");
options.Configuration = sessionService.ConnectionString;
options.InstanceName = sessionService.InstanceName;
});
Expand All @@ -277,9 +274,11 @@ private void ConfigureSessionService(IServiceCollection services, ISessionServic
{
services.AddDistributedSqlServerCache(options =>
{
GXLogging.Info(log, $"Using SQLServer for Distributed session, ConnectionString:{sessionService.ConnectionString}, SchemaName: {sessionService.Schema}, TableName: {sessionService.TableName}");
options.ConnectionString = sessionService.ConnectionString;
options.SchemaName = sessionService.Schema;
options.TableName = sessionService.TableName;
options.DefaultSlidingExpiration = TimeSpan.FromMinutes(sessionService.SessionTimeout);
});
}
}
Expand Down Expand Up @@ -475,6 +474,7 @@ bool IsAspx(HttpContext context, string basePath)
}
public class CustomExceptionHandlerMiddleware
{
static readonly ILog log = log4net.LogManager.GetLogger(typeof(CustomExceptionHandlerMiddleware));
public async Task Invoke(HttpContext httpContext)
{
Exception ex = httpContext.Features.Get<IExceptionHandlerFeature>()?.Error;
Expand All @@ -488,6 +488,7 @@ public async Task Invoke(HttpContext httpContext)
else
{
httpStatusCode = HttpStatusCode.InternalServerError;
GXLogging.Error(log, $"Internal error", ex);
}
}
if (httpStatusCode!= HttpStatusCode.OK)
Expand Down
14 changes: 14 additions & 0 deletions dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,7 @@ public class Preferences
static string defaultDatastore;
const string DEFAULT_DS = "Default";
static int httpclient_max_per_route = -1;
static int sessionTimeout = -1;
internal static string DefaultDatastore
{
get
Expand Down Expand Up @@ -1324,6 +1325,19 @@ internal static bool CorsEnabled {
return !string.IsNullOrEmpty(CorsAllowedOrigins());
}
}
const int DEFAULT_SESSION_TIMEOUT_MINUTES = 20;
public static int SessionTimeout {
get {
if (sessionTimeout == -1)
{
if (Config.GetValueOf("SessionTimeout", out string SessionTimeoutStr) && int.TryParse(SessionTimeoutStr, out int value))
sessionTimeout = value;
else
sessionTimeout = DEFAULT_SESSION_TIMEOUT_MINUTES;
}
return sessionTimeout;
}
}

internal static string CorsAllowedOrigins()
{
Expand Down
3 changes: 3 additions & 0 deletions dotnet/test/DotNetRedisTest/DotNetRedisTest.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
</ItemGroup>

<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="CloudServices.dev.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
64 changes: 64 additions & 0 deletions dotnet/test/DotNetRedisTest/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
"appSettings": {
"AppMainNamespace": "GeneXus.Programs",
"DataStore1": "Default",
"DataStore-Count": "1",
"DataStore-Default": "Default",
"Connection-Default-DBMS": "sqlserver",
"Connection-Default-Port": "",
"Connection-Default-LockTimeout": "0",
"Connection-Default-LockRetryCount": "10",
"Connection-Default-IsolationLevel": "CR",
"Connection-Default-Datasource": "",
"Connection-Default-User": "",
"Connection-Default-Password": "",
"Connection-Default-DB": "",
"Connection-Default-Schema": "",
"Connection-Default-Opts": "",
"Connection-Default-TrnInt": "1",
"DateFormat": "MDY",
"YearLimit": "1940",
"TimeAmPmFormat": "12",
"VER_STAMP": "20210602.093942",
"CS_BLOB_PATH": "PublicTempStorage",
"TMPMEDIA_DIR": "PrivateTempStorage",
"PRINT_LAYOUT_METADATA_DIR": "LayoutMetadata",
"StorageTimeZone": "1",
"LOGIN_AS_USERID": "0",
"LANGUAGE": "eng",
"LANG_NAME": "English",
"DECIMAL_POINT": ".",
"DATE_FMT": "MDY",
"CTOD_DATE_FMT": "L",
"Culture": "en-US",
"Theme": "Carmine",
"UseNamedParameters": "1",
"EnableIntegratedSecurity": "0",
"MAX_CURSOR": "100",
"STATIC_CONTENT": "",
"GX_BUILD_NUMBER": "11103481",
"CACHE_CONTENT_EXPIRATION": "36",
"ENABLE_MANAGEMENT": "0",
"COMPRESS_HTML": "1",
"IE_COMPATIBILITY_VIEW": "EmulateIE7",
"DocumentType": "HTML5",
"EXPOSE_METADATA": "0",
"SMART_CACHING": "0",
"wcf:serviceHostingEnvironment:useClassicReadEntityBodyMode": "true",
"HTTP_PROTOCOL": "Unsecure",
"SAMESITE_COOKIE": "Lax",
"CACHE_INVALIDATION_TOKEN": "20216211291931",
"CORS_ALLOW_ORIGIN": "https://normal-website.com",
"MY_CUSTOM_PTY": "DEFAULT_VALUE"
},
"languages": {
"English": {
"code": "eng",
"culture": "en-US",
"date_fmt": "MDY",
"decimal_point": ".",
"thousand_sep": ",",
"time_fmt": "12"
}
}
}