diff --git a/samples/frontend-backend/backend/Program.cs b/samples/frontend-backend/backend/Program.cs new file mode 100644 index 00000000..1b93b20d --- /dev/null +++ b/samples/frontend-backend/backend/Program.cs @@ -0,0 +1,20 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; + +namespace Backend +{ + public class Program + { + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); + } +} diff --git a/samples/frontend-backend/backend/Properties/launchSettings.json b/samples/frontend-backend/backend/Properties/launchSettings.json new file mode 100644 index 00000000..f70f5fcd --- /dev/null +++ b/samples/frontend-backend/backend/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:21017", + "sslPort": 44378 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "backend": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:5001;http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/samples/frontend-backend/backend/Startup.cs b/samples/frontend-backend/backend/Startup.cs new file mode 100644 index 00000000..66b18200 --- /dev/null +++ b/samples/frontend-backend/backend/Startup.cs @@ -0,0 +1,59 @@ +using System.Net; +using System.Text.Json; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http.Features; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; + +namespace Backend +{ + public class Startup + { + private readonly JsonSerializerOptions options = new JsonSerializerOptions() + { + PropertyNameCaseInsensitive = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + }; + + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseRouting(); + + app.UseEndpoints(endpoints => + { + endpoints.MapGet("/", async context => + { + var connection = context.Features.Get(); + var backendInfo = new BackendInfo() + { + IP = connection.LocalIpAddress.ToString(), + Hostname = Dns.GetHostName(), + }; + + context.Response.ContentType = "application/json; charset=utf-8"; + await JsonSerializer.SerializeAsync(context.Response.Body, backendInfo); + }); + }); + } + + class BackendInfo + { + public string IP { get; set; } = default!; + + public string Hostname { get; set; } = default!; + } + } +} diff --git a/samples/frontend-backend/backend/appsettings.Development.json b/samples/frontend-backend/backend/appsettings.Development.json new file mode 100644 index 00000000..dba68eb1 --- /dev/null +++ b/samples/frontend-backend/backend/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git a/samples/frontend-backend/backend/appsettings.json b/samples/frontend-backend/backend/appsettings.json new file mode 100644 index 00000000..81ff8777 --- /dev/null +++ b/samples/frontend-backend/backend/appsettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" +} diff --git a/samples/frontend-backend/backend/backend.csproj b/samples/frontend-backend/backend/backend.csproj new file mode 100644 index 00000000..be7ce155 --- /dev/null +++ b/samples/frontend-backend/backend/backend.csproj @@ -0,0 +1,8 @@ + + + + netcoreapp3.1 + Backend + + + diff --git a/samples/frontend-backend/frontend-backend.sln b/samples/frontend-backend/frontend-backend.sln new file mode 100644 index 00000000..c6c3b95c --- /dev/null +++ b/samples/frontend-backend/frontend-backend.sln @@ -0,0 +1,48 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "backend", "backend\backend.csproj", "{E900C6D9-7A87-49E3-93E5-97E6402E3939}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "frontend", "frontend\frontend.csproj", "{3BCACB4B-8506-4A5C-B4EE-FC76627EBE11}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E900C6D9-7A87-49E3-93E5-97E6402E3939}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E900C6D9-7A87-49E3-93E5-97E6402E3939}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E900C6D9-7A87-49E3-93E5-97E6402E3939}.Debug|x64.ActiveCfg = Debug|Any CPU + {E900C6D9-7A87-49E3-93E5-97E6402E3939}.Debug|x64.Build.0 = Debug|Any CPU + {E900C6D9-7A87-49E3-93E5-97E6402E3939}.Debug|x86.ActiveCfg = Debug|Any CPU + {E900C6D9-7A87-49E3-93E5-97E6402E3939}.Debug|x86.Build.0 = Debug|Any CPU + {E900C6D9-7A87-49E3-93E5-97E6402E3939}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E900C6D9-7A87-49E3-93E5-97E6402E3939}.Release|Any CPU.Build.0 = Release|Any CPU + {E900C6D9-7A87-49E3-93E5-97E6402E3939}.Release|x64.ActiveCfg = Release|Any CPU + {E900C6D9-7A87-49E3-93E5-97E6402E3939}.Release|x64.Build.0 = Release|Any CPU + {E900C6D9-7A87-49E3-93E5-97E6402E3939}.Release|x86.ActiveCfg = Release|Any CPU + {E900C6D9-7A87-49E3-93E5-97E6402E3939}.Release|x86.Build.0 = Release|Any CPU + {3BCACB4B-8506-4A5C-B4EE-FC76627EBE11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3BCACB4B-8506-4A5C-B4EE-FC76627EBE11}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3BCACB4B-8506-4A5C-B4EE-FC76627EBE11}.Debug|x64.ActiveCfg = Debug|Any CPU + {3BCACB4B-8506-4A5C-B4EE-FC76627EBE11}.Debug|x64.Build.0 = Debug|Any CPU + {3BCACB4B-8506-4A5C-B4EE-FC76627EBE11}.Debug|x86.ActiveCfg = Debug|Any CPU + {3BCACB4B-8506-4A5C-B4EE-FC76627EBE11}.Debug|x86.Build.0 = Debug|Any CPU + {3BCACB4B-8506-4A5C-B4EE-FC76627EBE11}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3BCACB4B-8506-4A5C-B4EE-FC76627EBE11}.Release|Any CPU.Build.0 = Release|Any CPU + {3BCACB4B-8506-4A5C-B4EE-FC76627EBE11}.Release|x64.ActiveCfg = Release|Any CPU + {3BCACB4B-8506-4A5C-B4EE-FC76627EBE11}.Release|x64.Build.0 = Release|Any CPU + {3BCACB4B-8506-4A5C-B4EE-FC76627EBE11}.Release|x86.ActiveCfg = Release|Any CPU + {3BCACB4B-8506-4A5C-B4EE-FC76627EBE11}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/samples/frontend-backend/frontend/ConfigurationExtensions.cs b/samples/frontend-backend/frontend/ConfigurationExtensions.cs new file mode 100644 index 00000000..d912c4bb --- /dev/null +++ b/samples/frontend-backend/frontend/ConfigurationExtensions.cs @@ -0,0 +1,21 @@ +using System; + +namespace Microsoft.Extensions.Configuration +{ + public static class ConfigurationExtensions + { + public static Uri? GetServiceUri(this IConfiguration configuration, string name) + { + var host = configuration[$"service:{name}:host"]; + var port = configuration[$"service:{name}:port"]; + var protocol = configuration[$"service:{name}:protocol"] ?? "http"; + + if (string.IsNullOrEmpty(host) || port == null) + { + return null; + } + + return new Uri(protocol + "://" + host + ":" + port + "/"); + } + } +} \ No newline at end of file diff --git a/samples/frontend-backend/frontend/Program.cs b/samples/frontend-backend/frontend/Program.cs new file mode 100644 index 00000000..229478a8 --- /dev/null +++ b/samples/frontend-backend/frontend/Program.cs @@ -0,0 +1,20 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; + +namespace Frontend +{ + public class Program + { + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); + } +} diff --git a/samples/frontend-backend/frontend/Properties/launchSettings.json b/samples/frontend-backend/frontend/Properties/launchSettings.json new file mode 100644 index 00000000..d970bc99 --- /dev/null +++ b/samples/frontend-backend/frontend/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:16377", + "sslPort": 44392 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "frontend": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:5001;http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/samples/frontend-backend/frontend/Startup.cs b/samples/frontend-backend/frontend/Startup.cs new file mode 100644 index 00000000..987b842b --- /dev/null +++ b/samples/frontend-backend/frontend/Startup.cs @@ -0,0 +1,76 @@ +using System; +using System.Net; +using System.Net.Http; +using System.Text.Json; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace Frontend +{ + public class Startup + { + private readonly JsonSerializerOptions options = new JsonSerializerOptions() + { + PropertyNameCaseInsensitive = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + }; + + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + public void ConfigureServices(IServiceCollection services) + { + services.AddHealthChecks(); + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseRouting(); + + app.UseEndpoints(endpoints => + { + var httpClient = new HttpClient() + { + BaseAddress = Configuration.GetServiceUri("backend"), + }; + + endpoints.MapGet("/", async context => + { + var bytes = await httpClient.GetByteArrayAsync("/"); + var backendInfo = JsonSerializer.Deserialize(bytes, options); + + var connection = context.Features.Get(); + await context.Response.WriteAsync($"Frontend Listening IP: {connection.LocalIpAddress}{Environment.NewLine}"); + await context.Response.WriteAsync($"Frontend Hostname: {Dns.GetHostName()}{Environment.NewLine}"); + await context.Response.WriteAsync($"EnvVar Configuration value: {Configuration["App:Value"]}{Environment.NewLine}"); + + await context.Response.WriteAsync($"Backend Listening IP: {backendInfo.IP}{Environment.NewLine}"); + await context.Response.WriteAsync($"Backend Hostname: {backendInfo.Hostname}{Environment.NewLine}"); + }); + + endpoints.MapHealthChecks("/healthz"); + }); + } + + class BackendInfo + { + public string IP { get; set; } = default!; + + public string Hostname { get; set; } = default!; + } + } +} diff --git a/samples/frontend-backend/frontend/appsettings.Development.json b/samples/frontend-backend/frontend/appsettings.Development.json new file mode 100644 index 00000000..dba68eb1 --- /dev/null +++ b/samples/frontend-backend/frontend/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git a/samples/frontend-backend/frontend/appsettings.json b/samples/frontend-backend/frontend/appsettings.json new file mode 100644 index 00000000..81ff8777 --- /dev/null +++ b/samples/frontend-backend/frontend/appsettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" +} diff --git a/samples/frontend-backend/frontend/frontend.csproj b/samples/frontend-backend/frontend/frontend.csproj new file mode 100644 index 00000000..b936890f --- /dev/null +++ b/samples/frontend-backend/frontend/frontend.csproj @@ -0,0 +1,8 @@ + + + + netcoreapp3.1 + Frontend + + + diff --git a/samples/frontend-backend/tye.yaml b/samples/frontend-backend/tye.yaml new file mode 100644 index 00000000..74569f0a --- /dev/null +++ b/samples/frontend-backend/tye.yaml @@ -0,0 +1,12 @@ +# tye application configuration file +# read all about it at https://github.com/dotnet/tye +name: frontend-backend +services: +- name: backend + project: backend/backend.csproj + bindings: + - port: 5050 +- name: frontend + project: frontend/frontend.csproj + bindings: + - port: 5051