Skip to content

Commit 9a4a497

Browse files
authored
Merge pull request #36 from jkone27/add-samples
Add samples (also C#)
2 parents 536db14 + 746b8b3 commit 9a4a497

File tree

13 files changed

+331
-0
lines changed

13 files changed

+331
-0
lines changed

.fantomasignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
samples
2+
samples/**

samples/web/Web.Sample.sln

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.0.31903.59
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{969848AF-660B-4C8F-A732-86958A0A3F9D}"
7+
EndProject
8+
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Web.Sample", "src\Web.Sample\Web.Sample.fsproj", "{09C4FAA7-792D-48F0-9AD0-77D99B5B337D}"
9+
EndProject
10+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{D3FA0092-6D80-4228-A143-E35105DAD823}"
11+
EndProject
12+
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Web.Sample.Test", "test\Web.Sample.Test\Web.Sample.Test.fsproj", "{16F1F95C-D971-4F35-B1BA-D0CD6A7F5569}"
13+
EndProject
14+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Web.Sample.Csharp.Test", "test\Web.Sample.Csharp.Test\Web.Sample.Csharp.Test.csproj", "{F9662931-A238-4FAD-81D9-50D81885EC55}"
15+
EndProject
16+
Global
17+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
18+
Debug|Any CPU = Debug|Any CPU
19+
Release|Any CPU = Release|Any CPU
20+
EndGlobalSection
21+
GlobalSection(SolutionProperties) = preSolution
22+
HideSolutionNode = FALSE
23+
EndGlobalSection
24+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
25+
{09C4FAA7-792D-48F0-9AD0-77D99B5B337D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
26+
{09C4FAA7-792D-48F0-9AD0-77D99B5B337D}.Debug|Any CPU.Build.0 = Debug|Any CPU
27+
{09C4FAA7-792D-48F0-9AD0-77D99B5B337D}.Release|Any CPU.ActiveCfg = Release|Any CPU
28+
{09C4FAA7-792D-48F0-9AD0-77D99B5B337D}.Release|Any CPU.Build.0 = Release|Any CPU
29+
{16F1F95C-D971-4F35-B1BA-D0CD6A7F5569}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
30+
{16F1F95C-D971-4F35-B1BA-D0CD6A7F5569}.Debug|Any CPU.Build.0 = Debug|Any CPU
31+
{16F1F95C-D971-4F35-B1BA-D0CD6A7F5569}.Release|Any CPU.ActiveCfg = Release|Any CPU
32+
{16F1F95C-D971-4F35-B1BA-D0CD6A7F5569}.Release|Any CPU.Build.0 = Release|Any CPU
33+
{F9662931-A238-4FAD-81D9-50D81885EC55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
34+
{F9662931-A238-4FAD-81D9-50D81885EC55}.Debug|Any CPU.Build.0 = Debug|Any CPU
35+
{F9662931-A238-4FAD-81D9-50D81885EC55}.Release|Any CPU.ActiveCfg = Release|Any CPU
36+
{F9662931-A238-4FAD-81D9-50D81885EC55}.Release|Any CPU.Build.0 = Release|Any CPU
37+
EndGlobalSection
38+
GlobalSection(NestedProjects) = preSolution
39+
{09C4FAA7-792D-48F0-9AD0-77D99B5B337D} = {969848AF-660B-4C8F-A732-86958A0A3F9D}
40+
{16F1F95C-D971-4F35-B1BA-D0CD6A7F5569} = {D3FA0092-6D80-4228-A143-E35105DAD823}
41+
{F9662931-A238-4FAD-81D9-50D81885EC55} = {D3FA0092-6D80-4228-A143-E35105DAD823}
42+
EndGlobalSection
43+
EndGlobal
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
namespace Web.Sample
2+
3+
#nowarn 20 // to avoid |> ignore everywhere in aspnet config files
4+
5+
open System
6+
open Microsoft.AspNetCore.Builder
7+
open Microsoft.Extensions.Hosting
8+
open Microsoft.Extensions.DependencyInjection
9+
open System.Threading.Tasks
10+
open Microsoft.AspNetCore.Http
11+
12+
module Clients =
13+
open System.Net.Http
14+
open System.Net.Http.Json
15+
16+
module Routes =
17+
let name = "/hello/name"
18+
let age = "/hello/age"
19+
20+
let ``localhost:5000`` (httpClient: HttpClient) =
21+
httpClient.BaseAddress <- "http://localhost" |> Uri
22+
23+
type ClientOne(httpClient: HttpClient) =
24+
member this.GetNameAsync() =
25+
httpClient.GetFromJsonAsync<{| Name: string |}>(Routes.name)
26+
27+
type ClientTwo(httpClient: HttpClient) =
28+
member this.GetAgeAsync() =
29+
httpClient.GetFromJsonAsync<{| Age: int |}>(Routes.age)
30+
31+
32+
module Services =
33+
open Clients
34+
35+
let routeOne = "/service-one"
36+
37+
type ServiceOne(clientOne: ClientOne, clientTwo: ClientTwo) =
38+
member this.GetAndPrintAsync() =
39+
task {
40+
let! name = clientOne.GetNameAsync()
41+
let! age = clientTwo.GetAgeAsync()
42+
43+
return $"name: {name}, age:{age}"
44+
}
45+
46+
// IMPORTANT: needed for WebApplicationFactory<T>
47+
type Program() = class end
48+
49+
// entry point is allowed only in let function bindings, so we need to also have this
50+
module Program =
51+
52+
[<EntryPoint>]
53+
let main args =
54+
55+
let builder =
56+
WebApplication.CreateBuilder(args)
57+
|> fun x ->
58+
x.Services.AddHttpClient<Clients.ClientOne>(Clients.``localhost:5000``)
59+
x.Services.AddHttpClient<Clients.ClientTwo>(Clients.``localhost:5000``)
60+
x.Services.AddTransient<Services.ServiceOne>()
61+
x
62+
63+
let app = builder.Build()
64+
65+
// our app service is invoked in this route
66+
app.MapPost(Services.routeOne, Func<HttpContext, _>(fun c ->
67+
task {
68+
let s = c.RequestServices.GetRequiredService<Services.ServiceOne>()
69+
70+
let! r = s.GetAndPrintAsync()
71+
72+
return r
73+
})
74+
)
75+
76+
// test api client against these endpoints to avoid extra server hosting in app / containers etc
77+
app.MapGet("/hello/name", Func<{| Name: string |}>(fun () -> {| Name = "john" |}))
78+
app.MapGet("/hello/age", Func<{| Age: int |}>(fun () -> {| Age = 25 |}))
79+
80+
app.Run()
81+
82+
0 // Exit code
83+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"$schema": "https://json.schemastore.org/launchsettings.json",
3+
"profiles": {
4+
"http": {
5+
"commandName": "Project",
6+
"dotnetRunMessages": true,
7+
"launchBrowser": true,
8+
"applicationUrl": "http://localhost:5003",
9+
"environmentVariables": {
10+
"ASPNETCORE_ENVIRONMENT": "Development"
11+
}
12+
},
13+
"https": {
14+
"commandName": "Project",
15+
"dotnetRunMessages": true,
16+
"launchBrowser": true,
17+
"applicationUrl": "https://localhost:7222;http://localhost:5003",
18+
"environmentVariables": {
19+
"ASPNETCORE_ENVIRONMENT": "Development"
20+
}
21+
}
22+
}
23+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net9.0</TargetFramework>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<Compile Include="Program.fs" />
9+
<!-- <InternalsVisibleTo Include="../../test/Web.Sample.Test" /> not working in F# -->
10+
</ItemGroup>
11+
12+
</Project>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft.AspNetCore": "Warning"
6+
}
7+
}
8+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft.AspNetCore": "Warning"
6+
}
7+
},
8+
"AllowedHosts": "*"
9+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
namespace Web.Sample.Csharp.Test;
2+
3+
using System;
4+
using Xunit;
5+
using ApiStub.FSharp;
6+
using System.Threading.Tasks;
7+
using static ApiStub.FSharp.CE;
8+
using Web.Sample;
9+
using System.Net.Http.Json;
10+
using Microsoft.AspNetCore.Mvc.Testing;
11+
12+
public class CSharpTests
13+
{
14+
private static WebApplicationFactory<Web.Sample.Program> getWebAppFactory()
15+
{
16+
// create an instance of the test client builder
17+
var b = new TestClient<Web.Sample.Program>();
18+
19+
return
20+
b.GetJson(b, Clients.Routes.name, new { Name = "Peter" })
21+
.GetJson(b, Clients.Routes.age, new { Age = 100 })
22+
.GetFactory();
23+
}
24+
25+
// one app factory instance is oke for all tests
26+
private static readonly WebApplicationFactory<Program> webAppFactory = getWebAppFactory();
27+
28+
[Fact]
29+
public async Task CsharpTest_Peter_is_100_years_old()
30+
{
31+
var client = webAppFactory.CreateClient();
32+
33+
var response = await client.PostAsJsonAsync<object>(Services.routeOne, new { });
34+
35+
var responseText = await response.Content.ReadAsStringAsync();
36+
37+
Assert.True(response.IsSuccessStatusCode);
38+
Assert.Contains("Peter", responseText);
39+
Assert.Contains("100", responseText);
40+
}
41+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net9.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
<IsPackable>false</IsPackable>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<PackageReference Include="coverlet.collector" Version="6.0.2" />
12+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
13+
<PackageReference Include="xunit" Version="2.9.2" />
14+
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
15+
</ItemGroup>
16+
17+
<ItemGroup>
18+
<Using Include="Xunit" />
19+
</ItemGroup>
20+
21+
<ItemGroup>
22+
<ProjectReference Include="..\..\..\..\ApiStub.FSharp\ApiStub.FSharp.fsproj" />
23+
<ProjectReference Include="..\..\src\Web.Sample\Web.Sample.fsproj" />
24+
</ItemGroup>
25+
26+
</Project>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
Microsoft Visual Studio Solution File, Format Version 12.00
2+
# Visual Studio Version 17
3+
VisualStudioVersion = 17.5.2.0
4+
MinimumVisualStudioVersion = 10.0.40219.1
5+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Web.Sample.Csharp.Test", "Web.Sample.Csharp.Test.csproj", "{D3F1722C-8D94-E4DB-11A4-2B388C9C4387}"
6+
EndProject
7+
Global
8+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
9+
Debug|Any CPU = Debug|Any CPU
10+
Release|Any CPU = Release|Any CPU
11+
EndGlobalSection
12+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
13+
{D3F1722C-8D94-E4DB-11A4-2B388C9C4387}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
14+
{D3F1722C-8D94-E4DB-11A4-2B388C9C4387}.Debug|Any CPU.Build.0 = Debug|Any CPU
15+
{D3F1722C-8D94-E4DB-11A4-2B388C9C4387}.Release|Any CPU.ActiveCfg = Release|Any CPU
16+
{D3F1722C-8D94-E4DB-11A4-2B388C9C4387}.Release|Any CPU.Build.0 = Release|Any CPU
17+
EndGlobalSection
18+
GlobalSection(SolutionProperties) = preSolution
19+
HideSolutionNode = FALSE
20+
EndGlobalSection
21+
GlobalSection(ExtensibilityGlobals) = postSolution
22+
SolutionGuid = {C9FE6498-48D8-4424-8EEB-EFAF6CDD9104}
23+
EndGlobalSection
24+
EndGlobal

0 commit comments

Comments
 (0)