diff --git a/README.md b/README.md index 3bbce70..c971dd3 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ | CI | Status | Platform(s) | Framework(s) | Test Framework(s) | | --- | --- | --- | --- | --- | -| [AppVeyor][app-veyor] | [![Build Status][app-veyor-shield]][app-veyor] | `Windows` | `nestandard2.0` | `netcoreapp2.2.0` | +| [AppVeyor][app-veyor] | [![Build Status][app-veyor-shield]][app-veyor] | `Windows` | `nestandard2.0` | `netcoreapp3.1` | Allows to route a `SQS` message to a specific endpoint on the `Worker` instead of having a single endpoint handling all the messages. @@ -22,12 +22,12 @@ StronglyTypedMessage model = new StronglyTypedMessage(); var sendMessageRequest = new SendMessageRequest { - // Serialize your model as JSON - MessageBody = JsonConvert.SerializeObject(model) - // Set the QueueUrl + // Serialize your model as JSON (you can use Newtonsoft.Json if you prefer) + MessageBody = System.Text.Json.JsonSerializer.Serialize(model) + // Set the QueueUrl and other properties as you see fit }; -// AddRoutingAttribute is an extension method +// AddRoutingAttribute is an extension method in the "BeanstalkWorker.SimpleRouting" namespace sendMessageRequest.MessageAttributes.AddRoutingAttribute("task-name"); ``` @@ -37,19 +37,19 @@ A sample `Web` app is provided in [samples/SampleWeb](samples/SampleWeb). You can send two distinct types of messages by hitting two different endpoints: -- `GET /send/work` -- `GET /send/nothing` +- `GET http://localhost:5000/send/work` +- `GET http://localhost:5000/send/nothing` ##### Configuration Create a `iAM` user (if you don't have one already) which has access to `SQS`. -You'll need to configure four settings, either using [user secrets][secret-manager] (preferred way as they'll be shared with the sample worker), `appsettings.json` or via [environment variables][environment-variables]: +You'll need to configure four settings using [user secrets][secret-manager]: - `Aws:RegionSystemName` - [region code][available-regions], for example `ap-southeast-2` - `Aws:Queue:WorkerQueueUrl` - `URL` of the `SQS` queue, for example `https://sqs.ap-southeast-2.amazonaws.com/375985941080/dev-gabriel` -- `AWS_ACCESS_KEY_ID` - this is the `Access key ID` of your `iAM user` -- `AWS_SECRET_ACCESS_KEY` - this is the `Secret access key` of your `iAM user` +- `Aws:Queue:AccessKeyId` - this is the `Access key ID` of your `iAM user` +- `Aws:Queue:SecretAccessKey` - this is the `Secret access key` of your `iAM user` ### Worker Tier @@ -60,9 +60,12 @@ In the `Configure` method of your `Startup` class: ```csharp public void Configure(IApplicationBuilder app) { + // The simple routing middleware needs to be added **before** configuring endpoint routing app.UseHeaderRouting(); - // Abbreviated for clarity + app.UseRouting(); + + app.UseEndpoints(endpoint => endpoint.MapControllers()); } ``` @@ -71,9 +74,10 @@ public void Configure(IApplicationBuilder app) ```csharp // This is important, we do not want a prefix in front of the action's route [Route("")] -public class SomeController : Controller +[ApiController] +public class SomeController : ControllerBase { - // The route has to match the argument given to AddRoutingAttribute + // The route template has to match the argument given to AddRoutingAttribute [HttpPost("task-name")] public async Task SomeMethod(StronglyTypedMessage model) { @@ -108,4 +112,3 @@ If you wish to run the `Worker` without deploying to `AWS Beanstalk` you can lev [app-veyor]: https://ci.appveyor.com/project/GabrielWeyer/simple-routing [app-veyor-shield]: https://ci.appveyor.com/api/projects/status/github/gabrielweyer/simple-routing?branch=master&svg=true [secret-manager]: https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-2.1&tabs=windows#secret-manager -[environment-variables]: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-2.1#environment-variables-configuration-provider diff --git a/samples/Core/Core.csproj b/samples/Core/Core.csproj index 2aa45c4..5831477 100644 --- a/samples/Core/Core.csproj +++ b/samples/Core/Core.csproj @@ -1,15 +1,14 @@  - netcoreapp2.1 + netcoreapp3.1 BeanstalkWorker.SimpleRouting.Core BeanstalkWorker.SimpleRouting.Core false - - - - - + + + + diff --git a/samples/Core/Models/DoNothingMessage.cs b/samples/Core/Models/DoNothingMessage.cs index 59d9830..8e94b7c 100644 --- a/samples/Core/Models/DoNothingMessage.cs +++ b/samples/Core/Models/DoNothingMessage.cs @@ -4,6 +4,6 @@ namespace BeanstalkWorker.SimpleRouting.Core.Models { public class DoNothingMessage { - public TimeSpan RestDuration { get; set; } + public DateTimeOffset StartAt { get; set; } } } diff --git a/samples/Core/Models/DoWorkMessage.cs b/samples/Core/Models/DoWorkMessage.cs index 1ce75ea..8ee13bb 100644 --- a/samples/Core/Models/DoWorkMessage.cs +++ b/samples/Core/Models/DoWorkMessage.cs @@ -5,6 +5,6 @@ namespace BeanstalkWorker.SimpleRouting.Core.Models public class DoWorkMessage { public string NatureOfWork { get; set; } - public TimeSpan ExpectedDurationOfWork { get; set; } + public DateTimeOffset StartsAt { get; set; } } } diff --git a/samples/SampleWeb/Program.cs b/samples/SampleWeb/Program.cs index 1c2f2b4..ead1e15 100644 --- a/samples/SampleWeb/Program.cs +++ b/samples/SampleWeb/Program.cs @@ -1,11 +1,5 @@ -using System; -using Amazon.SQS.Model; -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Serilog; -using Serilog.Core; -using Serilog.Events; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; namespace BeanstalkWorker.SimpleRouting.SampleWeb { @@ -13,117 +7,17 @@ public class Program { public static void Main(string[] args) { - BuildWebHost(args).Run(); + BuildWebHost(args).Build().Run(); } - private static IWebHost BuildWebHost(string[] args) + private static IHostBuilder BuildWebHost(string[] args) { - var webHostBuilder = WebHost.CreateDefaultBuilder(args); - - var contentRoot = webHostBuilder.GetSetting("contentRoot"); - var environment = webHostBuilder.GetSetting("ENVIRONMENT"); - - var isDevelopment = EnvironmentName.Development.Equals(environment); - - var configurationBuilder = new ConfigurationBuilder() - .SetBasePath(contentRoot) - .AddJsonFile("appsettings.json", false, false) - .AddEnvironmentVariables(); - - if (isDevelopment) - { - configurationBuilder.AddUserSecrets(); - } - - var configuration = configurationBuilder.Build(); - - var serilogLevel = configuration.GetLoggingLevel("MinimumLevel:Default"); - - var loggerConfiguration = new LoggerConfiguration() - .Destructure.ByTransforming(a => new {a.DataType, a.StringValue}) - .Enrich.WithDemystifiedStackTraces() - .ReadFrom.Configuration(configuration); - - if (isDevelopment) - { - loggerConfiguration = loggerConfiguration.WriteTo.Console(serilogLevel); - } - - var logger = loggerConfiguration.CreateLogger(); - - try - { - logger.Information("Starting Host..."); - - SetAwsEnvironmentVariables(configuration, logger); - - return webHostBuilder - .UseStartup() - .UseConfiguration(configuration) - .UseSerilog(logger, true) - .Build(); - } - catch (Exception ex) - { - logger.Fatal(ex, "Host terminated unexpectedly"); - throw; - } - } - - private static void SetAwsEnvironmentVariables(IConfigurationRoot configuration, Logger logger) - { - const string awsAccessKeyIdVariableName = "AWS_ACCESS_KEY_ID"; - const string awsSecretAccessKeyVariableName = "AWS_SECRET_ACCESS_KEY"; - - var accessKeyIdFromEnvironmentVariable = Environment.GetEnvironmentVariable(awsAccessKeyIdVariableName); - var secretAccessKeyFromEnvironmentVariable = Environment.GetEnvironmentVariable(awsSecretAccessKeyVariableName); - - if (!string.IsNullOrWhiteSpace(accessKeyIdFromEnvironmentVariable) && - !string.IsNullOrWhiteSpace(secretAccessKeyFromEnvironmentVariable)) - { - logger.Information($"'{awsAccessKeyIdVariableName}' and '{awsSecretAccessKeyVariableName}' set via environment variables"); - - return; - } - - var accessKeyIdFromConfiguration = configuration.GetValue(awsAccessKeyIdVariableName); - var secretAccessKeyFromConfiguration = configuration.GetValue(awsSecretAccessKeyVariableName); - - if (!string.IsNullOrWhiteSpace(accessKeyIdFromConfiguration) && - !string.IsNullOrWhiteSpace(secretAccessKeyFromConfiguration)) - { - logger.Information($"'{awsAccessKeyIdVariableName}' and '{awsSecretAccessKeyVariableName}' present in configuration, setting matching environment variables"); - - Environment.SetEnvironmentVariable( - awsAccessKeyIdVariableName, - accessKeyIdFromConfiguration, - EnvironmentVariableTarget.Process); - - Environment.SetEnvironmentVariable( - awsSecretAccessKeyVariableName, - secretAccessKeyFromConfiguration, - EnvironmentVariableTarget.Process); - } - else - { - throw new InvalidOperationException($"'{awsAccessKeyIdVariableName}' and '{awsSecretAccessKeyVariableName}' should either be set as environment variables or configuration, please refer to the README: https://github.com/gabrielweyer/simple-routing/blob/master/README.md#configuration."); - } - } - } - - internal static class ConfigurationRootExtensions - { - internal static LogEventLevel GetLoggingLevel(this IConfigurationRoot configuration, string keyName, - LogEventLevel defaultLevel = LogEventLevel.Warning) - { - try - { - return configuration.GetValue($"Serilog:{keyName}", LogEventLevel.Warning); - } - catch (Exception) - { - return defaultLevel; - } + return Host + .CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); } } } diff --git a/samples/SampleWeb/SampleWeb.csproj b/samples/SampleWeb/SampleWeb.csproj index 6c8315c..4e5f4b9 100644 --- a/samples/SampleWeb/SampleWeb.csproj +++ b/samples/SampleWeb/SampleWeb.csproj @@ -1,19 +1,12 @@  - netcoreapp2.2 + netcoreapp3.1 fa5b7428-c384-484b-bf75-1d9b2d1526a0 BeanstalkWorker.SimpleRouting.SampleWeb BeanstalkWorker.SimpleRouting.SampleWeb - - - - - - - - + diff --git a/samples/SampleWeb/SendController.cs b/samples/SampleWeb/SendController.cs index c2c7356..d821017 100644 --- a/samples/SampleWeb/SendController.cs +++ b/samples/SampleWeb/SendController.cs @@ -1,12 +1,13 @@ using System; using System.Threading.Tasks; -using BeanstalkWorker.SimpleRouting.Core.Logic; using BeanstalkWorker.SimpleRouting.Core.Models; using Microsoft.AspNetCore.Mvc; namespace BeanstalkWorker.SimpleRouting.SampleWeb { - public class SendController : Controller + [ApiController] + [Route("send")] + public class SendController : ControllerBase { private readonly ISqsClient _sqsClient; @@ -15,22 +16,24 @@ public SendController(ISqsClient sqsClient) _sqsClient = sqsClient; } + [Route("work")] public async Task Work() { var body = new DoWorkMessage { - ExpectedDurationOfWork = TimeSpan.FromSeconds(3), - NatureOfWork = "Not much" + NatureOfWork = "Not much", + StartsAt = DateTimeOffset.UtcNow.AddYears(3) }; await _sqsClient.SendDoWorkMessageAsync(body); } + [Route("nothing")] public async Task Nothing() { var body = new DoNothingMessage { - RestDuration = TimeSpan.FromDays(3) + StartAt = DateTimeOffset.UtcNow.AddSeconds(1) }; await _sqsClient.SendDoNothingMessageAsync(body); diff --git a/samples/Core/Logic/SqsClient.cs b/samples/SampleWeb/SqsClient.cs similarity index 93% rename from samples/Core/Logic/SqsClient.cs rename to samples/SampleWeb/SqsClient.cs index a61af1b..79ba134 100644 --- a/samples/Core/Logic/SqsClient.cs +++ b/samples/SampleWeb/SqsClient.cs @@ -5,9 +5,8 @@ using BeanstalkWorker.SimpleRouting.Core.Options; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using Newtonsoft.Json; -namespace BeanstalkWorker.SimpleRouting.Core.Logic +namespace BeanstalkWorker.SimpleRouting.SampleWeb { public class SqsClient : ISqsClient { @@ -49,7 +48,7 @@ SendMessageRequest GenerateRequest() { var sendMessageRequest = new SendMessageRequest { - MessageBody = JsonConvert.SerializeObject(body), + MessageBody = System.Text.Json.JsonSerializer.Serialize(body), QueueUrl = _queueOptions.WorkerQueueUrl.ToString() }; diff --git a/samples/SampleWeb/Startup.cs b/samples/SampleWeb/Startup.cs index 1b9f931..12d7246 100644 --- a/samples/SampleWeb/Startup.cs +++ b/samples/SampleWeb/Startup.cs @@ -1,10 +1,7 @@ using Amazon; using Amazon.SQS; -using BeanstalkWorker.SimpleRouting.Core.Logic; using BeanstalkWorker.SimpleRouting.Core.Options; using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -25,21 +22,16 @@ public void ConfigureServices(IServiceCollection services) ConfigureOptions(services); - services.AddOptions(); services - .AddMvc() - .SetCompatibilityVersion(CompatibilityVersion.Version_2_2); + .AddOptions() + .AddControllers(); } - public void Configure(IApplicationBuilder app, IHostingEnvironment env) + public void Configure(IApplicationBuilder app) { - app.UseMvc(routes => - { - routes.MapRoute( - name: "default", - template: "{controller}/{action}/{id?}", - defaults: new {controller = "Send", action = "Nothing"}); - }); + app.UseRouting(); + + app.UseEndpoints(endpoint => endpoint.MapControllers()); } private void ConfigureOptions(IServiceCollection services) @@ -54,7 +46,10 @@ private void AddServices(IServiceCollection services) var systemName = _configuration.GetValue("Aws:RegionSystemName"); var regionEndpoint = RegionEndpoint.GetBySystemName(systemName); - return new AmazonSQSClient(regionEndpoint); + var accessKeyId = _configuration.GetValue("Aws:Queue:AccessKeyId"); + var secretAccessKey = _configuration.GetValue("Aws:Queue:SecretAccessKey"); + + return new AmazonSQSClient(accessKeyId, secretAccessKey, regionEndpoint); }); services.AddScoped(); } diff --git a/samples/SampleWeb/appsettings.json b/samples/SampleWeb/appsettings.json index 89fe056..35b286f 100644 --- a/samples/SampleWeb/appsettings.json +++ b/samples/SampleWeb/appsettings.json @@ -5,13 +5,11 @@ "WorkerQueueUrl": "" } }, - "Serilog": { - "MinimumLevel": { - "Default": "Verbose", - "Override": { - "Microsoft": "Information", - "System": "Information" - } + "Logging": { + "LogLevel": { + "Default": "Debug", + "Microsoft": "Information", + "Microsoft.Hosting.Lifetime": "Information" } } } diff --git a/samples/SampleWorker/Program.cs b/samples/SampleWorker/Program.cs index 3b1434a..4bec85e 100644 --- a/samples/SampleWorker/Program.cs +++ b/samples/SampleWorker/Program.cs @@ -1,10 +1,5 @@ -using System; -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Serilog; -using Serilog.Core; -using Serilog.Events; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; namespace BeanstalkWorker.SimpleRouting.SampleWorker { @@ -12,115 +7,17 @@ public class Program { public static void Main(string[] args) { - BuildWebHost(args).Run(); + BuildWebHost(args).Build().Run(); } - private static IWebHost BuildWebHost(string[] args) + private static IHostBuilder BuildWebHost(string[] args) { - var webHostBuilder = WebHost.CreateDefaultBuilder(args); - - var contentRoot = webHostBuilder.GetSetting("contentRoot"); - var environment = webHostBuilder.GetSetting("ENVIRONMENT"); - - var isDevelopment = EnvironmentName.Development.Equals(environment); - - var configurationBuilder = new ConfigurationBuilder() - .SetBasePath(contentRoot) - .AddJsonFile("appsettings.json", false, false) - .AddEnvironmentVariables(); - - if (isDevelopment) - { - configurationBuilder.AddUserSecrets(); - } - - var configuration = configurationBuilder.Build(); - - var serilogLevel = configuration.GetLoggingLevel("MinimumLevel:Default"); - - var loggerConfiguration = new LoggerConfiguration() - .ReadFrom.Configuration(configuration) - .Enrich.WithDemystifiedStackTraces(); - - if (isDevelopment) - { - loggerConfiguration = loggerConfiguration.WriteTo.Console(serilogLevel); - } - - var logger = loggerConfiguration.CreateLogger(); - - try - { - logger.Information("Starting Host..."); - - SetAwsEnvironmentVariables(configuration, logger); - - return webHostBuilder - .UseStartup() - .UseConfiguration(configuration) - .UseSerilog(logger, true) - .Build(); - } - catch (Exception ex) - { - logger.Fatal(ex, "Host terminated unexpectedly"); - throw; - } - } - - private static void SetAwsEnvironmentVariables(IConfigurationRoot configuration, Logger logger) - { - const string awsAccessKeyIdVariableName = "AWS_ACCESS_KEY_ID"; - const string awsSecretAccessKeyVariableName = "AWS_SECRET_ACCESS_KEY"; - - var accessKeyIdFromEnvironmentVariable = Environment.GetEnvironmentVariable(awsAccessKeyIdVariableName); - var secretAccessKeyFromEnvironmentVariable = Environment.GetEnvironmentVariable(awsSecretAccessKeyVariableName); - - if (!string.IsNullOrWhiteSpace(accessKeyIdFromEnvironmentVariable) && - !string.IsNullOrWhiteSpace(secretAccessKeyFromEnvironmentVariable)) - { - logger.Information($"'{awsAccessKeyIdVariableName}' and '{awsSecretAccessKeyVariableName}' set via environment variables"); - - return; - } - - var accessKeyIdFromConfiguration = configuration.GetValue(awsAccessKeyIdVariableName); - var secretAccessKeyFromConfiguration = configuration.GetValue(awsSecretAccessKeyVariableName); - - if (!string.IsNullOrWhiteSpace(accessKeyIdFromConfiguration) && - !string.IsNullOrWhiteSpace(secretAccessKeyFromConfiguration)) - { - logger.Information($"'{awsAccessKeyIdVariableName}' and '{awsSecretAccessKeyVariableName}' present in configuration, setting matching environment variables"); - - Environment.SetEnvironmentVariable( - awsAccessKeyIdVariableName, - accessKeyIdFromConfiguration, - EnvironmentVariableTarget.Process); - - Environment.SetEnvironmentVariable( - awsSecretAccessKeyVariableName, - secretAccessKeyFromConfiguration, - EnvironmentVariableTarget.Process); - } - else - { - throw new InvalidOperationException($"'{awsAccessKeyIdVariableName}' and '{awsSecretAccessKeyVariableName}' should either be set as environment variables or configuration, please refer to the README: https://github.com/gabrielweyer/simple-routing/blob/master/README.md#configuration."); - } - } - } - - internal static class ConfigurationRootExtensions - { - internal static LogEventLevel GetLoggingLevel(this IConfigurationRoot configuration, string keyName, LogEventLevel defaultLevel = LogEventLevel.Warning) - { - try - { - return configuration.GetValue($"Serilog:{keyName}", LogEventLevel.Warning); - } - catch (Exception) - { - return defaultLevel; - } + return Host. + CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); } } } diff --git a/samples/SampleWorker/SampleWorker.csproj b/samples/SampleWorker/SampleWorker.csproj index 5eae72b..283dc70 100644 --- a/samples/SampleWorker/SampleWorker.csproj +++ b/samples/SampleWorker/SampleWorker.csproj @@ -1,19 +1,10 @@  - netcoreapp2.2 + netcoreapp3.1 fa5b7428-c384-484b-bf75-1d9b2d1526a0 BeanstalkWorker.SimpleRouting.SampleWorker BeanstalkWorker.SimpleRouting.SampleWorker - - - - - - - - - diff --git a/samples/SampleWorker/Startup.cs b/samples/SampleWorker/Startup.cs index 4a2c245..752aa7a 100644 --- a/samples/SampleWorker/Startup.cs +++ b/samples/SampleWorker/Startup.cs @@ -1,26 +1,24 @@ using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; namespace BeanstalkWorker.SimpleRouting.SampleWorker { public class Startup { - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { services - .AddMvc() - .SetCompatibilityVersion(CompatibilityVersion.Version_2_2); + .AddControllers(); } - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app) { + // The simple routing middleware needs to be added **before** configuring endpoint routing app.UseHeaderRouting(); - app.UseMvc(); + app.UseRouting(); + + app.UseEndpoints(endpoint => endpoint.MapControllers()); } } } diff --git a/samples/SampleWorker/WorkerController.cs b/samples/SampleWorker/WorkerController.cs index a3d995a..5c47e42 100644 --- a/samples/SampleWorker/WorkerController.cs +++ b/samples/SampleWorker/WorkerController.cs @@ -5,7 +5,8 @@ namespace BeanstalkWorker.SimpleRouting.SampleWorker { [Route("")] - public class WorkerController : Controller + [ApiController] + public class WorkerController : ControllerBase { private readonly ILogger _logger; @@ -17,7 +18,7 @@ public WorkerController(ILogger logger) [HttpPost(WorkerConstants.DoNothingTaskName)] public IActionResult DoNothing(DoNothingMessage model) { - _logger.LogDebug("Received message {@Message}", model); + _logger.LogDebug("Received order to do nothing starting at {StartAt}", model.StartAt); return Ok(); } @@ -25,7 +26,7 @@ public IActionResult DoNothing(DoNothingMessage model) [HttpPost(WorkerConstants.DoWorkTaskName)] public IActionResult DoWork(DoWorkMessage model) { - _logger.LogDebug("Received message {@Message}", model); + _logger.LogDebug("Received order to do {WorkType} starting at {StartAt}", model.NatureOfWork, model.StartsAt); return Ok(); } diff --git a/samples/SampleWorker/appsettings.json b/samples/SampleWorker/appsettings.json index acf3fc7..b84d4f4 100644 --- a/samples/SampleWorker/appsettings.json +++ b/samples/SampleWorker/appsettings.json @@ -1,11 +1,9 @@ { - "Serilog": { - "MinimumLevel": { - "Default": "Verbose", - "Override": { - "Microsoft": "Information", - "System": "Information" - } + "Logging": { + "LogLevel": { + "Default": "Debug", + "Microsoft": "Information", + "Microsoft.Hosting.Lifetime": "Information" } } } diff --git a/src/BeanstalkWorker.SimpleRouting/BeanstalkWorker.SimpleRouting.csproj b/src/BeanstalkWorker.SimpleRouting/BeanstalkWorker.SimpleRouting.csproj index 8606c04..1d8d35a 100644 --- a/src/BeanstalkWorker.SimpleRouting/BeanstalkWorker.SimpleRouting.csproj +++ b/src/BeanstalkWorker.SimpleRouting/BeanstalkWorker.SimpleRouting.csproj @@ -13,10 +13,10 @@ snupkg - + - - - + + + diff --git a/tests/BeanstalkWorker.SimpleRouting.Tests/BeanstalkWorker.SimpleRouting.Tests.csproj b/tests/BeanstalkWorker.SimpleRouting.Tests/BeanstalkWorker.SimpleRouting.Tests.csproj index 3eddd5c..f06ca37 100644 --- a/tests/BeanstalkWorker.SimpleRouting.Tests/BeanstalkWorker.SimpleRouting.Tests.csproj +++ b/tests/BeanstalkWorker.SimpleRouting.Tests/BeanstalkWorker.SimpleRouting.Tests.csproj @@ -1,11 +1,10 @@  - netcoreapp2.2 - 2.2.0 + netcoreapp3.1 false - + @@ -14,9 +13,9 @@ - - + + - +