Ejemplo n.º 1
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider, ILoggerFactory loggerFactory, IApiVersionDescriptionProvider provider)
        {
            app.UseDefaultFiles();

            var cultures = Configuration.GetSection("SupportedCultures").Get <string[]>();

            var supportedCultures = new List <CultureInfo>();

            foreach (var culture in cultures)
            {
                supportedCultures.Add(new CultureInfo(culture));
            }

            app.UseRequestLocalization(new RequestLocalizationOptions
            {
                DefaultRequestCulture = new RequestCulture("en"),
                SupportedCultures     = supportedCultures,
                SupportedUICultures   = supportedCultures
            });

            env.EnvironmentName = Environments.Development;

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseForwardedHeaders(new ForwardedHeadersOptions
                {
                    ForwardedHeaders = ForwardedHeaders.XForwardedFor,

                    // IIS is also tagging a X-Forwarded-For header on, so we need to increase this limit,
                    // otherwise the X-Forwarded-For we are passing along from the browser will be ignored
                    ForwardLimit = 2
                });
            }

            if (!Directory.Exists("Logs"))
            {
                Directory.CreateDirectory("Logs");
            }

            var webSocketOptions = new WebSocketOptions()
            {
                KeepAliveInterval = TimeSpan.FromSeconds(5),
                ReceiveBufferSize = 4 * 1024
            };

            app.UseWebSockets(webSocketOptions);

            // Enable middleware to serve generated Swagger as a JSON endpoint.
            app.UseSwagger(options =>
            {
                options.PreSerializeFilters.Add((swagger, httpReq) =>
                {
                    //swagger.Host = httpReq.Host.Value;

                    var ampersand = "&amp;";

                    foreach (var path in swagger.Paths)
                    {
                        if (path.Value.Operations.Any(x => x.Key == OperationType.Get && x.Value.Deprecated))
                        {
                            path.Value.Operations.First(x => x.Key == OperationType.Get).Value.Description = path.Value.Operations.First(x => x.Key == OperationType.Get).Value.Description.Replace(ampersand, "&");
                        }

                        if (path.Value.Operations.Any(x => x.Key == OperationType.Delete && x.Value?.Description != null))
                        {
                            path.Value.Operations.First(x => x.Key == OperationType.Delete).Value.Description = path.Value.Operations.First(x => x.Key == OperationType.Delete).Value.Description.Replace(ampersand, "&");
                        }
                    }

                    var paths = swagger.Paths.ToDictionary(p => p.Key, p => p.Value);
                    foreach (KeyValuePair <string, OpenApiPathItem> path in paths)
                    {
                        swagger.Paths.Remove(path.Key);
                        swagger.Paths.Add(path.Key.ToLowerInvariant(), path.Value);
                    }
                });
            });

            // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.), specifying the Swagger JSON endpoint.
            app.UseSwaggerUI(options =>
            {
                options.IndexStream = () => File.OpenRead("Views/Swagger/swagger-ui.html");
                foreach (var description in provider.ApiVersionDescriptions)
                {
                    options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant());
                }

                options.EnableFilter();
            });

            app.UseCors(builder => builder.WithOrigins("http://localhost:4200").AllowAnyHeader().AllowAnyMethod());
            app.UseStaticFiles();
            app.UseRouting();

            #region Error handler

            // Different middleware for api and ui requests
            app.UseWhen(context => context.Request.Path.StartsWithSegments("/api"), appBuilder =>
            {
                var localizer = serviceProvider.GetService <IStringLocalizer <ErrorsResource> >();
                var logger    = loggerFactory.CreateLogger("GlobalErrorHandling");

                // Exception handler - show exception data in api response
                appBuilder.UseExceptionHandler(new ExceptionHandlerOptions
                {
                    ExceptionHandler = async context =>
                    {
                        var errorModel = new ErrorResponseModel(localizer);
                        var result     = new ContentResult();

                        var exception = context.Features.Get <IExceptionHandlerPathFeature>();

                        if (exception.Error is CustomException)
                        {
                            var ex = (CustomException)exception.Error;

                            result = errorModel.Error(ex);
                        }
                        else
                        {
                            var message = exception.Error.InnerException?.Message ?? exception.Error.Message;
                            logger.LogError($"{exception.Path} - {message}");

                            errorModel.AddError("general", message);
                            result = errorModel.InternalServerError(env.IsDevelopment() ? exception.Error.StackTrace : null);
                        }

                        context.Response.StatusCode  = result.StatusCode.Value;
                        context.Response.ContentType = result.ContentType;

                        await context.Response.WriteAsync(result.Content);
                    }
                });

                // Handles responses with status codes (correctly executed requests, without any exceptions)
                appBuilder.UseStatusCodePages(async context =>
                {
                    string message = "";

                    List <ErrorKeyValue> errors = new List <ErrorKeyValue>();

                    switch (context.HttpContext.Response.StatusCode)
                    {
                    case 400:
                        message = "Bad Request";
                        break;

                    case 401:
                        message = "Unauthorized";
                        errors.Add(new ErrorKeyValue("token", "Token invalid"));
                        break;

                    case 403:
                        message = "Forbidden";
                        break;

                    case 404:
                        message = "Not found";
                        break;

                    case 500:
                        message = "Internal Server Error";
                        break;
                    }

                    context.HttpContext.Response.ContentType = "application/json";
                    await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(new ErrorResponseModel(localizer)
                    {
                        Code       = message,
                        StackTrace = "",
                        Errors     = errors
                    }, new JsonSerializerSettings {
                        Formatting = Formatting.Indented
                    }));
                });
            });

            app.UseWhen(context => !context.Request.Path.StartsWithSegments("/api"), appBuilder =>
            {
                appBuilder.UseExceptionHandler("/Error");
                appBuilder.UseStatusCodePagesWithReExecute("/Error", "?statusCode={0}");
            });

            #endregion

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id}");
            });
        }
