Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#4315 ContextManager Backport #4395

Draft
wants to merge 4 commits into
base: v7.x
Choose a base branch
from
Draft
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
1 change: 1 addition & 0 deletions Source/Csla.Axml.Android/Csla.Axml.Android.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<LangVersion>preview</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
Expand Down
133 changes: 127 additions & 6 deletions Source/Csla.Blazor.Test/ApplicationContextTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
#if NET6_0_OR_GREATER
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Extensions.DependencyInjection;
using System;
using Csla.Configuration;
Expand All @@ -7,20 +8,23 @@
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using System.Security.Claims;
using System.Threading;

namespace Csla.Blazor.Test
{
[TestClass]
public class ApplicationContextTests
{
#if NET6_0_OR_GREATER
[TestMethod]
public void CorrectManagerChosen()
{
IServiceCollection services = new ServiceCollection();
services.AddHttpContextAccessor();
services.AddScoped<Csla.AspNetCore.Blazor.ActiveCircuitState>();
services.AddScoped(typeof(AuthenticationStateProvider), typeof(TestAuthenticationStateProvider));
services.AddScoped(typeof(AuthenticationStateProvider), typeof(AuthenticationStateProviderFake));
services.AddCsla(c => c
.AddAspNetCore()
.AddServerSideBlazor()
Expand All @@ -45,12 +49,129 @@ public void CorrectManagerChosen()
Assert.IsTrue(appContext.ContextManager is Csla.Core.ApplicationContextManagerAsyncLocal);

}
#endif

[TestMethod]
public void UseApplicationContextManagerBlazor()
{
var services = new ServiceCollection();
services.AddScoped<AuthenticationStateProvider, AuthenticationStateProviderFake>();
services.AddHttpContextAccessor();
services.AddCsla(o => o
.AddAspNetCore()
.AddServerSideBlazor());
var serviceProvider = services.BuildServiceProvider();

var activeState = serviceProvider.GetRequiredService<AspNetCore.Blazor.ActiveCircuitState>();
activeState.CircuitExists = true;

var applicationContext = serviceProvider.GetRequiredService<ApplicationContext>();
Assert.IsInstanceOfType(applicationContext.ContextManager, typeof(Csla.AspNetCore.Blazor.ApplicationContextManagerBlazor));
}

[TestMethod]
public void UseAsyncLocalApplicationContextManager()
{
var services = new ServiceCollection();
services.AddScoped<AuthenticationStateProvider, AuthenticationStateProviderFake>();
services.AddHttpContextAccessor();
services.AddCsla(o => o
.AddAspNetCore()
.AddServerSideBlazor());
var serviceProvider = services.BuildServiceProvider();

var activeState = serviceProvider.GetRequiredService<AspNetCore.Blazor.ActiveCircuitState>();
activeState.CircuitExists = false;

var applicationContext = serviceProvider.GetRequiredService<ApplicationContext>();
Assert.IsInstanceOfType(applicationContext.ContextManager, typeof(Csla.Core.ApplicationContextManagerAsyncLocal));
}

[TestMethod]
public void UseBlazorApplicationContextManager()
{
var services = new ServiceCollection();
services.AddScoped<AuthenticationStateProvider, AuthenticationStateProviderFake>();
services.AddScoped<IHttpContextAccessor, HttpContextAccessorFake>();
services.AddCsla(o => o
.AddAspNetCore()
.AddServerSideBlazor());
var serviceProvider = services.BuildServiceProvider();

var activeState = serviceProvider.GetRequiredService<AspNetCore.Blazor.ActiveCircuitState>();
activeState.CircuitExists = true;

var applicationContext = serviceProvider.GetRequiredService<ApplicationContext>();
Assert.IsInstanceOfType(applicationContext.ContextManager, typeof(Csla.AspNetCore.Blazor.ApplicationContextManagerBlazor));
}

[TestMethod]
public void UseAspNetCoreOverBlazorApplicationContextManager()
{
var services = new ServiceCollection();
services.AddScoped<AuthenticationStateProvider, AuthenticationStateProviderFake>();
services.AddScoped<IHttpContextAccessor, HttpContextAccessorFake>();
services.AddCsla(o => o
.AddAspNetCore()
.AddServerSideBlazor());
var serviceProvider = services.BuildServiceProvider();

var activeState = serviceProvider.GetRequiredService<AspNetCore.Blazor.ActiveCircuitState>();
activeState.CircuitExists = false;

var applicationContext = serviceProvider.GetRequiredService<ApplicationContext>();
Assert.IsInstanceOfType(applicationContext.ContextManager, typeof(Csla.AspNetCore.ApplicationContextManagerHttpContext));
}

public class TestAuthenticationStateProvider : AuthenticationStateProvider
[TestMethod]
public void UseAspNetCoreApplicationContextManager()
{
public override Task<AuthenticationState> GetAuthenticationStateAsync()
var services = new ServiceCollection();
services.AddScoped<AuthenticationStateProvider, AuthenticationStateProviderFake>();
services.AddScoped<IHttpContextAccessor, HttpContextAccessorFake>();
services.AddCsla(o => o
.AddAspNetCore());
var serviceProvider = services.BuildServiceProvider();

var activeState = serviceProvider.GetRequiredService<AspNetCore.Blazor.ActiveCircuitState>();
activeState.CircuitExists = false;

var applicationContext = serviceProvider.GetRequiredService<ApplicationContext>();
Assert.IsInstanceOfType(applicationContext.ContextManager, typeof(Csla.AspNetCore.ApplicationContextManagerHttpContext));
}

}

public class AuthenticationStateProviderFake : AuthenticationStateProvider
{
public override Task<AuthenticationState> GetAuthenticationStateAsync()
=> Task.FromResult<AuthenticationState>(null);
}

public class HttpContextAccessorFake : IHttpContextAccessor
{
public HttpContext HttpContext { get; set; } = new HttpContextFake();
}

public class HttpContextFake : HttpContext
{
public override IFeatureCollection Features => throw new NotImplementedException();

public override HttpRequest Request => throw new NotImplementedException();

public override HttpResponse Response => throw new NotImplementedException();

public override ConnectionInfo Connection => throw new NotImplementedException();

public override WebSocketManager WebSockets => throw new NotImplementedException();

public override ClaimsPrincipal User { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public override IDictionary<object, object> Items { get; set; } = new Dictionary<object, object>();
public override IServiceProvider RequestServices { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public override CancellationToken RequestAborted { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public override string TraceIdentifier { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public override ISession Session { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }

public override void Abort() => throw new NotImplementedException();
}
}
#endif
2 changes: 1 addition & 1 deletion Source/Csla.Blazor/ConfigurationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public static CslaOptions AddServerSideBlazor(this CslaOptions config, Action<Bl
options?.Invoke(blazorOptions);

// minimize PropertyChanged events
config.PropertyChangedMode(ApplicationContext.PropertyChangedModes.Windows);
config.BindingOptions.PropertyChangedMode = ApplicationContext.PropertyChangedModes.Windows;

#if NET5_0_OR_GREATER
var managerType = Type.GetType("Csla.AspNetCore.Blazor.ApplicationContextManagerBlazor,Csla.AspNetCore");
Expand Down
3 changes: 2 additions & 1 deletion Source/Csla.Channels.Grpc/GrpcPortal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ protected virtual async Task<ResponseMessage> RouteMessage(string operation, str
{
var options = new GrpcProxyOptions { DataPortalUrl = $"{route}?operation={operation}" };
var channel = ApplicationContext.CreateInstanceDI<global::Grpc.Net.Client.GrpcChannel>();
var proxy = new GrpcProxy(ApplicationContext, channel, options);
var dataPortalOptions = ApplicationContext.GetRequiredService<Csla.Configuration.DataPortalOptions>();
var proxy = new GrpcProxy(ApplicationContext, channel, options, dataPortalOptions);
var clientRequest = new RequestMessage
{
Body = request.Body,
Expand Down
10 changes: 6 additions & 4 deletions Source/Csla.Channels.Grpc/GrpcProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// <summary>Implements a data portal proxy to relay data portal</summary>
//-----------------------------------------------------------------------
using System.Threading.Tasks;
using Csla.Configuration;
using Csla.DataPortalClient;
using Google.Protobuf;
using Grpc.Net.Client;
Expand All @@ -25,20 +26,22 @@ public class GrpcProxy : DataPortalProxy
/// <param name="applicationContext"></param>
/// <param name="channel">GrpcChannel instance</param>
/// <param name="options">Proxy options</param>
public GrpcProxy(ApplicationContext applicationContext, GrpcChannel channel, GrpcProxyOptions options)
/// <param name="dataPortalOptions">Data portal options</param>
public GrpcProxy(ApplicationContext applicationContext, GrpcChannel channel, GrpcProxyOptions options, DataPortalOptions dataPortalOptions)
: base(applicationContext)
{
_channel = channel;
DataPortalUrl = options.DataPortalUrl;
VersionRoutingTag = dataPortalOptions.VersionRoutingTag;
}

private GrpcChannel _channel;
private static GrpcChannel _defaultChannel;
private string VersionRoutingTag { get; set; }

/// <summary>
/// Gets the GrpcChannel used by the gRPC client.
/// </summary>
/// <returns></returns>
protected virtual GrpcChannel GetChannel()
{
if (_channel == null)
Expand All @@ -63,7 +66,6 @@ protected static void SetChannel(GrpcChannel channel)
/// <summary>
/// Get gRPC client object used by data portal.
/// </summary>
/// <returns></returns>
protected virtual GrpcService.GrpcServiceClient GetGrpcClient()
{
return _grpcClient ??= new GrpcService.GrpcServiceClient(GetChannel());
Expand All @@ -84,7 +86,7 @@ protected override async Task<byte[]> CallDataPortalServer(byte[] serialized, st
var request = new RequestMessage
{
Body = outbound,
Operation = CreateOperationTag(operation, ApplicationContext.VersionRoutingTag, routingToken)
Operation = CreateOperationTag(operation, VersionRoutingTag, routingToken)
};
ResponseMessage response;
if (isSync)
Expand Down
5 changes: 3 additions & 2 deletions Source/Csla.Channels.Grpc/GrpcProxyExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ public static DataPortalClientOptions UseGrpcProxy(
sp =>
{
var applicationContext = sp.GetRequiredService<ApplicationContext>();
var dataPortalOptions = sp.GetRequiredService<DataPortalOptions>();
var channel = GrpcChannel.ForAddress(proxyOptions.DataPortalUrl);
return new Csla.Channels.Grpc.GrpcProxy(applicationContext, channel, proxyOptions);
return new Csla.Channels.Grpc.GrpcProxy(applicationContext, channel, proxyOptions, dataPortalOptions);
});
return config;
}
}
}
}
1 change: 1 addition & 0 deletions Source/Csla.Iosui.Ios/Csla.Iosui.Ios.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<AssemblyOriginatorKeyFile>CslaKey.snk</AssemblyOriginatorKeyFile>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<LangVersion>preview</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
Expand Down
16 changes: 5 additions & 11 deletions Source/Csla.Windows/ApplicationContextManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,29 @@
// </copyright>
// <summary>Provides consistent context information between the client</summary>
//-----------------------------------------------------------------------
using System;
using System.Security.Principal;
using System.Threading;
using Csla.Core;
using Csla.Configuration;

namespace Csla.Windows
{
/// <summary>
/// ApplicationContextManager for Windows Forms applications
/// </summary>
public class ApplicationContextManager : Csla.Core.ApplicationContextManager
/// <param name="securityOptions"></param>
public class ApplicationContextManager(SecurityOptions securityOptions) : Csla.Core.ApplicationContextManager
{
/// <summary>
/// Creates an instance of the type.
/// </summary>
public ApplicationContextManager()
{ }

private static IPrincipal _principal;
private SecurityOptions SecurityOptions { get; set; } = securityOptions;

/// <summary>
/// Gets the current principal.
/// </summary>
/// <returns></returns>
public override IPrincipal GetUser()
{
if (_principal == null)
{
if (ApplicationContext.FlowSecurityPrincipalFromClient)
if (SecurityOptions.FlowSecurityPrincipalFromClient)
SetUser(new System.Security.Claims.ClaimsPrincipal());
else
#pragma warning disable CA1416 // Validate platform compatibility
Expand Down
2 changes: 1 addition & 1 deletion Source/Csla.Windows/ConfigurationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public static CslaOptions AddWindowsForms(this CslaOptions config, Action<Window
options?.Invoke(xamlOptions);

// use correct mode for raising PropertyChanged events
ApplicationContext.PropertyChangedMode = ApplicationContext.PropertyChangedModes.Windows;
config.BindingOptions.PropertyChangedMode = ApplicationContext.PropertyChangedModes.Windows;
return config;
}
}
Expand Down
1 change: 1 addition & 0 deletions Source/Csla.Windows/Csla.Windows.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<AssemblyOriginatorKeyFile>..\Csla\CslaKey.snk</AssemblyOriginatorKeyFile>
<BaseOutputPath>..\..\Bin</BaseOutputPath>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<LangVersion>preview</LangVersion>
</PropertyGroup>

<ItemGroup>
Expand Down
11 changes: 3 additions & 8 deletions Source/Csla.Windows/CslaActionExtender.cs
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,7 @@ protected void OnClick(object sender, EventArgs e)
}

break;
//case CslaFormAction.Validate
//case CslaFormAction.Validate

} // switch (props.ActionType)

Expand Down Expand Up @@ -823,12 +823,7 @@ private bool ExecuteSaveAction(ISavable savableObject, ITrackStatus trackableObj
if (!savingArgs.Cancel)
{
_bindingSourceTree.Apply();
ISavable objectToSave;

if (Csla.ApplicationContext.AutoCloneOnUpdate == false)
objectToSave = ((ICloneable)savableObject).Clone() as ISavable;// if not AutoClone, clone manually
else
objectToSave = savableObject;
ISavable objectToSave = savableObject;

if (objectToSave != null)
{
Expand Down Expand Up @@ -937,7 +932,7 @@ private void InitializeControl(Control ctl, KeyValuePair<Control, CslaActionExte
ChangeEnabled(ctl, trackableObject.IsNew || trackableObject.IsDirty || trackableObject.IsDeleted);
if (pair.Value.ActionType == CslaFormAction.Save)
ChangeEnabled(ctl, (trackableObject.IsNew || trackableObject.IsDirty || trackableObject.IsDeleted)
&& trackableObject.IsValid);
&& trackableObject.IsValid);
}
}
}
Expand Down
9 changes: 2 additions & 7 deletions Source/Csla.Windows/CslaActionExtenderToolStrip.cs
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,7 @@ protected void OnClick(object sender, EventArgs e)
}

break;
//case CslaFormAction.Validate
//case CslaFormAction.Validate

} // switch (props.ActionType)

Expand Down Expand Up @@ -823,12 +823,7 @@ private bool ExecuteSaveAction(ISavable savableObject, ITrackStatus trackableObj
if (!savingArgs.Cancel)
{
_bindingSourceTree.Apply();
ISavable objectToSave;

if (Csla.ApplicationContext.AutoCloneOnUpdate == false)
objectToSave = ((ICloneable)savableObject).Clone() as ISavable;// if not AutoClone, clone manually
else
objectToSave = savableObject;
ISavable objectToSave = savableObject;

if (objectToSave != null)
{
Expand Down
Loading
Loading