public static IServiceCollection AddCustomOptions(this IServiceCollection services, IConfiguration configuration) { services.Configure <ConfigurationSettings>(configuration); services.Configure <ApiBehaviorOptions>(options => { options.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState) { Instance = context.HttpContext.Request.Path, Status = StatusCodes.Status400BadRequest, Detail = "Please refer to the errors property for additional details." }; return(new BadRequestObjectResult(problemDetails) { ContentTypes = { "application/problem+json", "application/problem+xml" } }); }; }); return(services); }
public ActionResult <ReservaViewModel> Put(string identificacion, ReservaInputModel reservaInput) { Reserva reserva = MapearReserva(reservaInput); var id = _reservaService.BuscarxIdentificacion(reserva.IdReserva); if (id == null) { return(BadRequest("No encontrado")); } else { var response = _reservaService.Modificar(reserva); if (response.Error) { ModelState.AddModelError("Modificar Reserva", response.Mensaje); var problemDetails = new ValidationProblemDetails(ModelState) { Status = StatusCodes.Status400BadRequest, }; return(BadRequest(problemDetails)); } return(Ok(response.Reserva)); } }
void IOutputPort.Invalid(Notification notification) { ValidationProblemDetails problemDetails = new ValidationProblemDetails(notification.ModelState); this._viewModel = this.BadRequest(problemDetails); }
public static IServiceCollection AddCustomDefaultAspNetServices(this IServiceCollection services, IConfiguration configuration) { services.AddOptions(); services.AddHttpContextAccessor(); services.AddDefaultCors(configuration); services.AddResponseCompression(); services.AddApiVersioning(options => { options.ReportApiVersions = true; options.AssumeDefaultVersionWhenUnspecified = true; }); services.AddVersionedApiExplorer(options => { options.GroupNameFormat = "'v'VVV"; options.SubstituteApiVersionInUrl = true; }); services.Configure <ApiBehaviorOptions>(options => { options.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState) { Instance = context.HttpContext.Request.Path, Status = StatusCodes.Status400BadRequest, Type = $"https://httpstatuses.com/400", Title = "Dados inválidos", Detail = "Os dados enviados na requisição não estão corretos" }; return(new BadRequestObjectResult(problemDetails)); }; }); services.Configure <JsonOptions>(opt => { opt.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); opt.JsonSerializerOptions.IgnoreNullValues = true; }); services.Configure <MvcOptions>(opt => { opt.UseApiVersionRoute(); }); services .AddMvc() .AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining <UserValidator>()); services.AddDependencyInjections(); var key = Encoding.ASCII.GetBytes(configuration.GetValue <string>("Auth:SecretKey")); services.AddAuthentication(x => { x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(x => { x.RequireHttpsMetadata = false; x.SaveToken = true; x.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(key), ValidateIssuer = false, ValidateAudience = false }; }); return(services); }
public HttpStatusCodeException(ValidationProblemDetails problem) : base(problem.Title) { ResponseModel = problem; }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddResponseCaching(); services.AddControllers(setupAction => { setupAction.ReturnHttpNotAcceptable = true; setupAction.CacheProfiles.Add("240SecondsCacheProfile", new CacheProfile { Duration = 240 }); }) .AddNewtonsoftJson(opts => { opts.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); opts.SerializerSettings.Converters.Add(new StringEnumConverter()); }) .AddXmlDataContractSerializerFormatters() .ConfigureApiBehaviorOptions(setupAction => { setupAction.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState) { //Type = "https://courselibrary.com/modelvalidationproblem", Title = "One or more model validation errors occurred.", Status = StatusCodes.Status422UnprocessableEntity, Detail = "See the errors property for details.", Instance = context.HttpContext.Request.Path }; problemDetails.Extensions.Add("traceId", context.HttpContext.TraceIdentifier); return(new UnprocessableEntityObjectResult(problemDetails) { ContentTypes = { "application/problem+json" } }); }; }); services.Configure <MvcOptions>(config => { var newtonsoftJsonOutputFormatter = config.OutputFormatters.OfType <NewtonsoftJsonOutputFormatter>().FirstOrDefault(); newtonsoftJsonOutputFormatter?.SupportedMediaTypes.Add("application/vnd.marvin.hateoas+json"); }); services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); // register PropertyMappingService services.AddTransient <IPropertyMappingService, PropertyMappingService>(); // register PropertyCheckerService services.AddTransient <IPropertyCheckerService, PropertyCheckerService>(); // services services.AddScoped <IOwnerRepository, OwnerRepository>(); services.AddScoped <IDogRepository, DogRepository>(); services.AddDbContext <RenosFriendsListContext>(options => { options.UseSqlServer(@"Server=DEV63\SQLEXPRESS;Database=RenosFriendsListDb;Trusted_Connection=True;"); }); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.InitSwaggerConfig(); //Etag 缓存 services.InitEtagConfig(); services.Configure <Settings>(Configuration.GetSection("Settings")); services.AddControllers(options => { options.CacheProfiles.Add("120sCacheProfile", new CacheProfile { Duration = 120 }); options.Filters.Add(typeof(CustomerExceptionFilterAttribute));//全局异常处理 options.Filters.Add(typeof(CustomerResultFilterAttribute)); options.Filters.Add(typeof(CustomerAuthorizeFilterAttribute)); }) .AddNewtonsoftJson(setup => { setup.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); }) .ConfigureApiBehaviorOptions(setup =>//错误信息输出配置 FluentValidation { setup.InvalidModelStateResponseFactory = context => { var problemDetail = new ValidationProblemDetails(context.ModelState) { Type = "", Title = "有错误", Status = StatusCodes.Status422UnprocessableEntity, Detail = "请看详细信息", Instance = context.HttpContext.Request.Path }; problemDetail.Extensions.Add("traceId", context.HttpContext.TraceIdentifier); return(new UnprocessableEntityObjectResult(problemDetail) { ContentTypes = { "application/problem+json" } }); }; }) .AddXmlDataContractSerializerFormatters();//支持xml处理 services.AddDbContext <IbmDbContext>(options => { options.UseDb2(Configuration.GetConnectionString("DevelopDB"), action => { }).UseLoggerFactory(ConsoleLoggerFactory);//打印sql脚本 }); services.Scan(scan => scan.FromAssemblies(Assembly.Load("Station.Repository"), Assembly.Load("Station.SortApply.Helper")) .AddClasses().UsingAttributes());//程序集注入 services.AddScoped <IApplicationContext, ApplicationContext>(); services.AddScoped <IUserRoleControl, Core.UserRoleWcf.UserRoleControl>(); services.AddScoped <PropertyMappingCollection>(); services.AddAutoMapper(config => { config.ForAllMaps((a, b) => b.ForAllMembers(opt => opt.Condition((src, dest, sourceMember) => sourceMember != null))); }, Assembly.Load("Station.Entity"), Assembly.Load("Station.Models")); services.Configure <MvcOptions>(config => { var newtonSoftJsonOutputFormatter = config.OutputFormatters.OfType <NewtonsoftJsonOutputFormatter>().FirstOrDefault(); newtonSoftJsonOutputFormatter?.SupportedMediaTypes.Add("application/vnd.company.hateoas+json"); }); services.AddDistributedMemoryCache(); services.AddSession(config => { config.IdleTimeout = TimeSpan.FromDays(1); }); }
public void ConfigureServices(IServiceCollection services) { //ETag services.AddHttpCacheHeaders(opt => { //过期模型 opt.MaxAge = 60; opt.CacheLocation = CacheLocation.Private; }, validation => { validation.MustRevalidate = true; //验证模型 }); //Etag //缓存 services.AddResponseCaching(); //services.AddMvc();// Mvc, addcontrollers:no view,for api services.AddControllers(opt => { opt.ReturnHttpNotAcceptable = true; //请求类型和返回类型不一致时,返回406 //opt.InputFormatters.Add(new XmlDataContractSerializerInputFormatter()); //opt.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter()); //返回类型是xml //opt.OutputFormatters.Insert(0,new XmlDataContractSerializerOutputFormatter()); //调整默认格式顺序 opt.CacheProfiles.Add("120sCacheProfile", new CacheProfile { Duration = 120 }); }) .AddNewtonsoftJson(opt => { opt.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); }) /* //fluent validation * .AddFluentValidation(fv => * { * // 混用规则。 * fv.RunDefaultMvcValidationAfterFluentValidationExecutes = true; * fv.RegisterValidatorsFromAssembly(Assembly.GetAssembly(this.GetType())); * })*/ .AddXmlDataContractSerializerFormatters() //asp.net core 3.0后的写法,输入和输出 //自定义错误报告 .ConfigureApiBehaviorOptions(opt => { opt.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState) { Type = "https://www.google.com", Title = "有错误", Status = StatusCodes.Status422UnprocessableEntity, Detail = "请看详细信息", Instance = context.HttpContext.Request.Path }; problemDetails.Extensions.Add("traceId", context.HttpContext.TraceIdentifier); return(new UnprocessableEntityObjectResult(problemDetails) { ContentTypes = { "application/problem+json" } }); }; }); //全局注册vendor-specific media type:application/vnd.company.hateoas+json services.Configure <MvcOptions>(config => { var newtonSoftJsonOutputFormatter = config.OutputFormatters .OfType <NewtonsoftJsonOutputFormatter>()? .FirstOrDefault(); newtonSoftJsonOutputFormatter?.SupportedMediaTypes.Add( "application/vnd.company.hateoas+json"); }); //services.AddSwaggerGen(x => //{ // x.SwaggerDoc("v1", new OpenApiInfo // { // Title = "My Web Api", // Version = "v1" // }); // x.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme // { // Description = "JWT Authorization", // Name = "Authorization", // In = ParameterLocation.Header, // Type = SecuritySchemeType.ApiKey, // Scheme = "Bearer" // }); // x.AddSecurityRequirement(new OpenApiSecurityRequirement // { // { // new OpenApiSecurityScheme // { // Reference = new OpenApiReference // { // Type = ReferenceType.SecurityScheme, // Id = "Bearer" // } // }, // new string[] // { // } // } // }); //}); services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); //Auto Mapper,参数是程序集的数组 services.AddScoped <ICompanyRepository, CompanyRepository>(); //addscoped 每一次http请求 services.AddDbContext <RoutingDbContext>(opt => { opt.UseSqlite("Data Source=routine.db"); }); services.AddTransient <IPropertyMappingService, PropertyMappingService>(); services.AddTransient <IPropertyCheckService, PropertyCheckService>(); }
internal static IDictionary <string, string[]> ToDictionary(this ModelStateDictionary modelState) { var details = new ValidationProblemDetails(modelState); return(details.Errors); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddHttpCacheHeaders( expires => { expires.MaxAge = 60; expires.CacheLocation = CacheLocation.Private; }, validation => { validation.MustRevalidate = true; }); services.AddResponseCaching(); services.AddControllers(setup => { setup.ReturnHttpNotAcceptable = true; setup.CacheProfiles.Add("120sCacheProfile", new CacheProfile { Duration = 120 }); }) .AddNewtonsoftJson(setup => { setup.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); }).AddXmlDataContractSerializerFormatters() .ConfigureApiBehaviorOptions(setup => { setup.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState) { Type = "http://www.baidu.com", Title = "ÓдíÎ󣡣¡£¡", Status = StatusCodes.Status422UnprocessableEntity, Detail = "Çë¿´ÏêϸÐÅÏ¢", Instance = context.HttpContext.Request.Path }; problemDetails.Extensions.Add("traceId", context.HttpContext.TraceIdentifier); return(new UnprocessableEntityObjectResult(problemDetails) { ContentTypes = { "application/problem+json" } // Fluent Validation }); }; }); services.Configure <MvcOptions>(config => { var newtonSoftJsonOutputFormatter = config.OutputFormatters.OfType <NewtonsoftJsonOutputFormatter>()?.FirstOrDefault(); if (newtonSoftJsonOutputFormatter != null) { newtonSoftJsonOutputFormatter?.SupportedMediaTypes.Add("application/vnd.company.hateoas+json"); } }); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" }); }); services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); services.AddScoped <ICompanyRepository, CompanyRepository>(); services.AddDbContext <RoutineDbContext>(option => { option.UseSqlite("Data Source=routine.db"); }); services.AddTransient <IPropertyMappingService, PropertyMappingService>(); services.AddTransient <IPropertyCheckerService, PropertyCheckerService>(); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddHttpCacheHeaders( // Sets the Cache-Control header: (expirationModelOptions) => { expirationModelOptions.MaxAge = 60; // setting to private will prevent the UseResponseCaching middleware // from storing the response because that's public/shared cache expirationModelOptions.CacheLocation = Marvin.Cache.Headers.CacheLocation.Private; }, (validationModelOptions) => { // if a response becomes stale, invalidation has to happen // this will set a 'must-revaliate' directive to the Cache-Control response header validationModelOptions.MustRevalidate = true; // in request header add: If-None-Match: "<ETAG>" to validate against etags // if the etag as not changed the response will be a 304 - not modified // this is handled by the ResponseCachingStore (using UseResponseCaching middleware) }); services.AddResponseCaching(); services.AddControllers(setupAction => { setupAction.ReturnHttpNotAcceptable = true; setupAction.CacheProfiles .Add("240SecondsCacheProfile", new CacheProfile() { Duration = 240 }); }).AddNewtonsoftJson(setupAction => { setupAction.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); }) .AddXmlDataContractSerializerFormatters() .ConfigureApiBehaviorOptions(setupAction => { setupAction.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState) { Type = "https://courselibrary.com/modelvalidationproblem", Title = "One or more model validation errors occurred.", Status = StatusCodes.Status422UnprocessableEntity, Detail = "See the errors property for details.", Instance = context.HttpContext.Request.Path }; problemDetails.Extensions.Add("traceId", context.HttpContext.TraceIdentifier); return(new UnprocessableEntityObjectResult(problemDetails) { ContentTypes = { "application/problem+json" } }); }; }); services.Configure <MvcOptions>(opt => { var newtonsoftJsonOutputFormatter = opt.OutputFormatters .OfType <NewtonsoftJsonOutputFormatter>()?.FirstOrDefault(); if (newtonsoftJsonOutputFormatter != null) { newtonsoftJsonOutputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.hateoas+json"); } }); // register PropertyMappingService services.AddTransient <IPropertyMappingService, PropertyMappingService>(); services.AddTransient <IPropertyCheckerService, PropertyCheckerService>(); services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); services.AddScoped <ICourseLibraryRepository, CourseLibraryRepository>(); services.AddDbContext <CourseLibraryContext>(options => { options.UseSqlServer( @"Server=sqlserver;Database=CourseLibraryDB;User Id=sa;Password=V3ryStr0ngPa55!;"); }); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllers(setupAction => { // Forcing client to specify content-type attribute setupAction.ReturnHttpNotAcceptable = true; }) // Support for patching documents .AddNewtonsoftJson(setupAction => { setupAction.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); }) // Supporting XML content-type .AddXmlDataContractSerializerFormatters() // Returning detailed response body when validation error occured .ConfigureApiBehaviorOptions(setupAction => { setupAction.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState) { Type = "https://musicplayer.com/modelvalidationproblem", Title = "Validation error(s) have occured.", Status = StatusCodes.Status422UnprocessableEntity, Detail = "See the errors property for details", Instance = context.HttpContext.Request.Path }; problemDetails.Extensions.Add("traceId", context.HttpContext.TraceIdentifier); return(new UnprocessableEntityObjectResult(problemDetails) { ContentTypes = { "application/problem+json" } }); }; }); services.Configure <MvcOptions>(config => { var newtonsoftJsonOutputFormatter = config.OutputFormatters .OfType <NewtonsoftJsonOutputFormatter>()?.FirstOrDefault(); if (newtonsoftJsonOutputFormatter != null) { newtonsoftJsonOutputFormatter.SupportedMediaTypes.Add("application/vnd.mrwhiteness.hateoas+json"); } }); services.AddTransient <IPropertyMappingService, PropertyMappingService>(); services.AddTransient <IPropertyCheckerService, PropertyCheckerService>(); services.AddDbContext <MusicPlayerDbContext>(options => { options.UseSqlServer(Configuration.GetConnectionString("MusicPlayerDbConnStr")); }); services.AddScoped <IMusicPlayerRepository, MusicPlayerRepository>(); services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); }
private async Task HandleExceptionAsync( HttpContext context, Exception ex) { ValidationProblemDetails errorMessage = null; switch (ex) { case IdentityException ie: errorMessage = new ValidationProblemDetails { Status = (int)HttpStatusCode.InternalServerError, Title = ie.Message, Detail = string.Join(". ", ie.IdentityErrors.Select(e => e.Description)) }; _logger.LogError(ie, "IDENTITY ERROR", errorMessage, errorMessage); break; case ValidationException ve: errorMessage = new ValidationProblemDetails { Title = "One or more validation errors occurred.", Status = (int)HttpStatusCode.UnprocessableEntity }; foreach (IGrouping <string, FluentValidation.Results.ValidationFailure> errorGrouping in ve.Errors.GroupBy(e => e.PropertyName)) { errorMessage.Errors.Add(errorGrouping.Key, errorGrouping.Select(g => g.ErrorMessage).ToArray()); } _logger.LogError(ve, "DOMAIN VALIDATION ERROR", errorMessage); break; case AuthenticationException ae: errorMessage = new ValidationProblemDetails { Title = ae.Message, Status = (int)HttpStatusCode.Unauthorized, }; _logger.LogError(ae, "AUTHENTICATION ERROR", errorMessage); break; case NotFoundException nfe: errorMessage = new ValidationProblemDetails { Title = "Resource not found.", Status = (int)HttpStatusCode.NotFound }; errorMessage.Errors.Add(nfe.PropertyName, new string[] { nfe.Message }); _logger.LogError(nfe, "NOT FOUND ERROR", errorMessage); break; case EmailException ee: errorMessage = new ValidationProblemDetails { Status = (int)HttpStatusCode.FailedDependency, Title = ee.Message, Detail = ee.InnerException?.Message }; _logger.LogError(ee, "EMAIL ERROR", errorMessage); break; case AuthorizationException aze: errorMessage = new ValidationProblemDetails { Title = aze.Message, Status = (int)HttpStatusCode.Forbidden }; _logger.LogError(aze, "AUTHORIZATION ERROR", errorMessage); break; case Exception e: errorMessage = new ValidationProblemDetails { Status = (int)HttpStatusCode.InternalServerError, Title = "An unexpected error occured", Detail = e.Message }; _logger.LogError(e, "SERVER ERROR", errorMessage); break; } context.Response.StatusCode = errorMessage?.Status ?? 500; if (errorMessage != null) { context.Response.ContentType = MediaTypeNames.Application.Json; var serializedErrorMessage = JsonSerializer.Serialize(errorMessage); await context.Response.WriteAsync(serializedErrorMessage); } }
void IOutputPort.Invalid(ApplicationResult result) { var validationProblemDetails = new ValidationProblemDetails(result.ModelState); _viewModel = BadRequest(validationProblemDetails); }
// 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.AddIdentity <ApplicationUser, IdentityRole>() .AddEntityFrameworkStores <AppDbContext>(); services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { var secretByte = Encoding.UTF8.GetBytes(Configuration["Authentication:SecretKey"]); options.TokenValidationParameters = new TokenValidationParameters() { ValidateIssuer = true, ValidIssuer = Configuration["Authentication:Issuer"], ValidateAudience = true, ValidAudience = Configuration["Authentication:Audience"], ValidateLifetime = true, IssuerSigningKey = new SymmetricSecurityKey(secretByte) }; }); services.AddControllers(setupAction => { setupAction.ReturnHttpNotAcceptable = true; //setupAction.OutputFormatters.Add( // new XmlDataContractSerializerOutputFormatter() // ); }) .AddNewtonsoftJson(setupAction => { setupAction.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); }) .AddXmlDataContractSerializerFormatters() .ConfigureApiBehaviorOptions(setupAction => { setupAction.InvalidModelStateResponseFactory = context => { var problemDetail = new ValidationProblemDetails(context.ModelState) { Type = "无所谓", Title = "数据验证失败", Status = StatusCodes.Status422UnprocessableEntity, Detail = "请看详细说明", Instance = context.HttpContext.Request.Path }; problemDetail.Extensions.Add("traceId", context.HttpContext.TraceIdentifier); return(new UnprocessableEntityObjectResult(problemDetail) { ContentTypes = { "application/problem+json" } }); }; }); //services.AddTransient<ITouristRouteRepository,MockTouristRouteRepository>(); services.AddTransient <ITouristRouteRepository, TouristRouteRepository>(); services.AddDbContext <AppDbContext>(option => { //option.UseSqlServer(@"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=FakeXiechengDb;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"); //option.UseSqlServer("server=localhost;Database=FakeXiechengDb;User Id=sa;Password=PaSSword12!"); option.UseSqlServer(Configuration["DbContext:ConnectionString"]); }); services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); services.AddHttpClient(); services.AddSingleton <IActionContextAccessor, ActionContextAccessor>(); }
public void ConfigureServices(IServiceCollection services) { //services.AddFreeSql(Configuration); services.AddCsRedisCore(Configuration); services.AddJwtBearer(Configuration); services.AddAutoMapper(typeof(UserProfile).Assembly, typeof(PoemProfile).Assembly); services.AddCors(); #region Mvc services.AddMvc(options => { options.ValueProviderFactories.Add(new ValueProviderFactory()); //设置SnakeCase形式的QueryString参数 //options.Filters.Add<LogActionFilterAttribute>(); // 添加请求方法时的日志记录过滤器 options.Filters.Add <LinCmsExceptionFilter>(); // }) .AddNewtonsoftJson(opt => { opt.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:MM:ss"; // 设置自定义时间戳格式 opt.SerializerSettings.Converters = new List <JsonConverter>() { new LinCmsTimeConverter() }; // 设置下划线方式,首字母是小写 opt.SerializerSettings.ContractResolver = new DefaultContractResolver() { NamingStrategy = new SnakeCaseNamingStrategy() { //ProcessDictionaryKeys = true }, }; }) .ConfigureApiBehaviorOptions(options => { //options.SuppressConsumesConstraintForFormFileParameters = true; //SuppressUseValidationProblemDetailsForInvalidModelStateResponses; //自定义 BadRequest 响应 options.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState); var resultDto = new UnifyResponseDto(ErrorCode.ParameterError, problemDetails.Errors, context.HttpContext); return(new BadRequestObjectResult(resultDto) { ContentTypes = { "application/json" } }); }; }); services.AddSwaggerGenNewtonsoftSupport(); #endregion //Swagger 扩展方法配置Swagger services.AddSwaggerGen(); //配置Google验证码 services.AddScoped <RecaptchaVerifyActionFilter>(); services.Configure <GooglereCAPTCHAOptions>(Configuration.GetSection(GooglereCAPTCHAOptions.RecaptchaSettings)); GooglereCAPTCHAOptions googlereCAPTCHAOptions = services.BuildServiceProvider().GetService <IOptionsSnapshot <GooglereCAPTCHAOptions> >().Value; if (googlereCAPTCHAOptions.Enabled) { services.AddreCAPTCHAV3(x => { x.VerifyBaseUrl = googlereCAPTCHAOptions.VerifyBaseUrl; x.SiteKey = googlereCAPTCHAOptions.SiteKey; x.SiteSecret = googlereCAPTCHAOptions.SiteSecret; }); } services.AddDIServices(Configuration); //应用程序级别设置 services.Configure <FormOptions>(options => { //单个文件上传的大小限制为8 MB 默认134217728 应该是128MB options.MultipartBodyLengthLimit = 1024 * 1024 * 8; //8MB }); // 分布式事务一致性CAP services.AddCap(Configuration); services.Configure <ForwardedHeadersOptions>(options => { options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; }); //之前请注入AddCsRedisCore,内部实现IDistributedCache接口 services.AddIpRateLimiting(Configuration); services.AddHealthChecks(); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllers(setupAction => { setupAction.ReturnHttpNotAcceptable = true; setupAction.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter()); }) .AddNewtonsoftJson(setupAction => { setupAction.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); }) .AddXmlDataContractSerializerFormatters() .ConfigureApiBehaviorOptions(setupAction => { setupAction.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState) { Type = "http://bnz.co.nz/modelvalidationproblem", Title = "One or more model validation occured", Status = StatusCodes.Status422UnprocessableEntity, Detail = "See the error properties for details.", Instance = context.HttpContext.Request.Path }; problemDetails.Extensions.Add("traceId", context.HttpContext.TraceIdentifier); return(new UnprocessableEntityObjectResult(problemDetails) { ContentTypes = { "application/problem+json" } }); }; } ); services.AddCors(c => { c.AddPolicy("AllowOrigin", options => options.WithOrigins("*.*")); }); services.AddMvcCore(setupAction: option => { option.EnableEndpointRouting = false; option.Filters.Add <ValidationFilter>(); }).AddApiExplorer() .AddDataAnnotations() .AddFluentValidation(mvcConfig => mvcConfig.RegisterValidatorsFromAssemblyContaining <Startup>()) // .AddJsonOptions() .AddFormatterMappings(); services.AddDirectoryBrowser(); var conn = Configuration.GetConnectionString("DefaultConnection"); services.AddDbContext <AdviceFirstDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); services.AddScoped <IAdviceFirstRepository, AdviceFirstRepository>(); //services.AddAutoMappervices(AppDomain.CurrentDomain.GetAssemblies()); services.AddAutoMapper(typeof(Startup)); var mappingConfig = new MapperConfiguration(mc => { mc.AddProfile(new MappingProfile()); }); IMapper mapper = mappingConfig.CreateMapper(); services.AddSingleton(mapper); services.AddSwaggerGen(c => { c.SwaggerDoc("AdviceFirstAPi_V1", new OpenApiInfo { Title = "AdviceFirst API", Version = "v1" }); var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlFullFileName = Path.Combine(AppContext.BaseDirectory, xmlFile); c.IncludeXmlComments(xmlFullFileName); }); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddApplication(); services.AddInfrastructure(Configuration, Environment); services.AddScoped <ICurrentUserService, CurrentUserService>(); services.AddHttpContextAccessor(); services.AddHealthChecks() .AddDbContextCheck <ApplicationDbContext>(); services.AddResponseCaching(options => { options.MaximumBodySize = 1024; options.UseCaseSensitivePaths = true; }); services.AddControllers(setupAction => { setupAction.ReturnHttpNotAcceptable = true; }).AddNewtonsoftJson(setupAction => { setupAction.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); }).ConfigureApiBehaviorOptions(setupAction => { setupAction.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState) { Type = "https://library.com/modelvalidationproblem", Title = "One or more model validation errors occurred.", Status = StatusCodes.Status422UnprocessableEntity, Detail = "See the errors property for details.", Instance = context.HttpContext.Request.Path }; problemDetails.Extensions.Add("traceId", context.HttpContext.TraceIdentifier); return(new UnprocessableEntityObjectResult(problemDetails) { ContentTypes = { "application/problem+json" } }); }; }).AddXmlDataContractSerializerFormatters(); services.AddControllersWithViews(); services.AddRazorPages(); // register PropertyMappingService services.AddTransient <IPropertyMappingService, PropertyMappingService>(); // register PropertyCheckerService services.AddTransient <IPropertyCheckerService, PropertyCheckerService>(); services.Configure <ApiBehaviorOptions>(options => { options.SuppressModelStateInvalidFilter = true; }); #region Swagger Documentation services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Version = "v1", Title = "ToDo API", Description = "A simple example ASP.NET Core Web API", TermsOfService = new Uri("https://example.com/terms"), Contact = new OpenApiContact { Name = "Mahfuz Ali", Email = string.Empty, Url = new Uri("https://twitter.com/spboyer"), }, License = new OpenApiLicense { Name = "Use under LICX", Url = new Uri("https://example.com/license"), } }); c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"", Name = "Authorization", In = ParameterLocation.Header, Type = SecuritySchemeType.ApiKey, Scheme = "Bearer" }); c.AddSecurityRequirement(new OpenApiSecurityRequirement() { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }, Scheme = "oauth2", Name = "Bearer", In = ParameterLocation.Header, }, new List <string>() } }); // Set the comments path for the Swagger JSON and UI. var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); c.IncludeXmlComments(xmlPath); }); #endregion }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { //添加automapper 需要载入automapper配置类 var test2 = AppDomain.CurrentDomain.Load("hxcloud.service"); services.AddAutoMapper(test2 /*AppDomain.CurrentDomain.GetAssemblies()*//*Assembly.Load("HXCloud.ViewModel")*/); services.AddScoped <TypeActionFilter>(); services.AddControllers().AddNewtonsoftJson(); #region 添加自定义模型认证 services.Configure <ApiBehaviorOptions>(options => { options.InvalidModelStateResponseFactory = (context) => { var problemDetails = new ValidationProblemDetails(context.ModelState) { //Type = "www.baidu.com", Title = "输入的参数有误", Status = StatusCodes.Status400BadRequest, Detail = "详见Errors", Instance = context.HttpContext.Request.Path }; problemDetails.Extensions.Add("TraceId", context.HttpContext.TraceIdentifier); return(new BadRequestObjectResult(problemDetails)); }; }); #endregion #region 添加jwt认证 services.Configure <JwtConfig>(Configuration.GetSection("JWT")); JwtConfig config = new JwtConfig(); Configuration.GetSection("JWT").Bind(config);//读取appsetting.json配置文件,并将配置文件绑定到类上 services.AddAuthentication(opt => { opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer(opt => { opt.TokenValidationParameters = new TokenValidationParameters { ValidateAudience = true, //ValidateLifetime = true, ValidateLifetime = false, ValidateIssuer = true, ValidateIssuerSigningKey = true, ValidIssuer = config.Issuer, ValidAudience = config.Audience, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config.IssuerSigningKey)), ClockSkew = TimeSpan.Zero }; }); #endregion //添加授权策略 //services.AddAuthorization(opt=> { // //opt.AddPolicy("") //}); //配置数据库 var connection = Configuration.GetConnectionString("SqlServer"); services.AddDbContext <HXCloudContext>(a => a.UseSqlServer(connection, b => b.MigrationsAssembly("HXCloud.Repository")) .UseLoggerFactory(MyLoggerFactory)); //设置上传文件大小 services.Configure <FormOptions>(opt => { opt.ValueCountLimit = int.MaxValue; opt.MultipartBodyLengthLimit = 300_000_000; //int.MaxValue; opt.MultipartHeadersLengthLimit = int.MaxValue; }); services.AddSwaggerGen(s => { s.SwaggerDoc("V2.0", new Microsoft.OpenApi.Models.OpenApiInfo { Title = "HX api V2", Version = "V2.0 " }); s.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "HXCloud.APIV2.xml")); #region Jwt //开启权限小锁 s.OperationFilter <AddResponseHeadersFilter>(); s.OperationFilter <AppendAuthorizeToSummaryOperationFilter>(); //在header中添加token,传递到后台 s.OperationFilter <SecurityRequirementsOperationFilter>(); s.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme { Description = "JWT授权(数据将在请求头中进行传递)直接在下面框中输入Bearer {token}(注意两者之间是一个空格) \"", Name = "Authorization", //jwt默认的参数名称 In = ParameterLocation.Header, //jwt默认存放Authorization信息的位置(请求头中) Type = SecuritySchemeType.ApiKey }); #endregion }); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { #region IdentityServer4+FreeSql InMemoryConfiguration.Configuration = this.Configuration; services.AddSingleton(Fsql); services.AddFreeRepository(filter => { filter.Apply <ISoftDeleteAduitEntity>("SoftDelete", a => a.IsDeleted == false); }, GetType().Assembly, typeof(AuditBaseRepository <>).Assembly); services.AddIdentityServer() .AddDeveloperSigningCredential() .AddInMemoryIdentityResources(InMemoryConfiguration.GetIdentityResources()) .AddInMemoryApiResources(InMemoryConfiguration.GetApis()) .AddInMemoryClients(InMemoryConfiguration.GetClients()) .AddProfileService <LinCmsProfileService>() .AddResourceOwnerValidator <LinCmsResourceOwnerPasswordValidator>(); #region AddAuthentication\AddIdentityServerAuthentication //AddAuthentication()是把验证服务注册到DI, 并配置了Bearer作为默认模式. //AddIdentityServerAuthentication()是在DI注册了token验证的处理者. //由于是本地运行, 所以就不使用https了, RequireHttpsMetadata = false.如果是生产环境, 一定要使用https. //Authority指定Authorization Server的地址. //ApiName要和Authorization Server里面配置ApiResource的name一样. //和 AddJwtBearer不能同时使用,目前还不理解区别。 //services // .AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme) // .AddIdentityServerAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme, options => // { // options.RequireHttpsMetadata = false; // for dev env // options.Authority = $"{Configuration["Identity:Protocol"]}://{Configuration["Identity:IP"]}:{Configuration["Identity:Port"]}"; ; // options.ApiName = Configuration["Service:Name"]; // match with configuration in IdentityServer // options.JwtValidationClockSkew = TimeSpan.FromSeconds(60*5); // }); #endregion #region AddJwtBearer services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => { //identityserver4 地址 也就是本项目地址 options.Authority = $"{Configuration["Identity:Protocol"]}://{Configuration["Identity:IP"]}:{Configuration["Identity:Port"]}"; options.RequireHttpsMetadata = false; options.Audience = Configuration["Service:Name"]; //options.TokenValidationParameters = new TokenValidationParameters() //{ // ClockSkew = TimeSpan.Zero //偏移设置为了0s,用于测试过期策略,完全按照access_token的过期时间策略,默认原本为5分钟 //}; //使用Authorize设置为需要登录时,返回json格式数据。 options.Events = new JwtBearerEvents() { OnChallenge = context => { //此处代码为终止.Net Core默认的返回类型和数据结果,这个很重要哦 context.HandleResponse(); string msg; ErrorCode errorCode; int statusCode = StatusCodes.Status401Unauthorized; if (context.Error == "invalid_token" && context.ErrorDescription == "The token is expired") { msg = "令牌过期"; errorCode = ErrorCode.TokenExpired; statusCode = StatusCodes.Status422UnprocessableEntity; } else if (context.Error == "invalid_token" && context.ErrorDescription.IsNullOrEmpty()) { msg = "令牌失效"; errorCode = ErrorCode.TokenInvalidation; } else { msg = "认证失败,请检查请求头或者重新登陆"; errorCode = ErrorCode.TokenInvalidation; } context.Response.ContentType = "application/json"; context.Response.StatusCode = statusCode; context.Response.WriteAsync(new ResultDto(errorCode, msg, context.HttpContext).ToString()); return(Task.FromResult(0)); } }; }); #endregion #endregion services.AddAutoMapper(typeof(Startup).Assembly, typeof(PoemProfile).Assembly); services.AddCors(option => option.AddPolicy("cors", policy => policy.AllowAnyHeader().AllowAnyMethod().AllowCredentials().AllowAnyOrigin())); #region Mvc services.AddMvc(options => { options.ValueProviderFactories.Add(new SnakeCaseQueryValueProviderFactory()); //设置SnakeCase形式的QueryString参数 options.Filters.Add <LinCmsExceptionFilter>(); options.Filters.Add <LogActionFilterAttribute>(); // 添加请求方法时的日志记录过滤器 }) .SetCompatibilityVersion(CompatibilityVersion.Version_2_2) .ConfigureApiBehaviorOptions(options => { options.SuppressUseValidationProblemDetailsForInvalidModelStateResponses = true; //自定义 BadRequest 响应 options.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState); var resultDto = new ResultDto(ErrorCode.ParameterError, problemDetails.Errors, context.HttpContext); return(new BadRequestObjectResult(resultDto) { ContentTypes = { "application/json" } }); }; }) .AddJsonOptions(opt => { //opt.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:MM:ss"; //设置时间戳格式 opt.SerializerSettings.Converters = new List <JsonConverter>() { new LinCmsTimeConverter() }; // 设置下划线方式,首字母是小写 opt.SerializerSettings.ContractResolver = new DefaultContractResolver() { NamingStrategy = new SnakeCaseNamingStrategy() { ProcessDictionaryKeys = true } }; }); #endregion services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>(); #region Scrutor 与单个单个注册等价,不过可批量注册 //services.AddScoped<ILogService, LogService>(); //services.AddScoped<IUserSevice, UserService>(); services.Scan(scan => scan //加载Startup这个类所在的程序集 .FromAssemblyOf <Startup>() // 表示要注册那些类,上面的代码还做了过滤,只留下了以 Service 结尾的类 .AddClasses(classes => classes.Where(t => t.Name.EndsWith("Service", StringComparison.OrdinalIgnoreCase))) //表示将类型注册为提供其所有公共接口作为服务 .AsImplementedInterfaces() //表示注册的生命周期为 Transient .WithTransientLifetime() // We start out with all types in the assembly of ITransientService .FromAssemblyOf <IScopeDependency>() // AddClasses starts out with all public, non-abstract types in this assembly. // These types are then filtered by the delegate passed to the method. // In this case, we filter out only the classes that are assignable to ITransientService. .AddClasses(classes => classes.AssignableTo <ITransientDependency>()) // We then specify what type we want to register these classes as. // In this case, we want to register the types as all of its implemented interfaces. // So if a type implements 3 interfaces; A, B, C, we'd end up with three separate registrations. .AsImplementedInterfaces() // And lastly, we specify the lifetime of these registrations. .WithTransientLifetime() ); #endregion #region Swagger //Swagger重写PascalCase,改成SnakeCase模式 services.TryAddEnumerable(ServiceDescriptor .Transient <IApiDescriptionProvider, SnakeCaseQueryParametersApiDescriptionProvider>()); //Register the Swagger generator, defining 1 or more Swagger documents services.AddSwaggerGen(options => { options.SwaggerDoc("v1", new Info() { Title = "LinCms", Version = "v1" }); var security = new Dictionary <string, IEnumerable <string> > { { "Bearer", new string[] { } }, }; options.AddSecurityRequirement(security);//添加一个必须的全局安全信息,和AddSecurityDefinition方法指定的方案名称要一致,这里是Bearer。 options.AddSecurityDefinition("Bearer", new ApiKeyScheme { Description = "JWT授权(数据将在请求头中进行传输) 参数结构: \"Authorization: Bearer {token}\"", Name = "Authorization", //jwt默认的参数名称 In = "header", //jwt默认存放Authorization信息的位置(请求头中) Type = "apiKey" }); string basePath = Path.GetDirectoryName(typeof(Program).Assembly.Location);//获取应用程序所在目录(绝对,不受工作目录影响,建议采用此方法获取路径) string xmlPath = Path.Combine(basePath, "LinCms.Web.xml"); options.IncludeXmlComments(xmlPath); options.OperationFilter <SwaggerFileHeaderParameter>(); }); #endregion //将Handler注册到DI系统中 services.AddScoped <IAuthorizationHandler, PermissionAuthorizationHandler>(); services.Configure <FormOptions>(options => { options.MultipartBodyLengthLimit = 1024 * 1024 * 2; options.MultipartHeadersCountLimit = 10; }); }
public void ConfigureServices(IServiceCollection services) { services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); }) .ConfigureApiBehaviorOptions(options => { options.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState) { Instance = context.HttpContext.Request.Path, Status = StatusCodes.Status400BadRequest, Type = $"https://httpstatuses.com/400", Title = "Dados inválidos", Detail = "Os dados enviados na requisição não estão corretos" }; return(new BadRequestObjectResult(problemDetails)); }; }) .AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining <PlayJokenpoValidator>()); services.AddResponseCompression(); services.AddApiVersioning(o => { o.DefaultApiVersion = new ApiVersion(1, 0); o.ReportApiVersions = true; o.AssumeDefaultVersionWhenUnspecified = true; }); services.AddVersionedApiExplorer(options => { options.GroupNameFormat = "'v'VVV"; options.SubstituteApiVersionInUrl = true; }); services.AddSwaggerGen(options => { var provider = services.BuildServiceProvider().GetRequiredService <IApiVersionDescriptionProvider>(); foreach (var description in provider.ApiVersionDescriptions) { options.SwaggerDoc(description.GroupName, new OpenApiInfo() { Title = "API Jokenpo", Version = description.ApiVersion.ToString() }); } var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); options.IncludeXmlComments(xmlPath); }); // Não rolou // services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>(); services.Configure <MvcOptions>(opt => { opt.Conventions.Insert(0, new ApiVersionRouteConvention("api/v{version:apiVersion}/")); opt.Filters.Add(typeof(GlobalExceptionFilter)); }); services.AddCors(options => { options.AddDefaultPolicy(builder => { builder.AllowAnyHeader() .AllowAnyMethod() .AllowAnyOrigin(); }); }); // services.AddDbContext<DataContext>(opt => opt.UseInMemoryDatabase("Database")); services.AddDbContext <DataContext>(opt => opt.UseSqlServer(Configuration.GetConnectionString("conn"))); services.AddTransient <IJokenpoRepository, JokenpoRepository>(); services.AddTransient <PlayJokenpoHandler, PlayJokenpoHandler>(); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddDbContext <DataContext>(options => { options.UseSqlServer((Configuration.GetConnectionString("DefaultConnection"))); }); IdentityBuilder builder = services.AddIdentityCore <User>(opt => { opt.Password.RequireDigit = false; opt.Password.RequiredLength = 4; opt.Password.RequireNonAlphanumeric = false; opt.Password.RequireUppercase = false; /* // Lockout settings. * opt.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5); * opt.Lockout.MaxFailedAccessAttempts = 5; * opt.Lockout.AllowedForNewUsers = true; */ // User settings. opt.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+!"; opt.User.RequireUniqueEmail = true; }); builder = new IdentityBuilder(builder.UserType, typeof(Role), builder.Services); builder.AddEntityFrameworkStores <DataContext>().AddDefaultTokenProviders(); builder.AddRoleValidator <RoleValidator <Role> >(); builder.AddRoleManager <RoleManager <Role> >(); builder.AddSignInManager <SignInManager <User> >(); services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.GetSection("JwtSettings:key").Value)), ValidateIssuer = false, ValidIssuer = Configuration.GetSection("JwtSettings:issuer").Value, ValidateAudience = false, ValidAudience = Configuration.GetSection("JwtSettings:audience").Value, ValidateLifetime = true, ClockSkew = TimeSpan.FromDays(Convert.ToInt32(Configuration.GetSection("JwtSettings:daysToExpiration").Value)) }; }); services.AddAuthorization(options => { options.AddPolicy("RequireSuperAdminRole", policy => policy.RequireRole("SuperAdmin")); options.AddPolicy("RequireAdminRole", policy => policy.RequireRole("Admin", "SuperAdmin")); }); services.AddControllers(setupAction => { var policy = new AuthorizationPolicyBuilder() .RequireAuthenticatedUser() .Build(); setupAction.Filters.Add(new AuthorizeFilter(policy)); setupAction.ReturnHttpNotAcceptable = true; }).AddNewtonsoftJson(setupAction => { setupAction.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); setupAction.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; }) .ConfigureApiBehaviorOptions(setupAction => { setupAction.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState) { Type = "https://AtlantisPortals.com/modelvalidationproblem", Title = "One or more model validation errors occurred.", Status = StatusCodes.Status422UnprocessableEntity, Detail = "See the errors property for details.", Instance = context.HttpContext.Request.Path }; problemDetails.Extensions.Add("traceId", context.HttpContext.TraceIdentifier); return(new UnprocessableEntityObjectResult(problemDetails) { ContentTypes = { "application/problem+json" } }); }; }); services.AddCors(options => { options.AddPolicy("AllowAllOriginsHeadersAndMethods", corsbuilder => corsbuilder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()); }); services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); // HttpContext in services by injecting it services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>(); services.AddTransient <IPropertyMappingService, PropertyMappingService>(); services.AddScoped <IUserInfoService, UserInfoService>(); services.AddScoped <IUnitOfWork, UnitOfWork>(); services.AddScoped <ISystemRepository, SystemRepository>(); services.AddScoped <IUserRepository, UserRepository>(); services.AddScoped <IAgencyRepository, AgencyRepository>(); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services .AddControllers(setupAction => { setupAction.ReturnHttpNotAcceptable = true; }) .AddNewtonsoftJson(setupAction => { setupAction.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; setupAction.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); }) .AddXmlDataContractSerializerFormatters() .ConfigureApiBehaviorOptions(setupAction => { setupAction.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState) { Type = "https://ems.com/modelvalidationproblem", Title = "One or more validation errors occured.", Status = StatusCodes.Status422UnprocessableEntity, Detail = "See the errors property for details.", Instance = context.HttpContext.Request.Path }; problemDetails.Extensions.Add("traceId", context.HttpContext.TraceIdentifier); return(new UnprocessableEntityObjectResult(problemDetails) { ContentTypes = { MediaTypes.ProblemPlusJson } }); }; }); services.Configure <MvcOptions>(config => { var newtonsoftJsonOutputFormatter = config.OutputFormatters .OfType <NewtonsoftJsonOutputFormatter>()?.FirstOrDefault(); newtonsoftJsonOutputFormatter?.SupportedMediaTypes .Add(MediaTypes.HateoasPlusJson); }); services.AddDbContext <EMSDbContext>(options => { options.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EMSApiDb;Trusted_Connection=True;"); }); services.AddAutoMapper(typeof(SkillsProfile).Assembly); services.AddCustomServices(Configuration); //services.AddAutoMapper(typeof(Startup)); //services.AddScoped(provider => new MapperConfiguration(cfg => //{ // cfg.AddProfile(new JobSkillsProfile(provider.GetService<IUnitOfWork>())); // cfg.AddProfile(new JobsProfile()); // cfg.AddProfile(new SkillsProfile()); //}).CreateMapper()); //services.AddAutoMapper(typeof(SkillsProfile), typeof(JobsProfile)); //services.AddScoped(provider => new MapperConfiguration(cfg => //{ // cfg.AddProfile(new JobsProfile()); //}).CreateMapper()); //services.AddScoped(provider => new MapperConfiguration(cfg => //{ // cfg.AddProfile(new SkillsProfile()); //}).CreateMapper()); //services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); services.AddCors(options => { options.AddPolicy("LocalHostPolicy", builder => { builder.WithOrigins("https://localhost:44375") .AllowAnyHeader() .AllowAnyMethod(); }); }); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters() { ValidateIssuer = true, ValidIssuer = Configuration["JWT:Issuer"], ValidateAudience = true, ValidAudience = Configuration["JWT:Audience"], ValidateLifetime = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWT:SecretKey"])) }; }); services.AddControllers(setup => { setup.ReturnHttpNotAcceptable = true; }) .AddNewtonsoftJson(setup => { setup.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); }).AddXmlDataContractSerializerFormatters() .ConfigureApiBehaviorOptions(setup => { setup.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState) { Type = "https://tools.ietf.org/html/rfc4918#section-11.2", Title = "Errors occured", Status = StatusCodes.Status422UnprocessableEntity, Detail = "ErrCode 422: Unprocessable Entity", Instance = context.HttpContext.Request.Path }; problemDetails.Extensions.Add("traceId", context.HttpContext.TraceIdentifier); return(new UnprocessableEntityObjectResult(problemDetails) { ContentTypes = { "application/problem+json" } }); }; }); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "Wechat Mall API", Version = "v1" }); var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); c.IncludeXmlComments(xmlPath, true); }); services.AddMemoryCache(); services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); services.AddScoped <ICategoryRepository, CategoryRepository>(); services.AddScoped <IProductRepository, ProductRepository>(); services.AddScoped <IConfigRepository, ConfigRepository>(); services.AddScoped <IUserRepository, UserRepository>(); services.AddScoped <IOrderRepository, OrderRepository>(); services.AddScoped <ICouponRepository, CouponRepository>(); services.AddScoped <IAddrRepository, AddrRepository>(); services.AddScoped <IFareRepository, FareRepository>(); services.AddDbContext <MallDbContext>(option => { option.UseMySql(Configuration.GetConnectionString("DefaultConnection")); }); services.AddImageSharp(); services.AddHttpClient(); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllers(setupAction => { setupAction.ReturnHttpNotAcceptable = true; }) .AddNewtonsoftJson(setupAction => { setupAction.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); setupAction.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; }) .AddXmlDataContractSerializerFormatters() .ConfigureApiBehaviorOptions(setupAction => { setupAction.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState) { Type = "https://mijoe.dk/modelvalidationproblem", Title = "One or more model validation errors occurred.", Status = StatusCodes.Status422UnprocessableEntity, Detail = "See the errors property for details.", Instance = context.HttpContext.Request.Path }; problemDetails.Extensions.Add("traceId", context.HttpContext.TraceIdentifier); return(new UnprocessableEntityObjectResult(problemDetails) { ContentTypes = { "application/problem+json" } }); }; }); services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); services.AddScoped <IVejledningsbookingRepository, VejledningsbookingRepository>(); services.AddDbContext <VejledningsbookingContext>(options => { // TODO: Change to inmemory DB, uninstall Sql nupkg options.UseInMemoryDatabase(databaseName: "VejledningsbookingDB"); // options.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=VejledningsbookingDB;Trusted_Connection=True;"); }); services.AddMvc(); // Register the Swagger generator, defining 1 or more Swagger documents services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Version = "v1", Title = "Vejledningsbooking API", Description = "Vejledningsbooking ASP.NET Core Web API", TermsOfService = new Uri("https://example.com/terms"), Contact = new OpenApiContact { Name = "PostMan collection", Email = string.Empty, Url = new Uri("https://www.getpostman.com/collections/dae584dc41a05579a6c6"), }, License = new OpenApiLicense { Name = "Use under LICX", Url = new Uri("https://example.com/license"), } }); // Set the comments path for the Swagger JSON and UI. var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); c.IncludeXmlComments(xmlPath); }); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddResponseCaching(); //向服务容器注册服务 services.AddControllers(setup => { //支持406 output not acceptable. setup.ReturnHttpNotAcceptable = true; //增加输出格式xml的支持:XmlDataContractSerializerOutputFormatter,默认OutputFormatters包含一个item并且是json类型的,在json后添加一个xml类型. //旧写法 //setup.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter()); //修改默认输出格式为xml,输出的数据就不是json的了. //setup.OutputFormatters.Insert(0, new XmlDataContractSerializerOutputFormatter()); //cache 缓存策略 setup.CacheProfiles.Add("120sCacheProfile", new CacheProfile { Duration = 120 }); }) //http patch方法需要通过调用这个方法支持串行化 .AddNewtonsoftJson(setup => { setup.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); }) //.net core 3.0的新写法,添加accept-type和content-type支持xml //并且这个方法能够支持更多的数据类型,比如:datetimeoffset .AddXmlDataContractSerializerFormatters() //自定义客户端错误的返回信息,ErrorMessage是由不同的validation验证设置, //api body中的内容是自定义的,正常返回400,这里定义返回422 .ConfigureApiBehaviorOptions(setup => { setup.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState) { Type = "http://www.baidu.com", Title = "傻了吧,出错咯!", Status = StatusCodes.Status422UnprocessableEntity, Detail = "歪比歪比,歪比巴卜!", Instance = context.HttpContext.Request.Path }; problemDetails.Extensions.Add("traceId", context.HttpContext.TraceIdentifier); return(new UnprocessableEntityObjectResult(problemDetails) { ContentTypes = { "application/problem+json" } }); }; }); services.Configure <MvcOptions>(config => { var newtonSoftJasonOutputFormatter = config.OutputFormatters.OfType <NewtonsoftJsonOutputFormatter>()? .FirstOrDefault(); newtonSoftJasonOutputFormatter?.SupportedMediaTypes.Add("application/vnd.company.hateoas+json"); }); services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); services.AddScoped <ICompanyRepository, CompanyRepository>(); services.AddDbContext <RoutineDbContext>(options => { options.UseSqlite("Data Source=routine.db"); }); services.AddTransient <IPropertyMappingService, PropertyMappingService>(); services.AddTransient <IPropertyCheckerService, PropertyCheckerService>(); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddResponseCaching(); services.AddDbContext <CourseLibraryContext>(options => { options.UseSqlServer( Configuration.GetConnectionString("DefaultConnection"), sqlServerOptionsAction: (sqlOptions) => { sqlOptions.EnableRetryOnFailure( maxRetryCount: 5, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); }); }); services.AddControllers((options) => { options.ReturnHttpNotAcceptable = true; // MVC com restrição de XML e adição de filtro de ações. // options.OutputFormatters.Remove(new XmlDataContractSerializerOutputFormatter()); options.CacheProfiles.Add("120SecondsChaceProfile", new CacheProfile() { Duration = 120 }); }) .AddJsonOptions((options) => { // Remove null fields from API JSON response options.JsonSerializerOptions.IgnoreNullValues = true; }) .AddNewtonsoftJson((setupAction) => { setupAction.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); }) .ConfigureApiBehaviorOptions(setupAction => { setupAction.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState) { Type = "https://courselibrary.com/modelvalidationproblem", Title = "Ocorreu um erro de validação ou de modelo.", Status = StatusCodes.Status422UnprocessableEntity, Detail = "Consulte a propriedade de erros para obter detalhes.", Instance = context.HttpContext.Request.Path }; problemDetails.Extensions.Add("traceId", context.HttpContext.TraceIdentifier); return(new UnprocessableEntityObjectResult(problemDetails) { ContentTypes = { "application/problem+json" } }); }; }) .AddXmlDataContractSerializerFormatters(); // permite response and request no formato xml // permitir o fromHeader Accept services.Configure <MvcOptions>(config => { var newtonsoftJsonOutputFormatter = config.OutputFormatters .OfType <NewtonsoftJsonOutputFormatter>()?.FirstOrDefault(); if (newtonsoftJsonOutputFormatter != null) { newtonsoftJsonOutputFormatter.SupportedMediaTypes.Add("application/vnd.marvin.hateoas+json"); } }); services.AddScoped <ICourseLibraryRepository, CourseLibraryRepository>(); services.AddTransient <IPropertyMappingService, PropertyMappingService>(); services.AddTransient <IPropertyCheckerService, PropertyCheckerService>(); services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); }
public void ConfigureServices(IServiceCollection services) { services.AddContext(Configuration); services.AddCsRedisCore(Configuration); services.AddSecurity(Configuration); #region AddJwtBearer var jsonWebTokenSettings = services.BuildServiceProvider().GetRequiredService <JsonWebTokenSettings>(); services.AddAuthentication(opts => { opts.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; opts.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; opts.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddCookie(options => { options.LoginPath = "/cms/oauth2/signin"; options.LogoutPath = "/cms/oauth2/signout"; }) .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => { //identityserver4 地址 也就是本项目地址 options.Authority = Configuration["Service:Authority"]; options.RequireHttpsMetadata = false; options.Audience = Configuration["Service:Name"]; options.TokenValidationParameters = new TokenValidationParameters { // The signing key must match! ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jsonWebTokenSettings.Key)), // Validate the JWT Issuer (iss) claim ValidateIssuer = true, ValidIssuer = jsonWebTokenSettings.Issuer, // Validate the JWT Audience (aud) claim ValidateAudience = true, ValidAudience = jsonWebTokenSettings.Audience, // Validate the token expiry ValidateLifetime = true, // If you want to allow a certain amount of clock drift, set thatValidIssuer here //ClockSkew = TimeSpan.Zero }; //options.TokenValidationParameters = new TokenValidationParameters() //{ // ClockSkew = TimeSpan.Zero //偏移设置为了0s,用于测试过期策略,完全按照access_token的过期时间策略,默认原本为5分钟 //}; //使用Authorize设置为需要登录时,返回json格式数据。 options.Events = new JwtBearerEvents() { OnAuthenticationFailed = context => { //Token expired if (context.Exception.GetType() == typeof(SecurityTokenExpiredException)) { context.Response.Headers.Add("Token-Expired", "true"); } return(Task.CompletedTask); }, OnChallenge = context => { //此处代码为终止.Net Core默认的返回类型和数据结果,这个很重要哦 context.HandleResponse(); string message; ErrorCode errorCode; int statusCode = StatusCodes.Status401Unauthorized; if (context.Error == "invalid_token" && context.ErrorDescription == "The token is expired") { message = "令牌过期"; errorCode = ErrorCode.TokenExpired; statusCode = StatusCodes.Status422UnprocessableEntity; } else if (context.Error == "invalid_token" && context.ErrorDescription.IsNullOrEmpty()) { message = "令牌失效"; errorCode = ErrorCode.TokenInvalidation; } else { message = "请先登录" + context.ErrorDescription; //""认证失败,请检查请求头或者重新登录"; errorCode = ErrorCode.AuthenticationFailed; } context.Response.ContentType = "application/json"; context.Response.StatusCode = statusCode; context.Response.WriteAsync(new UnifyResponseDto(errorCode, message, context.HttpContext).ToString()); return(Task.FromResult(0)); } }; }) .AddGitHub(options => { options.ClientId = Configuration["Authentication:GitHub:ClientId"]; options.ClientSecret = Configuration["Authentication:GitHub:ClientSecret"]; options.Scope.Add("user:email"); options.ClaimActions.MapJsonKey(LinConsts.Claims.AvatarUrl, "avatar_url"); //登录成功后可通过 authenticateResult.Principal.FindFirst(ClaimTypes.Uri)?.Value; 得到GitHub头像 options.ClaimActions.MapJsonKey(LinConsts.Claims.BIO, "bio"); options.ClaimActions.MapJsonKey(LinConsts.Claims.BlogAddress, "blog"); }) .AddQQ(options => { options.ClientId = Configuration["Authentication:QQ:ClientId"]; options.ClientSecret = Configuration["Authentication:QQ:ClientSecret"]; }); #endregion services.AddAutoMapper(typeof(UserProfile).Assembly, typeof(PoemProfile).Assembly); services.AddCors(); #region Mvc services.AddControllers(options => { options.ValueProviderFactories.Add(new ValueProviderFactory()); //设置SnakeCase形式的QueryString参数 //options.Filters.Add<LogActionFilterAttribute>(); // 添加请求方法时的日志记录过滤器 options.Filters.Add <LinCmsExceptionFilter>(); // }) .AddNewtonsoftJson(opt => { opt.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:MM:ss"; // 设置自定义时间戳格式 opt.SerializerSettings.Converters = new List <JsonConverter>() { new LinCmsTimeConverter() }; // 设置下划线方式,首字母是小写 opt.SerializerSettings.ContractResolver = new DefaultContractResolver() { NamingStrategy = new SnakeCaseNamingStrategy() { ProcessDictionaryKeys = true }, }; }) .ConfigureApiBehaviorOptions(options => { options.SuppressConsumesConstraintForFormFileParameters = true; //SuppressUseValidationProblemDetailsForInvalidModelStateResponses; //自定义 BadRequest 响应 options.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState); var resultDto = new UnifyResponseDto(ErrorCode.ParameterError, problemDetails.Errors, context.HttpContext); return(new BadRequestObjectResult(resultDto) { ContentTypes = { "application/json" } }); }; }); #endregion services.AddDIServices(); #region Swagger //Swagger重写PascalCase,改成SnakeCase模式 services.TryAddEnumerable(ServiceDescriptor.Transient <IApiDescriptionProvider, ApiDescriptionProvider>()); //Register the Swagger generator, defining 1 or more Swagger documents services.AddSwaggerGen(options => { string ApiName = "LinCms.Web"; options.SwaggerDoc("v1", new OpenApiInfo() { Title = ApiName + RuntimeInformation.FrameworkDescription, Version = "v1", Contact = new OpenApiContact { Name = ApiName, Email = "*****@*****.**", Url = new Uri("https://www.cnblogs.com/igeekfan/") }, License = new OpenApiLicense { Name = ApiName + " 官方文档", Url = new Uri( "https://luoyunchong.github.io/vovo-docs/dotnetcore/lin-cms/dotnetcore-start.html") } }); var security = new OpenApiSecurityRequirement() { { new OpenApiSecurityScheme { Reference = new OpenApiReference() { Id = "Bearer", Type = ReferenceType.SecurityScheme } }, Array.Empty <string>() } }; options.AddSecurityRequirement(security); //添加一个必须的全局安全信息,和AddSecurityDefinition方法指定的方案名称要一致,这里是Bearer。 options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Description = "JWT授权(数据将在请求头中进行传输) 参数结构: \"Authorization: Bearer {token}\"", Name = "Authorization", //jwt默认的参数名称 In = ParameterLocation.Header, //jwt默认存放Authorization信息的位置(请求头中) Type = SecuritySchemeType.ApiKey }); try { string xmlPath = Path.Combine(AppContext.BaseDirectory, $"{typeof(Startup).Assembly.GetName().Name}.xml"); options.IncludeXmlComments(xmlPath, true); //实体层的xml文件名 string xmlEntityPath = Path.Combine(AppContext.BaseDirectory, $"{typeof(IEntity).Assembly.GetName().Name}.xml"); options.IncludeXmlComments(xmlEntityPath); //Dto所在类库 string applicationPath = Path.Combine(AppContext.BaseDirectory, $"{typeof(IApplicationService).Assembly.GetName().Name}.xml"); options.IncludeXmlComments(applicationPath); } catch (Exception ex) { Log.Logger.Warning(ex.Message); } }); #endregion //应用程序级别设置 services.Configure <FormOptions>(options => { //单个文件上传的大小限制为8 MB 默认134217728 应该是128MB options.MultipartBodyLengthLimit = 1024 * 1024 * 8; //8MB }); #region 分布式事务一致性CAP IConfigurationSection configurationSection = Configuration.GetSection("ConnectionStrings:MySql"); services.AddCap(x => { x.UseMySql(configurationSection.Value); bool isEnableInMemoryQueue = Configuration["CAP:InMemoryQueue:IsEnabled"].ToBoolean(); if (isEnableInMemoryQueue) { x.UseInMemoryMessageQueue(); } bool isEnableRabbitMq = Configuration["CAP:RabbitMQ:IsEnabled"].ToBoolean(); if (isEnableRabbitMq) { x.UseRabbitMQ(options => { options.HostName = Configuration["CAP:RabbitMQ:HostName"]; options.UserName = Configuration["CAP:RabbitMQ:UserName"]; options.Password = Configuration["CAP:RabbitMQ:Password"]; options.VirtualHost = Configuration["CAP:RabbitMQ:VirtualHost"]; }); } x.UseDashboard(); x.FailedRetryCount = 5; x.FailedThresholdCallback = (type) => { Console.WriteLine( $@"A message of type {type} failed after executing {x.FailedRetryCount} several times, requiring manual troubleshooting. Message name: {type.Message.GetName()}"); }; }); #endregion services.Configure <ForwardedHeadersOptions>(options => { options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; }); //之前请注入AddCsRedisCore,内部实现IDistributedCache接口 services.AddIpRateLimiting(Configuration); services.AddHealthChecks(); }
public override ActionResult ValidationProblem(ValidationProblemDetails descriptor) { return(base.ValidationProblem(descriptor)); }
/// <summary> /// Configures the error handling middlewere /// </summary> /// <param name="services"></param> /// <returns></returns> public static IServiceCollection AddCustomProblemDetails(this IServiceCollection services) { services.Configure <ApiBehaviorOptions>(options => { options.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState) { Instance = context.HttpContext.Request.Path, Status = StatusCodes.Status400BadRequest, Title = "https://sgs.com/400", Detail = ApiConstants.ModelStateValidation }; return(new BadRequestObjectResult(problemDetails) { ContentTypes = { "application/problem+json", "application/problem+xml" } }); }; }); return(services.AddProblemDetails(config => { config.Map <BusinessValidationException>((context, ex) => new ProblemDetails { Title = BusinessValidationException.DefaultMessage, Status = StatusCodes.Status412PreconditionFailed, Detail = ex.ToString() }); config.Map <ResourceAlreadyInUseException>((context, ex) => new ProblemDetails { Title = ResourceAlreadyInUseException.DefaultMessage, Status = StatusCodes.Status403Forbidden, Detail = ex.ToString() }); config.Map <ResourceAlreadyExistException>((context, ex) => new ProblemDetails { Title = ResourceAlreadyExistException.DefaultMessage, Status = StatusCodes.Status409Conflict, Detail = ex.ToString() }); config.Map <ResourceNotFoundException>((context, ex) => new ProblemDetails { Title = ResourceNotFoundException.DefaultMessage, Status = StatusCodes.Status404NotFound, Detail = ex.ToString() }); config.Map <Exception>((context, ex) => new ProblemDetails { Title = "An unhandled error occurred processing your request", Status = StatusCodes.Status500InternalServerError, Detail = ex.ToString() }); })); }