Skip to content

Commit 14b30ad

Browse files
Merge pull request #245 from astankov2/master
Check if an exception is client-side by checking if the exception source is a registered assembly in CloneStateBehavior
2 parents 6deb263 + 0fa27b1 commit 14b30ad

6 files changed

Lines changed: 60 additions & 23 deletions

File tree

Build/BlazorStateMultiStage.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pr: none
66
variables:
77
Major: 3
88
Minor: 4
9-
Patch: 2
9+
Patch: 3
1010
DotNetSdkVersion: 3.1.404
1111

1212
stages:

Source/BlazorState/Extensions/ServiceCollectionExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public static IServiceCollection AddBlazorState
4848
EnsureLogger(aServiceCollection);
4949
EnsureHttpClient(aServiceCollection);
5050
EnsureMediator(aServiceCollection, blazorStateOptions);
51-
EnusureStates(aServiceCollection, blazorStateOptions);
51+
EnsureStates(aServiceCollection, blazorStateOptions);
5252

5353
aServiceCollection.AddScoped<BlazorHostingLocation>();
5454
aServiceCollection.AddScoped<JsonRequestHandler>();
@@ -145,7 +145,7 @@ private static void EnsureMediator(IServiceCollection aServiceCollection, Blazor
145145
}
146146
}
147147

148-
private static void EnusureStates(IServiceCollection aServiceCollection, BlazorStateOptions aBlazorStateOptions)
148+
private static void EnsureStates(IServiceCollection aServiceCollection, BlazorStateOptions aBlazorStateOptions)
149149
{
150150
foreach (Assembly assembly in aBlazorStateOptions.Assemblies)
151151
{

Source/BlazorState/Pipeline/CloneState/CloneStateBehavior.cs

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,27 @@ namespace BlazorState.Pipeline.State
55
using MediatR;
66
using Microsoft.Extensions.Logging;
77
using System;
8+
using System.Linq;
89
using System.Threading;
910
using System.Threading.Tasks;
1011

1112
internal class CloneStateBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
1213
{
1314
private readonly ILogger Logger;
1415
private readonly IMediator Mediator;
16+
private readonly BlazorStateOptions BlazorStateOptions;
1517
private readonly IStore Store;
1618

1719
public CloneStateBehavior
18-
(
20+
(
1921
ILogger<CloneStateBehavior<TRequest, TResponse>> aLogger,
22+
BlazorStateOptions aBlazorStateOptions,
2023
IStore aStore,
21-
IMediator aMediator
22-
)
24+
IMediator aMediator)
2325
{
2426
Logger = aLogger;
2527
Logger.LogDebug($"{GetType().Name} constructor");
28+
BlazorStateOptions = aBlazorStateOptions;
2629
Store = aStore;
2730
Mediator = aMediator;
2831
}
@@ -79,7 +82,7 @@ RequestHandlerDelegate<TResponse> aNext
7982
Logger.LogWarning($"{className}: InnerError: {aException?.InnerException?.Message}");
8083
Logger.LogWarning($"{className}: Restoring State of type: {declaringType}");
8184

82-
if (!IsApiCallException(aException) && originalState != null)
85+
if (IsClientSideException(aException) && originalState != null)
8386
{
8487
Store.SetState(originalState as IState);
8588

@@ -98,16 +101,7 @@ RequestHandlerDelegate<TResponse> aNext
98101
}
99102
}
100103

101-
private bool IsApiCallException(Exception aException)
102-
{
103-
string stackTrace = aException.ToString();
104-
105-
if (stackTrace.ToLowerInvariant().Contains("httprequestexception"))
106-
{
107-
return true;
108-
}
109-
110-
return false;
111-
}
104+
private bool IsClientSideException(Exception aException) =>
105+
BlazorStateOptions.Assemblies.Any(aAssembly => aAssembly.GetName().Name == aException.Source);
112106
}
113107
}

Tests/Client.Integration.Tests/Pipeline/CloneStateBehavior_Tests.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,18 +80,17 @@ public async Task WillNotRollbackState_When_ExceptionOccursInAnEndpointOnServer(
8080
CounterState.Initialize(aCount: 22);
8181
Guid preActionGuid = CounterState.Guid;
8282

83-
var throwExceptionAction = new ThrowExceptionAction
83+
var throwServerSideExceptionAction = new ThrowServerSideExceptionAction
8484
{
85-
Message = new HttpRequestException(
86-
"Response status code does not indicate success: 500 (Internal Server Error).").ToString()
85+
Message = "Response status code does not indicate success: 500 (Internal Server Error)."
8786
};
8887

8988
// Act
9089
Exception exception = await Shouldly.Should.ThrowAsync<Exception>(async () =>
91-
await Send(throwExceptionAction));
90+
await Send(throwServerSideExceptionAction));
9291

9392
// Assert
94-
exception.Message.ShouldBe(throwExceptionAction.Message);
93+
exception.Message.ShouldBe(throwServerSideExceptionAction.Message);
9594
CounterState.Guid.Equals(preActionGuid).ShouldBeFalse();
9695
}
9796
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
namespace TestApp.Client.Features.Counter
2+
{
3+
using BlazorState;
4+
5+
public partial class CounterState
6+
{
7+
public class ThrowServerSideExceptionAction : IAction
8+
{
9+
public string Message { get; set; }
10+
}
11+
}
12+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
namespace TestApp.Client.Features.Counter
2+
{
3+
using BlazorState;
4+
using MediatR;
5+
using System.Net.Http;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using TestApp.Client.Features.Base;
9+
10+
public partial class CounterState
11+
{
12+
internal class ThrowServerSideExceptionHandler : BaseHandler<ThrowServerSideExceptionAction>
13+
{
14+
public ThrowServerSideExceptionHandler(IStore aStore) : base(aStore) { }
15+
16+
/// <summary>
17+
/// Intentionally throw so we can test exception handling.
18+
/// </summary>
19+
/// <param name="aThrowServerSideExceptionAction"></param>
20+
/// <param name="aCancellationToken"></param>
21+
/// <returns></returns>
22+
public override Task<Unit> Handle
23+
(
24+
ThrowServerSideExceptionAction aThrowServerSideExceptionAction,
25+
CancellationToken aCancellationToken
26+
) => throw new HttpRequestException(aThrowServerSideExceptionAction.Message)
27+
{
28+
Source = $"{nameof(TestApp)}.Server"
29+
};
30+
}
31+
}
32+
}

0 commit comments

Comments
 (0)