public async Task RunAsync(DateTime oldestDate) { _Log.LogInformation($"Deleting URL histories older than {oldestDate}."); var count = await _Context.DeleteUrlHistoriesOlderThan(oldestDate); _Log.LogInformation($"Deleted {count} URL histories older than {oldestDate}."); }
public async Task <ChannelConfigContainer> GetChannelConfigAsync(decimal channelId) { _Log.LogInformation($"Getting channel config for channel '{channelId}'."); var result = await _Context.GetChannelConfigAsync(channelId); _Log.LogInformation($"Got channel config for channel '{channelId}'."); return(result); }
public async Task <BroadcasterConfigContainer> GetBroadcasterConfigAsync(decimal channelId, string broadcaster) { _Log.LogInformation($"Getting channel config for channel '{channelId}'."); var result = await _Context.GetBroadcasterConfigAsync(channelId, broadcaster); _Log.LogInformation($"Got channel config for channel '{channelId}'."); return(result); }
public async Task <IActionResult> RunAsync() { _Log.LogInformation("Getting prefix dictionary."); var prefixDictionary = await _Context.GetPrefixDictionary(); _Log.LogInformation($"Got {prefixDictionary.Count} prefixes."); return(new OkObjectResult(prefixDictionary)); }
public async Task <IActionResult> RunAsync(JobConfigContainer container, decimal channelId) { _Log.LogInformation($"Channel {channelId} posting job config."); var result = await _Context.SetJobConfig(channelId, container); _Log.LogInformation($"Channel {channelId} posted job config."); return(new OkObjectResult(result)); }
public async Task <ChannelConfigContainer> PostChannelConfigAsync(decimal channelId, ChannelConfigContainer container) { _Log.LogInformation($"Posting channel config for channel '{channelId}'."); var result = await _Context.SetChannelConfigAsync(channelId, container); _Log.LogInformation($"Posted channel config for channel '{channelId}'."); return(result); }
public async Task <IActionResult> RunAsync(decimal channelId) { _Log.LogInformation($"Channel {channelId} deleting job config."); await _Context.DeleteJobConfig(channelId); _Log.LogInformation($"Channel {channelId} deleted job config."); return(new NoContentResult()); }
public async Task <IActionResult> RunAsync(decimal channelId) { _Log.LogInformation($"Channel {channelId} getting job config."); var container = await _Context.GetJobConfig(channelId); _Log.LogInformation($"Channel {channelId} got job config."); return(new OkObjectResult(container)); }
private void SetupHttpConnection(string baseUrl) { if (!UriIncludesHttpPrefex(baseUrl) && !UriIncludesHttpsPrefex(baseUrl)) { var errorMessage = $"URI is invalid because http(s) was not included in ${baseUrl}"; _loggerWrapper.LogInformation(errorMessage, GetType().Name, nameof(SetupHttpConnection), null); throw new ArgumentException(errorMessage, nameof(baseUrl)); } _loggerWrapper.LogInformation("Setting up http connection with base url of " + baseUrl, GetType().Name, nameof(SetupHttpConnection) + "()", null); IHttwrapConfiguration httwrapConfiguration = new HttwrapConfiguration(baseUrl); _httwrapClient = new HttwrapClient(httwrapConfiguration); }
public static void Main(string[] args) { var startUpCorrelationId = Guid.NewGuid().ToString(); try { var configuration = InitialiseConfiguration(new ConfigurationBuilder(), args).Build(); InitialiseLoggingAndErrorHandling(configuration); IWebHost host; using (_logger.BeginScopeWithCommonData(startUpCorrelationId, null, null, null, true, false)) { _logger.LogInformation("Logging is all set up and ready to go"); _logger.LogInformation("About to call BuildWebHost"); host = WebHost.CreateDefaultBuilder(args) .UseNLog() .ConfigureServices(services => { services.AddPlatformServices(); }) .ConfigureAppConfiguration(cfg => InitialiseConfiguration(cfg, args)) .ConfigureAppMetricsHostingConfiguration(options => { options.AllEndpointsPort = configuration.GetValue <int>("MetricsEndpoints:AllEndpointsPort"); }) .UseStartup <Startup>() .Build(); _logger.LogInformation("About to call webHost.Run"); } host.Run(); } catch (Exception ex) when(PassToErrorHandler(ex)) { // Do not interfere with what would ordinarily happen if we didn't try to intercept because // upstream components will likely be catching exceptions and / or the checking the return code _logger.LogInformation("Microservice about to throw unhandled exception. Process may be terminated."); throw; } _logger.LogInformation("Microservice instance is shutting down."); }
public async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] [RequestBodyType(typeof(GetNumberOfAddressesPerPostcodeInBoundaryRequest), "Get Number Of Addresses Per Postcode In Boundary")] GetNumberOfAddressesPerPostcodeInBoundaryRequest req, CancellationToken cancellationToken) { try { _logger.LogInformation("C# HTTP trigger function processed a request."); if (req.IsValid(out var validationResults)) { GetNumberOfAddressesPerPostcodeInBoundaryResponse response = await _mediator.Send(req, cancellationToken); return(new OkObjectResult(ResponseWrapper <GetNumberOfAddressesPerPostcodeInBoundaryResponse, AddressServiceErrorCode> .CreateSuccessfulResponse(response))); } else { return(new ObjectResult(ResponseWrapper <GetNumberOfAddressesPerPostcodeInBoundaryResponse, AddressServiceErrorCode> .CreateUnsuccessfulResponse(AddressServiceErrorCode.ValidationError, validationResults)) { StatusCode = 422 });; } } catch (Exception ex) { _logger.LogError($"Unhandled error in {nameof(GetNumberOfAddressesPerPostcodeInBoundary)}", ex); return(new ObjectResult(ResponseWrapper <GetNumberOfAddressesPerPostcodeInBoundaryResponse, AddressServiceErrorCode> .CreateUnsuccessfulResponse(AddressServiceErrorCode.UnhandledError, "Internal Error")) { StatusCode = StatusCodes.Status500InternalServerError }); } }
public async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestMessage reqAsHttpRequestMessage, CancellationToken cancellationToken) { try { NewRelic.Api.Agent.NewRelic.SetTransactionName("AddressService", "GetPostcodeCoordinates"); _logger.LogInformation("C# HTTP trigger function processed a request."); // accept compressed requests (can't do this with middleware) GetPostcodeCoordinatesRequest req = await HttpRequestMessageCompressionUtils.DeserialiseAsync <GetPostcodeCoordinatesRequest>(reqAsHttpRequestMessage); if (req.IsValid(out var validationResults)) { GetPostcodeCoordinatesResponse response = await _mediator.Send(req, cancellationToken); return(new OkObjectResult(ResponseWrapper <GetPostcodeCoordinatesResponse, AddressServiceErrorCode> .CreateSuccessfulResponse(response))); } else { return(new ObjectResult(ResponseWrapper <GetPostcodeCoordinatesResponse, AddressServiceErrorCode> .CreateUnsuccessfulResponse(AddressServiceErrorCode.ValidationError, validationResults)) { StatusCode = 422 }); } } catch (Exception ex) { _logger.LogErrorAndNotifyNewRelic($"Unhandled error in GetPostcodeCoordinates", ex); return(new ObjectResult(ResponseWrapper <GetPostcodeCoordinatesResponse, AddressServiceErrorCode> .CreateUnsuccessfulResponse(AddressServiceErrorCode.UnhandledError, "Internal Error")) { StatusCode = StatusCodes.Status500InternalServerError }); } }
public async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] GetJobsByFilterRequest req, CancellationToken cancellationToken) { try { _logger.LogInformation("GetJobsByFilter started"); GetJobsByFilterResponse response = await _mediator.Send(req, cancellationToken); return(new OkObjectResult(ResponseWrapper <GetJobsByFilterResponse, RequestServiceErrorCode> .CreateSuccessfulResponse(response))); } catch (PostCodeException exc) { _logger.LogErrorAndNotifyNewRelic($"{req.Postcode} is an invalid postcode", exc); return(new ObjectResult(ResponseWrapper <GetJobsByFilterResponse, RequestServiceErrorCode> .CreateUnsuccessfulResponse(RequestServiceErrorCode.ValidationError, "Invalid Postcode")) { StatusCode = StatusCodes.Status400BadRequest }); } catch (Exception exc) { _logger.LogErrorAndNotifyNewRelic("Exception occured in GetJobsByFilter", exc); return(new ObjectResult(ResponseWrapper <GetJobsByFilterResponse, RequestServiceErrorCode> .CreateUnsuccessfulResponse(RequestServiceErrorCode.InternalServerError, "Internal Error")) { StatusCode = StatusCodes.Status500InternalServerError }); } }
public async Task RunAsync(string trendingEndpoint) { var trendingResponse = await _GiphyWrapper.GetTrendingGifsAsync(trendingEndpoint); var count = await _Context.InsertNewTrendingGifs(trendingResponse.Data); _Log.LogInformation($"Inserted {count} URL caches."); }
public async Task <ChannelConfigContainer> DeleteBroadcasterConfigAsync(decimal channelId, string broadcaster) { if (string.IsNullOrEmpty(broadcaster)) { _Log.LogInformation($"Deleting broadcaster config for channel '{channelId}'."); await _Context.DeleteBroadcasterConfigAsync(channelId); _Log.LogInformation($"Deleted broadcaster config for channel '{channelId}'."); } else { _Log.LogInformation($"Deleting broadcaster config for channel '{channelId}' broadcaster '{broadcaster}'."); await _Context.DeleteBroadcasterConfigAsync(channelId, broadcaster); _Log.LogInformation($"Deleted broadcaster config for channel '{channelId}' broadcaster '{broadcaster}'."); } return(await _Context.GetChannelConfigAsync(channelId)); }
public async Task <List <PendingJobConfig> > GetContainers(int nowHour, List <int> currentValidMinutes) { _Log.LogInformation("Getting job configs."); var containers = await _Context.GetJobConfigsToRun(nowHour, currentValidMinutes); _Log.LogInformation($"Got {containers.Count} containers."); return(containers); }
public IActionResult Delete([FromRoute] int id, bool suspendOnly) { using (var _repository = _unitOfWork.GetRepository <EntityModel.ReferenceDataItem>()) { var entity = _repository.GetFirstOrDefault(predicate: e => e.ID == id); if (entity is null) { _logging.LogInformation($"Cannot delete item with Id '{id}' because it does not exist."); return(NotFound(id)); } _repository.Delete(id); } _unitOfWork.SaveChanges(); _logging.LogInformation($"Item with Id '{id}' deleted."); return(NoContent()); }
public async Task <IActionResult> RunAsync(int guildCount, long botId, List <StatPost> statPosts) { _Log.LogInformation("Posting stats."); foreach (var statPost in statPosts) { try { var requestUri = string.Format(statPost.UrlStringFormat, botId); var content = $"{{\"{statPost.GuildCountPropertyName}\":{guildCount}}}"; await _StatWrapper.PostStatAsync(requestUri, content, statPost.Token); } catch (StatPostException ex) { _Log.LogError(ex, $"Error posting stats."); } } _Log.LogInformation("Posted stats."); return(new NoContentResult()); }
public async Task Run([TimerTrigger("%TimedCacheRefresherCronExpression%")] TimerInfo timerInfo, CancellationToken cancellationToken, ILogger log) { _logger.LogInformation($"TimedCacheRefresher CRON trigger executed at : {DateTimeOffset.Now}"); Stopwatch stopwatch = Stopwatch.StartNew(); try { await _memDistCache.RefreshDataAsync(async (token) => await _volunteersForCacheGetter.GetAllVolunteersAsync(token), CacheKey.AllCachedVolunteerDtos.ToString(), cancellationToken); } catch (Exception ex) { _logger.LogError("Error running TimedCacheRefresher", ex); throw; } stopwatch.Stop(); _logger.LogInformation($"TimedCacheRefresher CRON trigger took: {stopwatch.Elapsed:%m' min '%s' sec'}"); }
public async Task <PostBroadcasterConfigResponse> PostBroadcasterConfigAsync(string endpoint, string clientId, string accept, decimal channelId, string broadcaster, BroadcasterConfigContainer container) { _Log.LogInformation($"Checking that broadcaster '{broadcaster}' exists."); var userResponse = await _TwitchWrapper.GetUsers(endpoint, clientId, accept, broadcaster); if (!userResponse.Users.Any()) { var errorMessage = $"Could not find streamer '{broadcaster}'."; _Log.LogInformation(errorMessage); return(new PostBroadcasterConfigResponse(errorMessage)); } var displayName = userResponse.Users[0].DisplayName; _Log.LogInformation($"Found broadcaster '{broadcaster}' with display name '{displayName}'."); _Log.LogInformation($"Posting broadcaster config for channel '{channelId}' broadcaster '{displayName}'."); var result = await _Context.SetBroadcasterConfigAsync(channelId, displayName, container); _Log.LogInformation($"Posted broadcaster config for channel '{channelId}' broadcaster '{displayName}'."); return(new PostBroadcasterConfigResponse(result)); }
public async Task<List<TEntity>> GetAll(string path, string token = null) { List<TEntity> result; _loggerWrapper.LogInformation("path: " + path, this.GetType().Name, nameof(GetAll) + "()", null); try { result = await HttpClientWrapper.GetAllAsync(path, token); } catch (Exception exception) { _loggerWrapper.LogError("Failed to retrieve items", this.GetType().Name, nameof(GetAll) + "()", null); _loggerWrapper.LogError(exception.Message, this.GetType().Name, nameof(GetAll) + "()", null); _loggerWrapper.LogError(exception.InnerException != null ? exception.InnerException.Message : null, this.GetType().Name, nameof(GetAll) + "()", null); throw new Exception("Failed to retrieve items", exception); } return result; }
public IActionResult Run( [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req, CancellationToken cancellationToken) { try { _logger.LogInformation("C# HTTP trigger function processed health check request."); return(new OkObjectResult("I'm alive!")); } catch (Exception ex) { _logger.LogErrorAndNotifyNewRelic($"Unhandled error in HealthCheck", ex, req); return(new InternalServerErrorResult()); } }
public async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] [RequestBodyType(typeof(GetNearbyPostcodesRequest), "get nearby postcodes")] GetNearbyPostcodesRequest req, CancellationToken cancellationToken) { try { NewRelic.Api.Agent.NewRelic.SetTransactionName("AddressService", "GetNearbyPostcodes"); _logger.LogInformation("C# HTTP trigger function processed a request."); // This validation logic belongs in a custom validation attribute on the Postcode property. However, validationContext.GetService<IExternalService> always returned null in the validation attribute (despite DI working fine elsewhere). I didn't want to spend a lot of time finding out why when there is lots to do so I've put the postcode validation logic here for now. if (!await _postcodeValidator.IsPostcodeValidAsync(req.Postcode)) { return(new ObjectResult(ResponseWrapper <GetNearbyPostcodesResponse, AddressServiceErrorCode> .CreateUnsuccessfulResponse(AddressServiceErrorCode.InvalidPostcode, "Invalid postcode")) { StatusCode = 422 }); } if (req.IsValid(out var validationResults)) { GetNearbyPostcodesResponse response = await _mediator.Send(req, cancellationToken); return(new OkObjectResult(ResponseWrapper <GetNearbyPostcodesResponse, AddressServiceErrorCode> .CreateSuccessfulResponse(response))); } else { return(new ObjectResult(ResponseWrapper <GetNearbyPostcodesResponse, AddressServiceErrorCode> .CreateUnsuccessfulResponse(AddressServiceErrorCode.ValidationError, validationResults)) { StatusCode = 422 }); } } catch (Exception ex) { _logger.LogErrorAndNotifyNewRelic($"Unhandled error in GetNearbyPostcodes", ex, req); return(new ObjectResult(ResponseWrapper <GetNearbyPostcodesResponse, AddressServiceErrorCode> .CreateUnsuccessfulResponse(AddressServiceErrorCode.UnhandledError, "Internal Error")) { StatusCode = StatusCodes.Status500InternalServerError }); } }
public async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] [RequestBodyType(typeof(GetJobsAllocatedToUserRequest), "get jobs allocated to user request")] GetJobsAllocatedToUserRequest req, CancellationToken cancellationToken) { try { _logger.LogInformation("GetJobsAllocatedToUser started"); GetJobsAllocatedToUserResponse response = await _mediator.Send(req, cancellationToken); return(new OkObjectResult(ResponseWrapper <GetJobsAllocatedToUserResponse, RequestServiceErrorCode> .CreateSuccessfulResponse(response))); } catch (Exception exc) { _logger.LogErrorAndNotifyNewRelic("Exception occured in GetJobsAllocatedToUser", exc); return(new ObjectResult(ResponseWrapper <GetJobsAllocatedToUserResponse, RequestServiceErrorCode> .CreateUnsuccessfulResponse(RequestServiceErrorCode.InternalServerError, "Internal Error")) { StatusCode = StatusCodes.Status500InternalServerError }); } }
public async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "put", Route = null)] [RequestBodyType(typeof(PutUpdateJobStatusToInProgressRequest), "put update job status to in progress request")] PutUpdateJobStatusToInProgressRequest req, CancellationToken cancellationToken) { try { _logger.LogInformation("PutUpdateJobStatusToInProgress started"); PutUpdateJobStatusToInProgressResponse response = await _mediator.Send(req, cancellationToken); return(new OkObjectResult(ResponseWrapper <PutUpdateJobStatusToInProgressResponse, RequestServiceErrorCode> .CreateSuccessfulResponse(response))); } catch (Exception exc) { _logger.LogErrorAndNotifyNewRelic("Exception occured in PutUpdateJobStatusToInProgress", exc); return(new ObjectResult(ResponseWrapper <PutUpdateJobStatusToInProgressResponse, RequestServiceErrorCode> .CreateUnsuccessfulResponse(RequestServiceErrorCode.InternalServerError, "Internal Error")) { StatusCode = StatusCodes.Status500InternalServerError }); } }
public async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] [RequestBodyType(typeof(GetDistanceBetweenPostcodesRequest), "Get Distance Between Postcodes")] GetDistanceBetweenPostcodesRequest req, CancellationToken cancellationToken) { try { var input = JsonConvert.SerializeObject(req); _logger.LogInformation(input); GetDistanceBetweenPostcodesResponse response = await _mediator.Send(req, cancellationToken); return(new OkObjectResult(ResponseWrapper <GetDistanceBetweenPostcodesResponse, AddressServiceErrorCode> .CreateSuccessfulResponse(response))); } catch (Exception exc) { _logger.LogErrorAndNotifyNewRelic("Exception occured in GetDistanceBetweenPostcodes", exc); _logger.LogError(exc.ToString(), exc); return(new ObjectResult(ResponseWrapper <GetDistanceBetweenPostcodesResponse, AddressServiceErrorCode> .CreateUnsuccessfulResponse(AddressServiceErrorCode.UnhandledError, "Internal Error")) { StatusCode = StatusCodes.Status500InternalServerError }); } }
public async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] [RequestBodyType(typeof(GetPostcodesRequest), "Get Postcodes")] GetPostcodesRequest req, CancellationToken cancellationToken) { try { NewRelic.Api.Agent.NewRelic.SetTransactionName("AddressService", "GetPostcodes"); _logger.LogInformation("C# HTTP trigger function processed a request."); GetPostcodesResponse response = await _mediator.Send(req, cancellationToken); return(new OkObjectResult(ResponseWrapper <GetPostcodesResponse, AddressServiceErrorCode> .CreateSuccessfulResponse(response))); } catch (Exception ex) { _logger.LogErrorAndNotifyNewRelic($"Unhandled error in GetPostcodes", ex, req); return(new ObjectResult(ResponseWrapper <GetPostcodesResponse, AddressServiceErrorCode> .CreateUnsuccessfulResponse(AddressServiceErrorCode.UnhandledError, "Internal Error")) { StatusCode = StatusCodes.Status500InternalServerError }); } }
public void Run([TimerTrigger("%TimedHealthCheckCronExpression%")] TimerInfo timerInfo) { _logger.LogInformation($"Health check CRON trigger executed at : {DateTimeOffset.Now}"); }
public async Task <List <TEntity> > GetAllAsync(string urlExtension, string token = null) { _loggerWrapper.LogInformation(nameof(urlExtension) + ": " + urlExtension + " | " + nameof(token) + ": " + token, this.GetType().Name, nameof(GetAllAsync) + "()", null); return(await CheckExceptions(async() => (await _httwrap.GetAsync(urlExtension, null, token != null ? GetCustomHeaders(token) : null)) .ReadAs <List <TEntity> >())); }
public void ConfigureServices(IServiceCollection services) { var env = services.BuildServiceProvider() .GetRequiredService <IHostingEnvironment>(); Logger.LogInformation("Registering second-line services in Startup.ConfigureServices"); services.AddSingleton <IServiceCollection>(services); /*: configuration section "logging" : */ services.AddLogging(builder => { builder.AddConsole() .AddDebug(); }); services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearerConfiguration(Configuration); services.AddAuthorizationConfiguration(Configuration); /*: configuration section "responseCaching" : */ if (ShouldUseCaching(Configuration, out var redisCacheOptions)) { services.AddDistributedRedisCache(options => { options.Configuration = redisCacheOptions.Configuration; options.InstanceName = redisCacheOptions.InstanceName; }); services.AddDistributedResponseCaching(); services.AddTransient <IDistributedCacheManager, RedisDistributedCacheManager>(); } // Database... var connectionStrings = new ConnectionStrings(); Configuration.Bind("ConnectionStrings", connectionStrings); //if(env.IsDevelopment()) // services.AddDbContext<ReferenceDataDbContext>(options => { options.UseSqlite("Data Source=mydb.db"); }); //else services.AddDbContext <ReferenceDataDbContext>(options => { options.UseSqlServer(connectionStrings.CoreReadDatabase); }); services.AddUnitOfWork <ReferenceDataDbContext>(); services.AddApiVersioning(options => { options.ReportApiVersions = true; }); services.AddVersionedApiExplorer(options => { options.DefaultApiVersion = new ApiVersion(1, 0); options.AssumeDefaultVersionWhenUnspecified = true; options.GroupNameFormat = "'v'VVV"; options.SubstituteApiVersionInUrl = true; }); services.AddOData( ) .EnableApiVersioning(options => { }); services.AddODataApiExplorer(options => { options.GroupNameFormat = "'v'VVV"; options.SubstituteApiVersionInUrl = true; }); services.AddTransient <IConfigureOptions <SwaggerGenOptions>, ConfigureSwaggerOptions>(); services.AddSwaggerGen(options => { // add a custom operation filter which sets default values options.OperationFilter <SwaggerDefaultValues>(); // tell swagger that we are using a JWT token // see: https://swagger.io/docs/specification/authentication/ options.AddSecurityDefinition("Bearer", new ApiKeyScheme { In = "header", Type = "apiKey", Name = "Authorization", Description = "JWT Authorization header using the Bearer scheme.", }); // integrate xml comments // options.IncludeXmlComments(XmlCommentsFilePath); }); services.AddPlatformComponents(options => { options.AutoGenerateEmptyCorrelationId = false; }); // Metrics services.AddMetricFromConfiguration(Configuration); services.AddHealthFromConfiguration(Configuration, builder => { if (redisCacheOptions != null) { //builder.HealthChecks // .AddRedisCheck( // "Redis connection check", // () => ConnectionMultiplexer.Connect(redisCacheOptions.Configuration), // TimeSpan.FromSeconds(90), // true); } if (!string.IsNullOrEmpty(connectionStrings.CoreReadDatabase)) { //builder.HealthChecks // .AddSqlCheck( // "Sql Database Check", // connectionStrings.CoreReadDatabase, // TimeSpan.FromSeconds(90), // true // ); } }); services.AddMvc(options => { //options.Filters.Add( // new ResponseCacheAttribute // { // Duration = 3600, // Location = ResponseCacheLocation.Any, // VaryByQueryKeys = new[] {"*"} // }); }) .SetCompatibilityVersion( CompatibilityVersion.Version_2_1 ); AddCors(services); Logger.LogInformation("Startup.ConfigureServices completed"); }