diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml
index ab09c9c..e23cc5d 100644
--- a/.github/workflows/dotnet.yml
+++ b/.github/workflows/dotnet.yml
@@ -17,7 +17,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v1
with:
- dotnet-version: 5.0.x
+ dotnet-version: 6.0.x
- name: Restore dependencies
run: dotnet restore
working-directory: .\main
@@ -34,9 +34,12 @@ jobs:
-p:AssemblyInformationalVersion=${{ steps.nbgv.outputs.AssemblyInformationalVersion }}
--no-restore
working-directory: .\main
- - name: Test
+ - name: ProxyTests
run: dotnet test -c Release --no-build --verbosity normal .\test\ReCode.Cocoon.Proxy.Tests
working-directory: .\main
+ - name: LegacyTests
+ run: |
+ ~/.nuget/packages/xunit.runner.console/2.4.1/tools/net472/xunit.console.exe $Env:GITHUB_WORKSPACE\main\test\ReCode.Cocoon.Legacy.Tests\bin\Release\net45\ReCode.Cocoon.Legacy.Tests.dll
- name: PackLegacy
run: >
dotnet pack --configuration Release --no-build
diff --git a/README.md b/README.md
index 332c07b..1f002cd 100644
--- a/README.md
+++ b/README.md
@@ -18,30 +18,6 @@ An implementation of the Strangler Fig pattern for ASP.NET Core
```
-### Amend `Startup.Auth.cs`
-
-In the file `/App_Start/Startup.Auth.cs`, add delegate to the `OnApplyRedirect` property that supresses the redirect to the login URL for `/facadeauth` requests.
-```c#
-app.UseCookieAuthentication(new CookieAuthenticationOptions
-{
- AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
- LoginPath = new PathString("/Account/Login"),
- Provider = new CookieAuthenticationProvider
- {
- OnApplyRedirect = context =>
- {
- /* This prevents the cookie auth model trying to redirect on a 401 */
- if(context.Request.Uri.ToString().Contains("facadeauth") && context.Response.StatusCode == 401)
- {
- return;
- }
-
- context.Response.Redirect(context.RedirectUri);
- }
- }
-});
-```
-
### Disable MVC routing for the new handlers
```
@@ -151,4 +127,4 @@ dotnet tool install --global Microsoft.Playwright.CLI
playwright install
```
-You can now run the tests inside the test/integration folder.
\ No newline at end of file
+You can now run the tests inside the test/integration folder.
diff --git a/main/Cocoon.sln b/main/Cocoon.sln
index 67673a7..a19e7b6 100644
--- a/main/Cocoon.sln
+++ b/main/Cocoon.sln
@@ -26,14 +26,21 @@ EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReCode.Cocoon.Proxy.Benchmarks", "benchmarks\ReCode.Cocoon.Proxy.Benchmarks\ReCode.Cocoon.Proxy.Benchmarks.csproj", "{33521FFB-D30A-40E5-8AA8-2E394CD01E76}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "assets", "assets", "{19C51172-6F93-479C-BF81-EDA51D6597AE}"
-ProjectSection(SolutionItems) = preProject
- Directory.Build.props = Directory.Build.props
- version.json = version.json
-EndProjectSection
+ ProjectSection(SolutionItems) = preProject
+ Directory.Build.props = Directory.Build.props
+ version.json = version.json
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReCode.Cocoon.Proxy.BlazorCodeGen", "src\ReCode.Cocoon.Proxy.BlazorCodeGen\ReCode.Cocoon.Proxy.BlazorCodeGen.csproj", "{7AFD9FAF-92A5-4EC6-BEA4-EED5C521A6E1}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReCode.Cocoon.Proxy.BlazorCodeGen.Tests", "test\ReCode.Cocoon.Proxy.BlazorCodeGen.Tests\ReCode.Cocoon.Proxy.BlazorCodeGen.Tests.csproj", "{E790C7E7-1C7A-47EF-8F6A-895F104C2BDA}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReCode.Cocoon.Proxy.CodeGenerator.Tests", "test\ReCode.Cocoon.Proxy.CodeGenerator.Tests\ReCode.Cocoon.Proxy.CodeGenerator.Tests.csproj", "{C198CA0A-D982-4295-BF18-8114F8E887F8}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{6AD14C47-2BE5-4428-AB83-641684162C8A}"
ProjectSection(SolutionItems) = preProject
..\.github\workflows\dotnet-develop.yml = ..\.github\workflows\dotnet-develop.yml
+ ..\.github\workflows\dotnet.yml = ..\.github\workflows\dotnet.yml
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "integration", "integration", "{D59BBE80-D414-4AFD-BE3A-A50659F8E4C7}"
diff --git a/main/src/ReCode.Cocoon.Legacy/Session/SessionApiHandler.cs b/main/src/ReCode.Cocoon.Legacy/Session/SessionApiHandler.cs
index 57eb3dd..e67a1c5 100644
--- a/main/src/ReCode.Cocoon.Legacy/Session/SessionApiHandler.cs
+++ b/main/src/ReCode.Cocoon.Legacy/Session/SessionApiHandler.cs
@@ -32,7 +32,7 @@ public void ProcessRequest(HttpContextBase context)
else if ("PUT".Equals(context.Request.HttpMethod, StringComparison.OrdinalIgnoreCase))
{
var typeName = context.Request.QueryString["type"];
- if (string.IsNullOrEmpty(key))
+ if (string.IsNullOrEmpty(typeName))
{
// Bad request
context.Response.StatusCode = 400;
diff --git a/main/src/ReCode.Cocoon.Proxy.BlazorServer/ReCode.Cocoon.Proxy.BlazorServer.csproj b/main/src/ReCode.Cocoon.Proxy.BlazorServer/ReCode.Cocoon.Proxy.BlazorServer.csproj
index 5329d4e..0dfa816 100644
--- a/main/src/ReCode.Cocoon.Proxy.BlazorServer/ReCode.Cocoon.Proxy.BlazorServer.csproj
+++ b/main/src/ReCode.Cocoon.Proxy.BlazorServer/ReCode.Cocoon.Proxy.BlazorServer.csproj
@@ -7,6 +7,9 @@
+
diff --git a/main/src/ReCode.Cocoon.Proxy.BlazorWasm/CocoonProxyBlazorWasmRouting.cs b/main/src/ReCode.Cocoon.Proxy.BlazorWasm/CocoonProxyBlazorWasmRouting.cs
index 2c6e2b5..99c1117 100644
--- a/main/src/ReCode.Cocoon.Proxy.BlazorWasm/CocoonProxyBlazorWasmRouting.cs
+++ b/main/src/ReCode.Cocoon.Proxy.BlazorWasm/CocoonProxyBlazorWasmRouting.cs
@@ -10,20 +10,35 @@ namespace Microsoft.AspNetCore.Routing
{
public static class CocoonProxyBlazorWasmRouting
{
- public static IEndpointRouteBuilder MapCocoonProxyWithBlazor(this IEndpointRouteBuilder endpoints, Type programType) =>
- MapCocoonProxyWithBlazor(endpoints, BlazorRouteDiscovery.FindRoutes(programType));
+ public static IEndpointRouteBuilder MapCocoonProxyWithBlazor(this IEndpointRouteBuilder endpoints, Type type)
+ {
+ Func blazorTestFunc;
+ if (type.Name == "CocoonBlazorRouteTester")
+ {
+ var instance = Activator.CreateInstance(type);
+ var method = type.GetMethod("IsMatch");
+ blazorTestFunc = (Func) method!.CreateDelegate(typeof(Func), instance);
+ }
+ else
+ {
+ var blazorPaths = BlazorRouteDiscovery.FindRoutes(type);
+ var blazorRoutes = new BlazorRoutes(blazorPaths);
+ var method = typeof(BlazorRoutes).GetMethod("Contains");
+ blazorTestFunc = (Func) method!.CreateDelegate(typeof(Func), blazorRoutes);
+ }
- public static IEndpointRouteBuilder MapCocoonProxyWithBlazor(this IEndpointRouteBuilder endpoints, IEnumerable blazorPaths)
+ return MapCocoonProxyWithBlazor(endpoints, blazorTestFunc);
+ }
+
+ public static IEndpointRouteBuilder MapCocoonProxyWithBlazor(this IEndpointRouteBuilder endpoints, Func blazorRouteTest)
{
var cocoonProxy = endpoints.ServiceProvider.GetRequiredService();
- var blazorRoutes = new BlazorRoutes(blazorPaths);
-
var app = endpoints.CreateApplicationBuilder();
app.Use(async (httpContext, next) =>
{
- if (blazorRoutes.Contains(httpContext.Request.Path))
+ if (blazorRouteTest(httpContext.Request.Path))
{
httpContext.Request.Path = "/index.html";
diff --git a/main/src/ReCode.Cocoon.Proxy.BlazorWasm/RouteTesterAttribute.cs b/main/src/ReCode.Cocoon.Proxy.BlazorWasm/RouteTesterAttribute.cs
new file mode 100644
index 0000000..d5a9b88
--- /dev/null
+++ b/main/src/ReCode.Cocoon.Proxy.BlazorWasm/RouteTesterAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace ReCode.Cocoon.Proxy.Blazor
+{
+ [AttributeUsage(AttributeTargets.Class, Inherited = false)]
+ public sealed class RouteTesterAttribute : Attribute
+ {
+ public RouteTesterAttribute(params Type[] types)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/main/src/ReCode.Cocoon.Proxy/Authentication/MessageClaim.cs b/main/src/ReCode.Cocoon.Proxy/Authentication/MessageClaim.cs
index bf0f7ca..36e2a2c 100644
--- a/main/src/ReCode.Cocoon.Proxy/Authentication/MessageClaim.cs
+++ b/main/src/ReCode.Cocoon.Proxy/Authentication/MessageClaim.cs
@@ -11,22 +11,22 @@ namespace ReCode.Cocoon.Proxy.Authentication
public class MessageClaim
{
[Key(0)]
- public string Issuer { get; set; }
+ public string? Issuer { get; set; }
[Key(1)]
- public string OriginalIssuer { get; set; }
+ public string? OriginalIssuer { get; set; }
[Key(2)]
- public IDictionary Properties { get; set; }
+ public IDictionary? Properties { get; set; }
[Key(3)]
- public string Type { get; set; }
+ public string? Type { get; set; }
[Key(4)]
- public string Value { get; set; }
+ public string? Value { get; set; }
[Key(5)]
- public string ValueType { get; set; }
+ public string? ValueType { get; set; }
public Claim ToClaim()
{
diff --git a/main/src/ReCode.Cocoon.Proxy/Authentication/MessageIdentity.cs b/main/src/ReCode.Cocoon.Proxy/Authentication/MessageIdentity.cs
index 79a77f3..3becf04 100644
--- a/main/src/ReCode.Cocoon.Proxy/Authentication/MessageIdentity.cs
+++ b/main/src/ReCode.Cocoon.Proxy/Authentication/MessageIdentity.cs
@@ -12,25 +12,27 @@ namespace ReCode.Cocoon.Proxy.Authentication
public class MessageIdentity
{
[Key(0)]
- public string AuthenticationType { get; set; }
+ public string? AuthenticationType { get; set; }
[Key(1)]
public bool IsAuthenticated { get; set; }
[Key(2)]
- public string Label { get; set; }
+ public string? Label { get; set; }
[Key(3)]
- public string NameClaimType { get; set; }
+ public string? NameClaimType { get; set; }
[Key(4)]
- public string RoleClaimType { get; set; }
+ public string? RoleClaimType { get; set; }
[Key(5)]
- public List Claims { get; set; }
+ public List? Claims { get; set; }
public ClaimsIdentity ToClaimsIdentity()
{
+ if (Claims is null) return new ClaimsIdentity();
+
var claims = Claims.Select(c => c.ToClaim());
return new ClaimsIdentity(claims,
AuthenticationType, NameClaimType, RoleClaimType);
diff --git a/main/src/ReCode.Cocoon.Proxy/Authentication/MessagePrincipal.cs b/main/src/ReCode.Cocoon.Proxy/Authentication/MessagePrincipal.cs
index cebe575..42cbdea 100644
--- a/main/src/ReCode.Cocoon.Proxy/Authentication/MessagePrincipal.cs
+++ b/main/src/ReCode.Cocoon.Proxy/Authentication/MessagePrincipal.cs
@@ -12,10 +12,12 @@ namespace ReCode.Cocoon.Proxy.Authentication
public class MessagePrincipal
{
[Key(0)]
- public List Identities { get; set; }
+ public List? Identities { get; set; }
public ClaimsPrincipal ToClaimsPrincipal()
{
+ if (Identities is null) return new ClaimsPrincipal();
+
var identities =
Identities.Select(i => i.ToClaimsIdentity());
return new ClaimsPrincipal(identities);
diff --git a/main/src/ReCode.Cocoon.Proxy/Session/CocoonSession.cs b/main/src/ReCode.Cocoon.Proxy/Session/CocoonSession.cs
index d1c2f43..25f950d 100644
--- a/main/src/ReCode.Cocoon.Proxy/Session/CocoonSession.cs
+++ b/main/src/ReCode.Cocoon.Proxy/Session/CocoonSession.cs
@@ -51,6 +51,8 @@ public void Set(string key, T? value)
activity?.AddTag("key", key);
var bytes = await _client.GetAsync(key, _context.Request);
+ if (bytes is null) return default;
+
var value = SessionValueDeserializer.Deserialize(bytes);
CacheValue(key, bytes, value);
diff --git a/main/test/ReCode.Cocoon.Proxy.BlazorCodeGen.Tests/Bar.cs b/main/test/ReCode.Cocoon.Proxy.BlazorCodeGen.Tests/Bar.cs
new file mode 100644
index 0000000..8c90511
--- /dev/null
+++ b/main/test/ReCode.Cocoon.Proxy.BlazorCodeGen.Tests/Bar.cs
@@ -0,0 +1,8 @@
+namespace MySourceGenerator.Tests
+{
+ [Microsoft.AspNetCore.Components.RouteAttribute("bar")]
+ public class Bar
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/main/test/ReCode.Cocoon.Proxy.BlazorCodeGen.Tests/Dummy.cs b/main/test/ReCode.Cocoon.Proxy.BlazorCodeGen.Tests/Dummy.cs
new file mode 100644
index 0000000..faba2b5
--- /dev/null
+++ b/main/test/ReCode.Cocoon.Proxy.BlazorCodeGen.Tests/Dummy.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace Dummy
+{
+ [Route("dummy")]
+ public class Dummy
+ {
+
+ }
+
+ internal class RouteAttribute : Attribute
+ {
+ private readonly string _dummy;
+
+ public RouteAttribute(string dummy)
+ {
+ _dummy = dummy;
+ }
+ }
+}
\ No newline at end of file
diff --git a/main/test/ReCode.Cocoon.Proxy.BlazorCodeGen.Tests/Foo.cs b/main/test/ReCode.Cocoon.Proxy.BlazorCodeGen.Tests/Foo.cs
new file mode 100644
index 0000000..4046935
--- /dev/null
+++ b/main/test/ReCode.Cocoon.Proxy.BlazorCodeGen.Tests/Foo.cs
@@ -0,0 +1,16 @@
+using Microsoft.AspNetCore.Components;
+
+namespace MySourceGenerator.Tests
+{
+ [Route("foo")]
+ public class Foo
+ {
+
+ }
+
+ [Route("Admin/AdminPage")]
+ public class AdminPage
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/main/test/ReCode.Cocoon.Proxy.BlazorCodeGen.Tests/Quux.cs b/main/test/ReCode.Cocoon.Proxy.BlazorCodeGen.Tests/Quux.cs
new file mode 100644
index 0000000..121f397
--- /dev/null
+++ b/main/test/ReCode.Cocoon.Proxy.BlazorCodeGen.Tests/Quux.cs
@@ -0,0 +1,10 @@
+using Microsoft.AspNetCore.Components;
+
+namespace MySourceGenerator.Tests
+{
+ [Route("quux")]
+ public class Quux
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/main/test/ReCode.Cocoon.Proxy.BlazorCodeGen.Tests/ReCode.Cocoon.Proxy.BlazorCodeGen.Tests.csproj b/main/test/ReCode.Cocoon.Proxy.BlazorCodeGen.Tests/ReCode.Cocoon.Proxy.BlazorCodeGen.Tests.csproj
new file mode 100644
index 0000000..7e68479
--- /dev/null
+++ b/main/test/ReCode.Cocoon.Proxy.BlazorCodeGen.Tests/ReCode.Cocoon.Proxy.BlazorCodeGen.Tests.csproj
@@ -0,0 +1,27 @@
+
+
+
+ net5.0
+
+ false
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
diff --git a/main/test/ReCode.Cocoon.Proxy.BlazorCodeGen.Tests/RouteAttribute.cs b/main/test/ReCode.Cocoon.Proxy.BlazorCodeGen.Tests/RouteAttribute.cs
new file mode 100644
index 0000000..bbf4e0b
--- /dev/null
+++ b/main/test/ReCode.Cocoon.Proxy.BlazorCodeGen.Tests/RouteAttribute.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Microsoft.AspNetCore.Components
+{
+ public class RouteAttribute : Attribute
+ {
+ private readonly string _template;
+
+ public RouteAttribute(string template)
+ {
+ _template = template;
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Class, Inherited = false)]
+ public sealed class RouteTesterAttribute : Attribute
+ {
+ // See the attribute guidelines at
+ // http://go.microsoft.com/fwlink/?LinkId=85236
+ public RouteTesterAttribute(params Type[] types)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/main/test/ReCode.Cocoon.Proxy.BlazorCodeGen.Tests/UnitTest1.cs b/main/test/ReCode.Cocoon.Proxy.BlazorCodeGen.Tests/UnitTest1.cs
new file mode 100644
index 0000000..81a0aee
--- /dev/null
+++ b/main/test/ReCode.Cocoon.Proxy.BlazorCodeGen.Tests/UnitTest1.cs
@@ -0,0 +1,23 @@
+using System;
+using ReCode.Cocoon.Proxy.Blazor;
+using Xunit;
+
+namespace ReCode.Cocoon.Proxy.BlazorCodeGen.Tests
+{
+ public class UnitTest1
+ {
+ [Fact]
+ public void MatchesFoo()
+ {
+ var target = new CocoonBlazorRouteTester();
+ Assert.True(target.IsMatch("/foo"));
+ }
+
+ [Fact]
+ public void MatchesAdminPage()
+ {
+ var target = new CocoonBlazorRouteTester();
+ Assert.True(target.IsMatch("/Admin/AdminPage"));
+ }
+ }
+}
diff --git a/main/test/ReCode.Cocoon.Proxy.CodeGenerator.Tests/ReCode.Cocoon.Proxy.CodeGenerator.Tests.csproj b/main/test/ReCode.Cocoon.Proxy.CodeGenerator.Tests/ReCode.Cocoon.Proxy.CodeGenerator.Tests.csproj
new file mode 100644
index 0000000..0d56c8b
--- /dev/null
+++ b/main/test/ReCode.Cocoon.Proxy.CodeGenerator.Tests/ReCode.Cocoon.Proxy.CodeGenerator.Tests.csproj
@@ -0,0 +1,26 @@
+
+
+
+ net5.0
+
+ false
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
diff --git a/main/test/ReCode.Cocoon.Proxy.CodeGenerator.Tests/RouteTesterGeneratorTests.cs b/main/test/ReCode.Cocoon.Proxy.CodeGenerator.Tests/RouteTesterGeneratorTests.cs
new file mode 100644
index 0000000..0a12459
--- /dev/null
+++ b/main/test/ReCode.Cocoon.Proxy.CodeGenerator.Tests/RouteTesterGeneratorTests.cs
@@ -0,0 +1,84 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.Loader;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using ReCode.Cocoon.Proxy.BlazorCodeGen;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace RouteTesterGen.Tests
+{
+ public class RouteTesterGeneratorTests
+ {
+ private readonly ITestOutputHelper _output;
+ private Func _isMatch;
+
+ public RouteTesterGeneratorTests(ITestOutputHelper output)
+ {
+ _output = output;
+ }
+
+ [Theory]
+ [InlineData("/posts")]
+ [InlineData("/posts/42")]
+ [InlineData("/posts/42/edit")]
+ [InlineData("/people")]
+ [InlineData("/people/42")]
+ [InlineData("/people/42/edit")]
+ [InlineData("/files/foo/bar/quux.pdf")]
+ [InlineData("/Admin/AdminPage")]
+ public void MatchesPath(string path)
+ {
+ _isMatch ??= Build();
+ Assert.True(_isMatch(path));
+ }
+
+ private Func Build()
+ {
+ var routes = new[]
+ {
+ "/posts",
+ "/posts/{id}",
+ "/posts/{id}/edit",
+ "/people",
+ "/people/{id}",
+ "/people/{id}/edit",
+ "/files/{*path}",
+ "/Admin/AdminPage",
+ };
+ var target = new RouteTesterGenerator(routes);
+ var actual = target.Generate();
+
+ var assemblyName = Path.GetRandomFileName();
+ var references = new[]
+ {
+ typeof(object).Assembly.Location
+ }.Select(p => MetadataReference.CreateFromFile(p))
+ .ToArray();
+ var syntax = CSharpSyntaxTree.ParseText(actual);
+ var compilation = CSharpCompilation.Create(assemblyName, new[] {syntax},
+ references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
+ using var ms = new MemoryStream();
+ var result = compilation.Emit(ms);
+ if (result.Diagnostics.Length > 0)
+ {
+ foreach (var diagnostic in result.Diagnostics)
+ {
+ _output.WriteLine(diagnostic.ToString());
+ }
+ }
+ Assert.True(result.Success);
+ ms.Position = 0;
+ var assembly = AssemblyLoadContext.Default.LoadFromStream(ms);
+ var type = assembly.GetType("ReCode.Cocoon.Proxy.Blazor.CocoonBlazorRouteTester");
+ Assert.NotNull(type);
+ var method = type.GetMethod("IsMatch");
+ Assert.NotNull(method);
+ var obj = Activator.CreateInstance(type);
+ return method.CreateDelegate>(obj);
+ }
+ }
+}
\ No newline at end of file
diff --git a/main/test/ReCode.Cocoon.Proxy.CodeGenerator.Tests/UnitTest1.cs b/main/test/ReCode.Cocoon.Proxy.CodeGenerator.Tests/UnitTest1.cs
new file mode 100644
index 0000000..e5992b9
--- /dev/null
+++ b/main/test/ReCode.Cocoon.Proxy.CodeGenerator.Tests/UnitTest1.cs
@@ -0,0 +1,14 @@
+using System;
+using Xunit;
+
+namespace ReCode.Cocoon.Proxy.CodeGenerator.Tests
+{
+ public class UnitTest1
+ {
+ [Fact]
+ public void Test1()
+ {
+
+ }
+ }
+}
diff --git a/samples/BlazorCocoon/Server/BlazorCocoon.Server.csproj b/samples/BlazorCocoon/Server/BlazorCocoon.Server.csproj
index be7f7ed..60709b5 100644
--- a/samples/BlazorCocoon/Server/BlazorCocoon.Server.csproj
+++ b/samples/BlazorCocoon/Server/BlazorCocoon.Server.csproj
@@ -10,15 +10,15 @@
-
-
-
-
+
+
+
+
-
+