From 589cab520b1e23a88bbfac5ed96b992e2a6b8166 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Sun, 30 May 2021 15:04:33 +0200 Subject: [PATCH] Add Conductor project and SendCommand activity --- Elsa.sln | 14 ++++++ .../Activities/SendCommand.cs | 46 +++++++++++++++++++ .../Consumers/SendCommandConsumer.cs | 14 ++++++ .../Elsa.Activities.Conductor.csproj | 23 ++++++++++ .../ElsaOptionsBuilderExtensions.cs | 37 +++++++++++++++ .../Elsa.Activities.Conductor/FodyWeavers.xml | 3 ++ .../IsExternalInit.cs | 17 +++++++ .../Models/SendCommandModel.cs | 4 ++ .../Options/ConductorOptions.cs | 23 ++++++++++ .../Services/RemoteApplicationClient.cs | 38 +++++++++++++++ .../Workflows/RunWorkflow/RunWorkflow.cs | 5 +- .../Elsa.Samples.Server.Host.csproj | 1 + .../Elsa.Samples.Server.Host/Startup.cs | 4 +- .../Elsa.Samples.Server.Host/appsettings.json | 3 ++ .../Controllers/ElsaHookController.cs | 21 +++++++++ .../server/SampleClientApp.Web/Program.cs | 17 +++++++ .../Properties/launchSettings.json | 31 +++++++++++++ .../SampleClientApp.Web.csproj | 12 +++++ .../server/SampleClientApp.Web/Startup.cs | 35 ++++++++++++++ .../appsettings.Development.json | 9 ++++ .../SampleClientApp.Web/appsettings.json | 10 ++++ 21 files changed, 363 insertions(+), 4 deletions(-) create mode 100644 src/activities/Elsa.Activities.Conductor/Activities/SendCommand.cs create mode 100644 src/activities/Elsa.Activities.Conductor/Consumers/SendCommandConsumer.cs create mode 100644 src/activities/Elsa.Activities.Conductor/Elsa.Activities.Conductor.csproj create mode 100644 src/activities/Elsa.Activities.Conductor/Extensions/ElsaOptionsBuilderExtensions.cs create mode 100644 src/activities/Elsa.Activities.Conductor/FodyWeavers.xml create mode 100644 src/activities/Elsa.Activities.Conductor/IsExternalInit.cs create mode 100644 src/activities/Elsa.Activities.Conductor/Models/SendCommandModel.cs create mode 100644 src/activities/Elsa.Activities.Conductor/Options/ConductorOptions.cs create mode 100644 src/activities/Elsa.Activities.Conductor/Services/RemoteApplicationClient.cs create mode 100644 src/samples/server/SampleClientApp.Web/Controllers/ElsaHookController.cs create mode 100644 src/samples/server/SampleClientApp.Web/Program.cs create mode 100644 src/samples/server/SampleClientApp.Web/Properties/launchSettings.json create mode 100644 src/samples/server/SampleClientApp.Web/SampleClientApp.Web.csproj create mode 100644 src/samples/server/SampleClientApp.Web/Startup.cs create mode 100644 src/samples/server/SampleClientApp.Web/appsettings.Development.json create mode 100644 src/samples/server/SampleClientApp.Web/appsettings.json diff --git a/Elsa.sln b/Elsa.sln index f8d7e567f..6130fa6d7 100644 --- a/Elsa.sln +++ b/Elsa.sln @@ -297,6 +297,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Providers.Redis", "src EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.DistributedLocking.Redis", "src\locking\Elsa.DistributedLocking.Redis\Elsa.DistributedLocking.Redis.csproj", "{D1644D32-AA51-4D10-942E-F2722DB963B4}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Activities.Conductor", "src\activities\Elsa.Activities.Conductor\Elsa.Activities.Conductor.csproj", "{E62077E1-59F4-4937-B45B-59F86417BCF8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleClientApp.Web", "src\samples\server\SampleClientApp.Web\SampleClientApp.Web.csproj", "{7756E22A-AD59-46C1-A019-1D28D7217347}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -695,6 +699,14 @@ Global {D1644D32-AA51-4D10-942E-F2722DB963B4}.Debug|Any CPU.Build.0 = Debug|Any CPU {D1644D32-AA51-4D10-942E-F2722DB963B4}.Release|Any CPU.ActiveCfg = Release|Any CPU {D1644D32-AA51-4D10-942E-F2722DB963B4}.Release|Any CPU.Build.0 = Release|Any CPU + {E62077E1-59F4-4937-B45B-59F86417BCF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E62077E1-59F4-4937-B45B-59F86417BCF8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E62077E1-59F4-4937-B45B-59F86417BCF8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E62077E1-59F4-4937-B45B-59F86417BCF8}.Release|Any CPU.Build.0 = Release|Any CPU + {7756E22A-AD59-46C1-A019-1D28D7217347}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7756E22A-AD59-46C1-A019-1D28D7217347}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7756E22A-AD59-46C1-A019-1D28D7217347}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7756E22A-AD59-46C1-A019-1D28D7217347}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -830,6 +842,8 @@ Global {EC5D4AFD-3F7F-4B51-9C38-F18C60618731} = {DA71CDAA-8DD3-4D5F-9FBD-8E4B37A2D925} {9ACA06DA-9AFE-41A2-8109-EFED8B9B14A1} = {EC5D4AFD-3F7F-4B51-9C38-F18C60618731} {D1644D32-AA51-4D10-942E-F2722DB963B4} = {DBBD242E-4437-4BDB-919F-A70839BE75FA} + {E62077E1-59F4-4937-B45B-59F86417BCF8} = {B43B546E-23F3-46E8-ACB7-D04F05CDA180} + {7756E22A-AD59-46C1-A019-1D28D7217347} = {BBCFC623-2113-464D-8A1F-3CCDABF1241C} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8B0975FD-7050-48B0-88C5-48C33378E158} diff --git a/src/activities/Elsa.Activities.Conductor/Activities/SendCommand.cs b/src/activities/Elsa.Activities.Conductor/Activities/SendCommand.cs new file mode 100644 index 000000000..0c9448995 --- /dev/null +++ b/src/activities/Elsa.Activities.Conductor/Activities/SendCommand.cs @@ -0,0 +1,46 @@ +using System.Threading.Tasks; +using Elsa.Activities.Conductor.Models; +using Elsa.ActivityResults; +using Elsa.Attributes; +using Elsa.Design; +using Elsa.Expressions; +using Elsa.Services; +using Elsa.Services.Models; + +// ReSharper disable once CheckNamespace +namespace Elsa.Activities.Conductor +{ + [Activity( + Category = "Conductor", + Description = "Sends a command to your application.", + Outcomes = new[] { OutcomeNames.Done } + )] + public class SendCommand : Activity + { + private readonly IEventPublisher _eventPublisher; + + public SendCommand(IEventPublisher eventPublisher) + { + _eventPublisher = eventPublisher; + } + + [ActivityInput( + Label = "Command", + Hint = "The command to send.", + SupportedSyntaxes = new[] { SyntaxNames.JavaScript, SyntaxNames.Liquid } + )] + public string CommandName { get; set; } = default!; + + [ActivityInput( + UIHint = ActivityInputUIHints.MultiLine, + Hint = "Optional data to send to your application.", + SupportedSyntaxes = new[] { SyntaxNames.JavaScript, SyntaxNames.Liquid, SyntaxNames.Json })] + public object? Payload { get; set; } = default!; + + protected override async ValueTask OnExecuteAsync(ActivityExecutionContext context) + { + await _eventPublisher.PublishAsync(new SendCommandModel(CommandName, Payload)); + return Done(); + } + } +} \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Conductor/Consumers/SendCommandConsumer.cs b/src/activities/Elsa.Activities.Conductor/Consumers/SendCommandConsumer.cs new file mode 100644 index 000000000..393c78360 --- /dev/null +++ b/src/activities/Elsa.Activities.Conductor/Consumers/SendCommandConsumer.cs @@ -0,0 +1,14 @@ +using System.Threading.Tasks; +using Elsa.Activities.Conductor.Models; +using Elsa.Activities.Conductor.Services; +using Rebus.Handlers; + +namespace Elsa.Activities.Conductor.Consumers +{ + public class SendCommandConsumer : IHandleMessages + { + private readonly RemoteApplicationClient _remoteApplicationClient; + public SendCommandConsumer(RemoteApplicationClient remoteApplicationClient) => _remoteApplicationClient = remoteApplicationClient; + public async Task Handle(SendCommandModel message) => await _remoteApplicationClient.SendCommandAsync(message.Command, message.Payload); + } +} \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Conductor/Elsa.Activities.Conductor.csproj b/src/activities/Elsa.Activities.Conductor/Elsa.Activities.Conductor.csproj new file mode 100644 index 000000000..ad155e286 --- /dev/null +++ b/src/activities/Elsa.Activities.Conductor/Elsa.Activities.Conductor.csproj @@ -0,0 +1,23 @@ + + + + + + + netstandard2.1 + + Elsa is a set of workflow libraries and tools that enable lean and mean workflowing capabilities in any .NET Core application. + This package provides activities to implement conductor-style workflows where Elsa sends commands to your application, which responds asynchronously with events. + + elsa, workflows, conductor + + + + + + + + + + + diff --git a/src/activities/Elsa.Activities.Conductor/Extensions/ElsaOptionsBuilderExtensions.cs b/src/activities/Elsa.Activities.Conductor/Extensions/ElsaOptionsBuilderExtensions.cs new file mode 100644 index 000000000..69b96a87b --- /dev/null +++ b/src/activities/Elsa.Activities.Conductor/Extensions/ElsaOptionsBuilderExtensions.cs @@ -0,0 +1,37 @@ +using System; +using Elsa.Activities.Conductor.Consumers; +using Elsa.Activities.Conductor.Models; +using Elsa.Activities.Conductor.Options; +using Elsa.Activities.Conductor.Services; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Polly; + +namespace Elsa.Activities.Conductor.Extensions +{ + public static class ElsaOptionsBuilderExtensions + { + public static ElsaOptionsBuilder AddConductorActivities(this ElsaOptionsBuilder elsa, Action? configureOptions = default, Action? configureHttpClient = default) + { + var services = elsa.Services; + + if (configureOptions != null) + services.Configure(configureOptions); + + var httpClientBuilder = services.AddHttpClient((sp, httpClient) => + { + var options = sp.GetRequiredService>().Value; + httpClient.BaseAddress = options.ApplicationHookUrl; + }); + + if (configureHttpClient == null) + httpClientBuilder.AddTransientHttpErrorPolicy(x => x.WaitAndRetryAsync(10, retryCount => TimeSpan.FromSeconds(Math.Pow(2, retryCount)))); + else + configureHttpClient(httpClientBuilder); + + elsa.AddActivitiesFrom(); + elsa.AddCompetingConsumer(); + return elsa; + } + } +} \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Conductor/FodyWeavers.xml b/src/activities/Elsa.Activities.Conductor/FodyWeavers.xml new file mode 100644 index 000000000..00e1d9a1c --- /dev/null +++ b/src/activities/Elsa.Activities.Conductor/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Conductor/IsExternalInit.cs b/src/activities/Elsa.Activities.Conductor/IsExternalInit.cs new file mode 100644 index 000000000..475dd51b6 --- /dev/null +++ b/src/activities/Elsa.Activities.Conductor/IsExternalInit.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.ComponentModel; + +// ReSharper disable once CheckNamespace +namespace System.Runtime.CompilerServices +{ + /// + /// Reserved to be used by the compiler for tracking metadata. + /// This class should not be used by developers in source code. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + internal static class IsExternalInit + { + } +} \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Conductor/Models/SendCommandModel.cs b/src/activities/Elsa.Activities.Conductor/Models/SendCommandModel.cs new file mode 100644 index 000000000..da2a67e9a --- /dev/null +++ b/src/activities/Elsa.Activities.Conductor/Models/SendCommandModel.cs @@ -0,0 +1,4 @@ +namespace Elsa.Activities.Conductor.Models +{ + public record SendCommandModel(string Command, object? Payload); +} \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Conductor/Options/ConductorOptions.cs b/src/activities/Elsa.Activities.Conductor/Options/ConductorOptions.cs new file mode 100644 index 000000000..d106d6337 --- /dev/null +++ b/src/activities/Elsa.Activities.Conductor/Options/ConductorOptions.cs @@ -0,0 +1,23 @@ +using System; +using Newtonsoft.Json; +using NodaTime; +using NodaTime.Serialization.JsonNet; + +namespace Elsa.Activities.Conductor.Options +{ + public class ConductorOptions + { + public ConductorOptions() + { + SerializerSettings = new JsonSerializerSettings(); + SerializerSettings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb); + } + + /// + /// The URL to post commands to. + /// + public Uri ApplicationHookUrl { get; set; } = default!; + + public JsonSerializerSettings SerializerSettings { get; set; } + } +} \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Conductor/Services/RemoteApplicationClient.cs b/src/activities/Elsa.Activities.Conductor/Services/RemoteApplicationClient.cs new file mode 100644 index 000000000..9ac73ec4e --- /dev/null +++ b/src/activities/Elsa.Activities.Conductor/Services/RemoteApplicationClient.cs @@ -0,0 +1,38 @@ +using System.Net.Http; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Elsa.Activities.Conductor.Options; +using Microsoft.Extensions.Options; +using Newtonsoft.Json; + +namespace Elsa.Activities.Conductor.Services +{ + public class RemoteApplicationClient + { + private readonly HttpClient _httpClient; + private readonly ConductorOptions _options; + + public RemoteApplicationClient(HttpClient httpClient, IOptions options) + { + _httpClient = httpClient; + _options = options.Value; + } + + public async Task SendCommandAsync(string command, object? payload, CancellationToken cancellationToken = default) + { + payload ??= new object(); + + var model = new + { + Command = command, + Payload = payload + }; + + var json = JsonConvert.SerializeObject(model, _options.SerializerSettings); + var content = new StringContent(json, Encoding.UTF8, "application/json"); + + await _httpClient.PostAsync("", content, cancellationToken); + } + } +} \ No newline at end of file diff --git a/src/core/Elsa.Core/Activities/Workflows/RunWorkflow/RunWorkflow.cs b/src/core/Elsa.Core/Activities/Workflows/RunWorkflow/RunWorkflow.cs index ac908bc3e..ca235106b 100644 --- a/src/core/Elsa.Core/Activities/Workflows/RunWorkflow/RunWorkflow.cs +++ b/src/core/Elsa.Core/Activities/Workflows/RunWorkflow/RunWorkflow.cs @@ -64,9 +64,10 @@ namespace Elsa.Activities.Workflows public string? ContextId { get; set; } [ActivityInput( - UIHint = ActivityInputUIHints.Json, + UIHint = ActivityInputUIHints.MultiLine, Hint = "Optional custom attributes to associate with the workflow to run.", - Category = PropertyCategories.Advanced)] + Category = PropertyCategories.Advanced, + SupportedSyntaxes = new[] { SyntaxNames.JavaScript, SyntaxNames.Liquid, SyntaxNames.Json })] public Variables? CustomAttributes { get; set; } = default!; [ActivityInput( diff --git a/src/samples/server/Elsa.Samples.Server.Host/Elsa.Samples.Server.Host.csproj b/src/samples/server/Elsa.Samples.Server.Host/Elsa.Samples.Server.Host.csproj index ca5c59dc6..57ee696f2 100644 --- a/src/samples/server/Elsa.Samples.Server.Host/Elsa.Samples.Server.Host.csproj +++ b/src/samples/server/Elsa.Samples.Server.Host/Elsa.Samples.Server.Host.csproj @@ -9,6 +9,7 @@ + diff --git a/src/samples/server/Elsa.Samples.Server.Host/Startup.cs b/src/samples/server/Elsa.Samples.Server.Host/Startup.cs index 272b9aa29..3e65e596b 100644 --- a/src/samples/server/Elsa.Samples.Server.Host/Startup.cs +++ b/src/samples/server/Elsa.Samples.Server.Host/Startup.cs @@ -1,3 +1,4 @@ +using Elsa.Activities.Conductor.Extensions; using Elsa.Activities.UserTask.Extensions; using Elsa.Persistence.EntityFramework.Core.Extensions; using Elsa.Persistence.EntityFramework.Sqlite; @@ -16,8 +17,6 @@ namespace Elsa.Samples.Server.Host { Environment = environment; Configuration = configuration; - - //BsonClassMap.RegisterClassMap(cm => { cm.AutoMap(); }); } private IWebHostEnvironment Environment { get; } @@ -58,6 +57,7 @@ namespace Elsa.Samples.Server.Host //.AddHangfireTemporalActivities(hangfire => hangfire.UseSqlServerStorage(sqlServerConnectionString), (_, hangfireServer) => hangfireServer.SchedulePollingInterval = TimeSpan.FromSeconds(5)) .AddJavaScriptActivities() .AddUserTaskActivities() + .AddConductorActivities(options => elsaSection.GetSection("Conductor").Bind(options)) .AddActivitiesFrom() .AddWorkflowsFrom() ); diff --git a/src/samples/server/Elsa.Samples.Server.Host/appsettings.json b/src/samples/server/Elsa.Samples.Server.Host/appsettings.json index d7cfd71ea..23dbe9218 100644 --- a/src/samples/server/Elsa.Samples.Server.Host/appsettings.json +++ b/src/samples/server/Elsa.Samples.Server.Host/appsettings.json @@ -24,6 +24,9 @@ "Host": "localhost", "Port": "2525", "DefaultSender": "noreply@acme.com" + }, + "Conductor": { + "ApplicationHookUrl": "https://localhost:16001/elsa-hook" } } } diff --git a/src/samples/server/SampleClientApp.Web/Controllers/ElsaHookController.cs b/src/samples/server/SampleClientApp.Web/Controllers/ElsaHookController.cs new file mode 100644 index 000000000..a7badcf3d --- /dev/null +++ b/src/samples/server/SampleClientApp.Web/Controllers/ElsaHookController.cs @@ -0,0 +1,21 @@ +using System; +using System.Text.Json; +using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json.Linq; + +namespace SampleClientApp.Web.Controllers +{ + [ApiController] + [Route("elsa-hook")] + public class ElsaHookController : ControllerBase + { + [HttpPost] + public IActionResult Post(ElsaCommand model) + { + Console.WriteLine("Received command {0} with payload {1}", model.Command, model.Payload); + return Ok(); + } + } + + public record ElsaCommand(string Command, JsonElement Payload); +} \ No newline at end of file diff --git a/src/samples/server/SampleClientApp.Web/Program.cs b/src/samples/server/SampleClientApp.Web/Program.cs new file mode 100644 index 000000000..c6978971d --- /dev/null +++ b/src/samples/server/SampleClientApp.Web/Program.cs @@ -0,0 +1,17 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; + +namespace SampleClientApp.Web +{ + 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(); }); + } +} \ No newline at end of file diff --git a/src/samples/server/SampleClientApp.Web/Properties/launchSettings.json b/src/samples/server/SampleClientApp.Web/Properties/launchSettings.json new file mode 100644 index 000000000..df7d00556 --- /dev/null +++ b/src/samples/server/SampleClientApp.Web/Properties/launchSettings.json @@ -0,0 +1,31 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "https://localhost:16001", + "sslPort": 16001 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "SampleClientApp.Web": { + "commandName": "Project", + "dotnetRunMessages": "true", + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:16001", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/src/samples/server/SampleClientApp.Web/SampleClientApp.Web.csproj b/src/samples/server/SampleClientApp.Web/SampleClientApp.Web.csproj new file mode 100644 index 000000000..70110db0a --- /dev/null +++ b/src/samples/server/SampleClientApp.Web/SampleClientApp.Web.csproj @@ -0,0 +1,12 @@ + + + + net6.0 + + + + + + + + diff --git a/src/samples/server/SampleClientApp.Web/Startup.cs b/src/samples/server/SampleClientApp.Web/Startup.cs new file mode 100644 index 000000000..b76daf699 --- /dev/null +++ b/src/samples/server/SampleClientApp.Web/Startup.cs @@ -0,0 +1,35 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace SampleClientApp.Web +{ + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + public void ConfigureServices(IServiceCollection services) + { + services.AddControllers(); + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseRouting(); + app.UseAuthorization(); + app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); + } + } +} \ No newline at end of file diff --git a/src/samples/server/SampleClientApp.Web/appsettings.Development.json b/src/samples/server/SampleClientApp.Web/appsettings.Development.json new file mode 100644 index 000000000..8983e0fc1 --- /dev/null +++ b/src/samples/server/SampleClientApp.Web/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git a/src/samples/server/SampleClientApp.Web/appsettings.json b/src/samples/server/SampleClientApp.Web/appsettings.json new file mode 100644 index 000000000..d9d9a9bff --- /dev/null +++ b/src/samples/server/SampleClientApp.Web/appsettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" +}