Skip to content

Commit b5e2544

Browse files
committed
middleware
1 parent 85c6f3c commit b5e2544

18 files changed

Lines changed: 280 additions & 23 deletions

File tree

Directory.Build.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
<RepositoryUrl>https://github.com/managedcode/Communication</RepositoryUrl>
1818
<PackageProjectUrl>https://github.com/managedcode/Communication</PackageProjectUrl>
1919
<Product>Managed Code - Communication</Product>
20-
<Version>2.0.24</Version>
21-
<PackageVersion>2.0.24</PackageVersion>
20+
<Version>2.0.25</Version>
21+
<PackageVersion>2.0.25</PackageVersion>
2222

2323
</PropertyGroup>
2424
<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">

ManagedCode.Communication.Extensions/CommunicationMiddleware.cs

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.ComponentModel.DataAnnotations;
34
using System.Diagnostics;
45
using System.IO;
@@ -25,12 +26,31 @@ public CommunicationMiddleware(ILogger<CommunicationMiddleware> logger, RequestD
2526
public async Task Invoke(HttpContext httpContext)
2627
{
2728
var sw = Stopwatch.StartNew();
29+
2830
try
2931
{
3032
await _next(httpContext);
31-
33+
sw.Stop();
34+
httpContext.Response.Headers.Add("executionTime", sw.Elapsed.ToString());
35+
}
36+
catch (Exception ex)
37+
{
38+
sw.Stop();
39+
40+
httpContext.Response.Headers.Add("executionTime", sw.Elapsed.ToString());
41+
httpContext.Response.Headers.CacheControl = "no-cache,no-store";
42+
httpContext.Response.Headers.Pragma = "no-cache";
43+
httpContext.Response.Headers.Expires = "-1";
44+
httpContext.Response.Headers.ETag = default;
45+
46+
httpContext.Response.ContentType = "application/json; charset=utf-8";
47+
httpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
48+
49+
var result = Result.Fail(HttpStatusCode.InternalServerError, ex.Message);
50+
await httpContext.Response.WriteAsJsonAsync(result);
3251
}
33-
catch (Exception ex) when (ex is InvalidDataException ||
52+
53+
/*catch (Exception ex) when (ex is InvalidDataException ||
3454
ex is InvalidDataContractException)
3555
{
3656
_logger.LogError("Request throw an error", ex);
@@ -42,10 +62,19 @@ public async Task Invoke(HttpContext httpContext)
4262
catch (Exception ex) when (ex is ValidationException)
4363
{
4464
_logger.LogError("Request throw an error", ex);
45-
httpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
65+
//httpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
4666
var result = Result.Fail(HttpStatusCode.InternalServerError, ex.Message);
4767
var json = JsonSerializer.Serialize(result);
48-
await httpContext.Response.WriteAsJsonAsync(json);
68+
//await httpContext.Response.WriteAsJsonAsync(json);
69+
70+
71+
var response = httpContext.Response;
72+
response.ContentType = "application/json";
73+
74+
// get the response code and message
75+
76+
response.StatusCode = (int)HttpStatusCode.InternalServerError;
77+
await response.WriteAsync(json);
4978
}
5079
catch (Exception ex)
5180
{
@@ -54,8 +83,6 @@ public async Task Invoke(HttpContext httpContext)
5483
var result = Result.Fail(HttpStatusCode.InternalServerError, ex.Message);
5584
var json = JsonSerializer.Serialize(result);
5685
await httpContext.Response.WriteAsJsonAsync(json);
57-
}
58-
sw.Stop();
59-
httpContext.Response.Headers.Add("executionTime", sw.Elapsed.ToString());
86+
}*/
6087
}
6188
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
using ManagedCode.Communication.Filters;
3+
using Orleans.Hosting;
4+
5+
namespace ManagedCode.Communication.Extensions;
6+
7+
public static class OrleansExtensions
8+
{
9+
public static ISiloBuilder UseOrleansCommunication(this ISiloBuilder builder)
10+
{
11+
return builder.AddIncomingGrainCallFilter<CommunicationIncomingGrainCallFilter>();
12+
}
13+
public static IClientBuilder UseOrleansCommunication(this IClientBuilder builder)
14+
{
15+
return builder.AddOutgoingGrainCallFilter<CommunicationOutgoingGrainCallFilter>();
16+
}
17+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System;
2+
using System.Globalization;
3+
using System.Linq;
4+
using System.Reflection;
5+
using System.Threading.Tasks;
6+
using Orleans;
7+
8+
namespace ManagedCode.Communication.Filters;
9+
10+
public class CommunicationIncomingGrainCallFilter : IIncomingGrainCallFilter
11+
{
12+
public async Task Invoke(IIncomingGrainCallContext context)
13+
{
14+
try
15+
{
16+
await context.Invoke();
17+
}
18+
catch (Exception exception)
19+
{
20+
Type type;
21+
if (context.InterfaceMethod.ReturnType.IsAssignableFrom(typeof(IResult)))
22+
{
23+
type = typeof(Result);
24+
}
25+
else
26+
{
27+
type = context.InterfaceMethod.ReturnType.IsGenericType
28+
? context.InterfaceMethod.ReturnType.GetGenericArguments()[0]
29+
: context.InterfaceMethod.ReturnType;
30+
}
31+
32+
33+
var resultType = Activator.CreateInstance(type, BindingFlags.NonPublic | BindingFlags.Instance,
34+
null, new object[] { exception }, CultureInfo.CurrentCulture);
35+
36+
context.Result = resultType;
37+
}
38+
}
39+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using System;
2+
using System.Globalization;
3+
using System.Reflection;
4+
using System.Threading.Tasks;
5+
using Orleans;
6+
7+
namespace ManagedCode.Communication.Filters;
8+
9+
public class CommunicationOutgoingGrainCallFilter : IOutgoingGrainCallFilter
10+
{
11+
public async Task Invoke(IOutgoingGrainCallContext context)
12+
{
13+
try
14+
{
15+
await context.Invoke();
16+
}
17+
catch (Exception exception)
18+
{
19+
Type type;
20+
if (context.InterfaceMethod.ReturnType.IsAssignableFrom(typeof(IResult)))
21+
{
22+
type = typeof(Result);
23+
}
24+
else
25+
{
26+
type = context.InterfaceMethod.ReturnType.IsGenericType
27+
? context.InterfaceMethod.ReturnType.GetGenericArguments()[0]
28+
: context.InterfaceMethod.ReturnType;
29+
}
30+
31+
32+
var resultType = Activator.CreateInstance(type, BindingFlags.NonPublic | BindingFlags.Instance,
33+
null, new object[] { exception }, CultureInfo.CurrentCulture);
34+
35+
context.Result = resultType;
36+
}
37+
}
38+
}

ManagedCode.Communication.Orleans/ManagedCode.Communication.Orleans.csproj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<LangVersion>11</LangVersion>
55
<Nullable>enable</Nullable>
66
<IsPackable>true</IsPackable>
7-
<TargetFrameworks>net6.0;net7.0;</TargetFrameworks>
7+
<TargetFramework>net7.0</TargetFramework>
88
<RootNamespace>ManagedCode.Communication</RootNamespace>
99
</PropertyGroup>
1010

@@ -18,11 +18,12 @@
1818

1919
<ItemGroup>
2020
<PackageReference Include="Microsoft.Orleans.Sdk" Version="7.1.0" />
21+
<PackageReference Include="Microsoft.Orleans.Runtime" Version="7.1.0" />
2122
<PackageReference Include="Microsoft.Orleans.Serialization.Abstractions" Version="7.1.0" />
2223
</ItemGroup>
2324

2425
<ItemGroup>
2526
<ProjectReference Include="..\ManagedCode.Communication\ManagedCode.Communication.csproj" />
2627
</ItemGroup>
27-
28+
2829
</Project>

ManagedCode.Communication.Tests/Commands/CommandTests.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
using System.Linq;
21
using FluentAssertions;
32
using Xunit;
43

5-
namespace ManagedCode.Communication.Tests.Collections;
4+
namespace ManagedCode.Communication.Tests.Commands;
65

76
public class CommandTests
87
{

ManagedCode.Communication.Tests/ControllerTests/MiddlewareTests.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
1-
using System.ComponentModel.DataAnnotations;
21
using System.Net;
32
using System.Net.Http.Json;
4-
using System.Net.Mime;
53
using System.Threading.Tasks;
64
using FluentAssertions;
75
using ManagedCode.Communication.Tests.TestApp;
6+
using ManagedCode.Communication.Tests.TestApp.Grains;
87
using Xunit;
98
using Xunit.Abstractions;
10-
using JsonSerializer = System.Text.Json.JsonSerializer;
119

12-
namespace ManagedCode.Communication.Tests;
10+
namespace ManagedCode.Communication.Tests.ControllerTests;
1311

1412
[Collection(nameof(TestClusterApplication))]
1513
public class MiddlewareTests
@@ -30,6 +28,8 @@ public async Task ValidationException()
3028
response.StatusCode.Should().Be(HttpStatusCode.InternalServerError);
3129
var content = await response.Content.ReadAsStringAsync();
3230
var result = await response.Content.ReadFromJsonAsync<Result>();
31+
result.IsFailed.Should().BeTrue();
32+
result.GetError().Value.Message.Should().Be("ValidationException");
3333
}
3434

3535
[Fact]
@@ -38,6 +38,8 @@ public async Task InvalidDataException()
3838
var response = await _application.CreateClient().GetAsync($"test/test2");
3939
response.StatusCode.Should().Be(HttpStatusCode.InternalServerError);
4040
var content = await response.Content.ReadAsStringAsync();
41-
var result = await response.Content.ReadFromJsonAsync<Result>();
41+
var result = await response.Content.ReadFromJsonAsync<Result<int>>();
42+
result.IsFailed.Should().BeTrue();
43+
result.GetError().Value.Message.Should().Be("InvalidDataException");
4244
}
4345
}

ManagedCode.Communication.Tests/ManagedCode.Communication.Tests.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
</None>
2727
</ItemGroup>
2828
<ItemGroup>
29+
<PackageReference Include="Microsoft.Orleans.TestingHost" Version="7.1.0" />
2930
<PackageReference Include="FluentAssertions" Version="6.8.0" />
3031
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
3132
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
@@ -51,6 +52,7 @@
5152

5253
<ItemGroup>
5354
<ProjectReference Include="..\ManagedCode.Communication.Extensions\ManagedCode.Communication.Extensions.csproj" />
55+
<ProjectReference Include="..\ManagedCode.Communication.Orleans\ManagedCode.Communication.Orleans.csproj" />
5456
<ProjectReference Include="..\ManagedCode.Communication\ManagedCode.Communication.csproj" />
5557
</ItemGroup>
5658

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System.Threading.Tasks;
2+
using FluentAssertions;
3+
using ManagedCode.Communication.Tests.TestApp;
4+
using ManagedCode.Communication.Tests.TestApp.Grains;
5+
using Xunit;
6+
using Xunit.Abstractions;
7+
8+
namespace ManagedCode.Communication.Tests.OrleansTests;
9+
10+
[Collection(nameof(TestClusterApplication))]
11+
public class GrainClientTests
12+
{
13+
private readonly ITestOutputHelper _outputHelper;
14+
private readonly TestClusterApplication _application;
15+
16+
public GrainClientTests(ITestOutputHelper outputHelper, TestClusterApplication application)
17+
{
18+
_outputHelper = outputHelper;
19+
_application = application;
20+
}
21+
22+
[Fact]
23+
public async Task IntResult()
24+
{
25+
var intResult = await _application.Cluster.Client.GetGrain<ITestGrain>(0).TestResultInt();
26+
intResult.IsSuccess.Should().Be(true);
27+
intResult.Value.Should().Be(5);
28+
}
29+
30+
[Fact]
31+
public async Task Result()
32+
{
33+
var intResult = await _application.Cluster.Client.GetGrain<ITestGrain>(0).TestResult();
34+
intResult.IsSuccess.Should().Be(true);
35+
}
36+
37+
[Fact]
38+
public async Task IntResultError()
39+
{
40+
var intResult = await _application.Cluster.Client.GetGrain<ITestGrain>(0).TestResultIntError();
41+
intResult.IsFailed.Should().Be(true);
42+
}
43+
44+
[Fact]
45+
public async Task ResultError()
46+
{
47+
var intResult = await _application.Cluster.Client.GetGrain<ITestGrain>(0).TestResultError();
48+
intResult.IsFailed.Should().Be(true);
49+
}
50+
}

0 commit comments

Comments
 (0)