Ejemplo n.º 2
0
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            // Apply this logic only if action have one reference type parameter
            if (context.ActionDescriptor.Parameters.Count > 0 && context.ActionDescriptor.Parameters.Any(x => x.ParameterType.IsClass))
            {
                if (_errorsLocalizer == null)
                {
                    using (var scope = context.HttpContext.RequestServices.CreateScope())
                    {
                        _errorsLocalizer = scope.ServiceProvider.GetRequiredService <IStringLocalizer <ErrorsResource> >();
                    }
                }

                var actionData = context.ActionDescriptor.GetType().GetMethod(context.ActionDescriptor.DisplayName);

                // Return bad request if model is null or non of argument if value type
                if (!context.ActionArguments.Any())
                {
                    context.Result = new ContentResult
                    {
                        Content = JsonConvert.SerializeObject(new ErrorResponseModel(_errorsLocalizer)
                        {
                            Code   = ErrorCode.BadRequest,
                            Errors = new List <ErrorKeyValue>
                            {
                                new ErrorKeyValue("model", "Model is invalid")
                            }
                        }),
                        StatusCode  = (int)HttpStatusCode.BadRequest,
                        ContentType = "application/json"
                    };

                    return;
                }
                else if (context.ActionArguments.Count != context.ActionDescriptor.Parameters.Count)
                {
                    // In case if one of argument empty (it can not be bind) and not optional return error with this model
                    var data = context.ActionDescriptor.Parameters.Where(x => x.ParameterType.IsClass && !((ControllerParameterDescriptor)x).ParameterInfo.IsOptional && !context.ActionArguments.ContainsKey(x.Name)).ToList();

                    if (data.Any())
                    {
                        _errors = new ErrorResponseModel(_errorsLocalizer);
                        foreach (var x in data)
                        {
                            _errors.AddError(x.Name, $"{x.Name} is invalid");
                        }

                        context.Result = _errors.BadRequest();
                        return;
                    }
                }
            }

            // Build validation errors response
            if (!context.ModelState.IsValid)
            {
                _errors = new ErrorResponseModel(_errorsLocalizer);
                _errors.BuildErrors(context.ModelState);
                context.Result = _errors.BadRequest();
            }

            return;
        }