From e159536ff3789edd89ce049d4ccf1edb0485ec98 Mon Sep 17 00:00:00 2001 From: rafsanulhasan Date: Mon, 13 Aug 2018 21:20:55 +0600 Subject: [PATCH] Removed ASP.NET Core's (2.1) default model validation behavior --- src/Services/Basket/Basket.API/Startup.cs | 454 +++++++++++----------- 1 file changed, 230 insertions(+), 224 deletions(-) diff --git a/src/Services/Basket/Basket.API/Startup.cs b/src/Services/Basket/Basket.API/Startup.cs index 283d66498..4f3917815 100644 --- a/src/Services/Basket/Basket.API/Startup.cs +++ b/src/Services/Basket/Basket.API/Startup.cs @@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; using Microsoft.Azure.ServiceBus; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; @@ -34,283 +35,288 @@ using System.Threading.Tasks; namespace Microsoft.eShopOnContainers.Services.Basket.API { - public class Startup - { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } - public IConfiguration Configuration { get; } + public IConfiguration Configuration { get; } - // This method gets called by the runtime. Use this method to add services to the container. - public IServiceProvider ConfigureServices(IServiceCollection services) - { - RegisterAppInsights(services); + // This method gets called by the runtime. Use this method to add services to the container. + public IServiceProvider ConfigureServices(IServiceCollection services) + { + RegisterAppInsights(services); - // Add framework services. - services.AddMvc(options => - { - options.Filters.Add(typeof(HttpGlobalExceptionFilter)); - options.Filters.Add(typeof(ValidateModelStateFilter)); + services.Configure(opt => + { + opt.SuppressModelStateInvalidFilter = true; + }); - }) - .SetCompatibilityVersion(AspNetCore.Mvc.CompatibilityVersion.Version_2_1) - .AddControllersAsServices(); + // Add framework services. + services.AddMvc(options => + { + options.Filters.Add(typeof(HttpGlobalExceptionFilter)); + options.Filters.Add(typeof(ValidateModelStateFilter)); - ConfigureAuthService(services); + }) + .SetCompatibilityVersion(AspNetCore.Mvc.CompatibilityVersion.Version_2_1) + .AddControllersAsServices(); - services.AddHealthChecks(checks => - { - checks.AddValueTaskCheck("HTTP Endpoint", () => new ValueTask(HealthCheckResult.Healthy("Ok")), - TimeSpan.Zero //No cache for this HealthCheck, better just for demos - ); - }); + ConfigureAuthService(services); - services.Configure(Configuration); + services.AddHealthChecks(checks => + { + checks.AddValueTaskCheck("HTTP Endpoint", () => new ValueTask(HealthCheckResult.Healthy("Ok")), + TimeSpan.Zero //No cache for this HealthCheck, better just for demos + ); + }); - //By connecting here we are making sure that our service - //cannot start until redis is ready. This might slow down startup, - //but given that there is a delay on resolving the ip address - //and then creating the connection it seems reasonable to move - //that cost to startup instead of having the first request pay the - //penalty. - services.AddSingleton(sp => - { - var settings = sp.GetRequiredService>().Value; - var configuration = ConfigurationOptions.Parse(settings.ConnectionString, true); + services.Configure(Configuration); - configuration.ResolveDns = true; + //By connecting here we are making sure that our service + //cannot start until redis is ready. This might slow down startup, + //but given that there is a delay on resolving the ip address + //and then creating the connection it seems reasonable to move + //that cost to startup instead of having the first request pay the + //penalty. + services.AddSingleton(sp => + { + var settings = sp.GetRequiredService>().Value; + var configuration = ConfigurationOptions.Parse(settings.ConnectionString, true); - return ConnectionMultiplexer.Connect(configuration); - }); + configuration.ResolveDns = true; + + return ConnectionMultiplexer.Connect(configuration); + }); - if (Configuration.GetValue("AzureServiceBusEnabled")) - { - services.AddSingleton(sp => - { - var logger = sp.GetRequiredService>(); + if (Configuration.GetValue("AzureServiceBusEnabled")) + { + services.AddSingleton(sp => + { + var logger = sp.GetRequiredService>(); - var serviceBusConnectionString = Configuration["EventBusConnection"]; - var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString); + var serviceBusConnectionString = Configuration["EventBusConnection"]; + var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString); - return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger); - }); - } - else - { - services.AddSingleton(sp => - { - var logger = sp.GetRequiredService>(); + return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger); + }); + } + else + { + services.AddSingleton(sp => + { + var logger = sp.GetRequiredService>(); - var factory = new ConnectionFactory() - { - HostName = Configuration["EventBusConnection"] - }; + var factory = new ConnectionFactory() + { + HostName = Configuration["EventBusConnection"] + }; - if (!string.IsNullOrEmpty(Configuration["EventBusUserName"])) - { - factory.UserName = Configuration["EventBusUserName"]; - } + if (!string.IsNullOrEmpty(Configuration["EventBusUserName"])) + { + factory.UserName = Configuration["EventBusUserName"]; + } - if (!string.IsNullOrEmpty(Configuration["EventBusPassword"])) - { - factory.Password = Configuration["EventBusPassword"]; - } + if (!string.IsNullOrEmpty(Configuration["EventBusPassword"])) + { + factory.Password = Configuration["EventBusPassword"]; + } - var retryCount = 5; - if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) - { - retryCount = int.Parse(Configuration["EventBusRetryCount"]); - } + var retryCount = 5; + if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) + { + retryCount = int.Parse(Configuration["EventBusRetryCount"]); + } - return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); - }); - } + return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); + }); + } - RegisterEventBus(services); + RegisterEventBus(services); - services.AddSwaggerGen(options => - { - options.DescribeAllEnumsAsStrings(); - options.SwaggerDoc("v1", new Info - { - Title = "Basket HTTP API", - Version = "v1", - Description = "The Basket Service HTTP API", - TermsOfService = "Terms Of Service" - }); + services.AddSwaggerGen(options => + { + options.DescribeAllEnumsAsStrings(); + options.SwaggerDoc("v1", new Info + { + Title = "Basket HTTP API", + Version = "v1", + Description = "The Basket Service HTTP API", + TermsOfService = "Terms Of Service" + }); - options.AddSecurityDefinition("oauth2", new OAuth2Scheme - { - Type = "oauth2", - Flow = "implicit", - AuthorizationUrl = $"{Configuration.GetValue("IdentityUrlExternal")}/connect/authorize", - TokenUrl = $"{Configuration.GetValue("IdentityUrlExternal")}/connect/token", - Scopes = new Dictionary() - { - { "basket", "Basket API" } - } - }); + options.AddSecurityDefinition("oauth2", new OAuth2Scheme + { + Type = "oauth2", + Flow = "implicit", + AuthorizationUrl = $"{Configuration.GetValue("IdentityUrlExternal")}/connect/authorize", + TokenUrl = $"{Configuration.GetValue("IdentityUrlExternal")}/connect/token", + Scopes = new Dictionary() + { + { "basket", "Basket API" } + } + }); - options.OperationFilter(); - }); + options.OperationFilter(); + }); - services.AddCors(options => - { - options.AddPolicy("CorsPolicy", - builder => builder.AllowAnyOrigin() - .AllowAnyMethod() - .AllowAnyHeader() - .AllowCredentials()); - }); - services.AddSingleton(); - services.AddTransient(); - services.AddTransient(); + services.AddCors(options => + { + options.AddPolicy("CorsPolicy", + builder => builder.AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials()); + }); + services.AddSingleton(); + services.AddTransient(); + services.AddTransient(); - services.AddOptions(); + services.AddOptions(); - var container = new ContainerBuilder(); - container.Populate(services); + var container = new ContainerBuilder(); + container.Populate(services); - return new AutofacServiceProvider(container.Build()); - } - + return new AutofacServiceProvider(container.Build()); + } - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) - { - loggerFactory.AddAzureWebAppDiagnostics(); - loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); - var pathBase = Configuration["PATH_BASE"]; - if (!string.IsNullOrEmpty(pathBase)) - { - app.UsePathBase(pathBase); - } + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) + { + loggerFactory.AddAzureWebAppDiagnostics(); + loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); + + var pathBase = Configuration["PATH_BASE"]; + if (!string.IsNullOrEmpty(pathBase)) + { + app.UsePathBase(pathBase); + } #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously - app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200)); + app.Map("/liveness", lapp => lapp.Run(async ctx => ctx.Response.StatusCode = 200)); #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously - app.UseStaticFiles(); - app.UseCors("CorsPolicy"); + app.UseStaticFiles(); + app.UseCors("CorsPolicy"); - ConfigureAuth(app); + ConfigureAuth(app); - app.UseMvcWithDefaultRoute(); + app.UseMvcWithDefaultRoute(); - app.UseSwagger() - .UseSwaggerUI(c => - { - c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Basket.API V1"); - c.OAuthClientId ("basketswaggerui"); - c.OAuthAppName("Basket Swagger UI"); - }); + app.UseSwagger() + .UseSwaggerUI(c => + { + c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Basket.API V1"); + c.OAuthClientId("basketswaggerui"); + c.OAuthAppName("Basket Swagger UI"); + }); - ConfigureEventBus(app); + ConfigureEventBus(app); - } + } - private void RegisterAppInsights(IServiceCollection services) - { - services.AddApplicationInsightsTelemetry(Configuration); - var orchestratorType = Configuration.GetValue("OrchestratorType"); - - if (orchestratorType?.ToUpper() == "K8S") - { - // Enable K8s telemetry initializer - services.EnableKubernetes(); - } - if (orchestratorType?.ToUpper() == "SF") - { - // Enable SF telemetry initializer - services.AddSingleton((serviceProvider) => - new FabricTelemetryInitializer()); - } - } + private void RegisterAppInsights(IServiceCollection services) + { + services.AddApplicationInsightsTelemetry(Configuration); + var orchestratorType = Configuration.GetValue("OrchestratorType"); - private void ConfigureAuthService(IServiceCollection services) - { - // prevent from mapping "sub" claim to nameidentifier. - JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); + if (orchestratorType?.ToUpper() == "K8S") + { + // Enable K8s telemetry initializer + services.EnableKubernetes(); + } + if (orchestratorType?.ToUpper() == "SF") + { + // Enable SF telemetry initializer + services.AddSingleton((serviceProvider) => + new FabricTelemetryInitializer()); + } + } - var identityUrl = Configuration.GetValue("IdentityUrl"); - - services.AddAuthentication(options => - { - options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; - options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + private void ConfigureAuthService(IServiceCollection services) + { + // prevent from mapping "sub" claim to nameidentifier. + JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); - }).AddJwtBearer(options => - { - options.Authority = identityUrl; - options.RequireHttpsMetadata = false; - options.Audience = "basket"; - }); - } + var identityUrl = Configuration.GetValue("IdentityUrl"); - protected virtual void ConfigureAuth(IApplicationBuilder app) - { - if (Configuration.GetValue("UseLoadTest")) - { - app.UseMiddleware(); - } + services.AddAuthentication(options => + { + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; - app.UseAuthentication(); - } + }).AddJwtBearer(options => + { + options.Authority = identityUrl; + options.RequireHttpsMetadata = false; + options.Audience = "basket"; + }); + } - private void RegisterEventBus(IServiceCollection services) - { - var subscriptionClientName = Configuration["SubscriptionClientName"]; + protected virtual void ConfigureAuth(IApplicationBuilder app) + { + if (Configuration.GetValue("UseLoadTest")) + { + app.UseMiddleware(); + } - if (Configuration.GetValue("AzureServiceBusEnabled")) - { - services.AddSingleton(sp => - { - var serviceBusPersisterConnection = sp.GetRequiredService(); - var iLifetimeScope = sp.GetRequiredService(); - var logger = sp.GetRequiredService>(); - var eventBusSubcriptionsManager = sp.GetRequiredService(); + app.UseAuthentication(); + } - return new EventBusServiceBus(serviceBusPersisterConnection, logger, - eventBusSubcriptionsManager, subscriptionClientName, iLifetimeScope); - }); - } - else - { - services.AddSingleton(sp => - { - var rabbitMQPersistentConnection = sp.GetRequiredService(); - var iLifetimeScope = sp.GetRequiredService(); - var logger = sp.GetRequiredService>(); - var eventBusSubcriptionsManager = sp.GetRequiredService(); + private void RegisterEventBus(IServiceCollection services) + { + var subscriptionClientName = Configuration["SubscriptionClientName"]; - var retryCount = 5; - if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) - { - retryCount = int.Parse(Configuration["EventBusRetryCount"]); - } + if (Configuration.GetValue("AzureServiceBusEnabled")) + { + services.AddSingleton(sp => + { + var serviceBusPersisterConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); - return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount); - }); - } + return new EventBusServiceBus(serviceBusPersisterConnection, logger, + eventBusSubcriptionsManager, subscriptionClientName, iLifetimeScope); + }); + } + else + { + services.AddSingleton(sp => + { + var rabbitMQPersistentConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); - services.AddSingleton(); + var retryCount = 5; + if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) + { + retryCount = int.Parse(Configuration["EventBusRetryCount"]); + } - services.AddTransient(); - services.AddTransient(); - } + return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount); + }); + } - private void ConfigureEventBus(IApplicationBuilder app) - { - var eventBus = app.ApplicationServices.GetRequiredService(); + services.AddSingleton(); - eventBus.Subscribe(); - eventBus.Subscribe(); - } - } + services.AddTransient(); + services.AddTransient(); + } + + private void ConfigureEventBus(IApplicationBuilder app) + { + var eventBus = app.ApplicationServices.GetRequiredService(); + + eventBus.Subscribe(); + eventBus.Subscribe(); + } + } }