public override void OnActionExecuting(ActionExecutingContext context)
 {
     // Check if model binding is valid
     if (!context.ModelState.IsValid)
     {
         // filter all the attributes with errors
         var errorLists = context.ModelState.Select(x => x.Value.Errors)
                          .Where(y => y.Count > 0)
                          .ToList();
         // flatten, then aggregate them to single list of error
         var errors = errorLists.Aggregate(new List <string>(), (acc, errorList) =>
         {
             // map errors to its errorMessage
             return(acc.Concat(errorList.Select(x => x.ErrorMessage)).ToList());
         });
         //return in
         var result = new UnprocessableEntityObjectResult(new { errors });
         // return 422 immediately
         context.Result = result;
     }
     else
     {
         base.OnActionExecuting(context);
     }
 }
        public bool ValidateGetCollection(
            OfmForGetCollectionQueryResult <TOfmForGet> ofmForGetCollectionQueryResult,
            out ObjectResult objectResult)
        {
            objectResult = null;
            if (ofmForGetCollectionQueryResult.ErrorMessages.Count() > 0)
            {
                foreach (var errorMessage in ofmForGetCollectionQueryResult.ErrorMessages)
                {
                    _controller.ModelState.AddModelError(_shortCamelCasedControllerName, errorMessage);
                }
                objectResult = new UnprocessableEntityObjectResult(_controller.ModelState);
                return(false);
            }

            var allOfmForGet = ofmForGetCollectionQueryResult.ReturnedTOfmForGetCollection;

            if (allOfmForGet.OfmForGets.Count() == 0)
            {
                _controller.ModelState.AddModelError(_shortCamelCasedControllerName, $"No {_shortCamelCasedControllerName.ToPlural()} found");
                objectResult = new EntityNotFoundObjectResult(_controller.ModelState);
                return(false);
            }

            return(true);
        }
        public Task <IActionResult> Handle(CreateCategoryCommand request, CancellationToken cancellationToken)
        {
            IActionResult response = new BadRequestResult();

            try
            {
                var validatorResults = _createValidator.Validate(request);

                if (!validatorResults.IsValid)
                {
                    var errors = validatorResults.Errors.Select(f => f.ErrorMessage);
                    var output = ApiResultHelper.GenerateErrorResponse(HttpStatusCode.UnprocessableEntity, errors);

                    response = new UnprocessableEntityObjectResult(output);
                }
                else
                {
                    var entity = _mapper.Map <Category>(request);
                    var result = _repository.Save(entity).Result;

                    response = new OkObjectResult(ApiResultHelper.GenerateResponse(HttpStatusCode.OK, result));
                }
            }
            catch (Exception ex)
            {
                if (this._logger != null)
                {
                    _logger.LogError(ex, "Exception");
                }
            }

            return(Task.FromResult(response));
        }
        public bool ValidateGetById(
            OfmForGetQueryResult <TOfmForGet> ofmForGetQueryResult,
            int id,
            out ObjectResult objectResult)
        {
            objectResult = null;
            if (ofmForGetQueryResult.ErrorMessages.Count > 0)
            {
                foreach (var errorMessage in ofmForGetQueryResult.ErrorMessages)
                {
                    _controller.ModelState.AddModelError(_shortCamelCasedControllerName, errorMessage);
                }
                objectResult = new UnprocessableEntityObjectResult(_controller.ModelState);
                return(false);
            }

            //var entity = await _repo.GetById(id);
            if (ofmForGetQueryResult.ReturnedTOfmForGet == null)
            {
                _controller.ModelState.AddModelError(_shortCamelCasedControllerName, "No " + _shortCamelCasedControllerName + " found for id=" + id);
                objectResult = new EntityNotFoundObjectResult(_controller.ModelState);
                return(false);
            }
            return(true);
        }
        public void NotCreateNewUserWhenModelValidAndIdentityError()
        {
            var userCreateModel = new UserCreateModel
            {
                FirstName = "Jess",
                LastName  = "Scott",
                Email     = "*****@*****.**",
                Password  = "******"
            };
            var mappedUserEntity = new GameUser
            {
                FirstName = userCreateModel.FirstName,
                LastName  = userCreateModel.LastName,
                Email     = userCreateModel.Email,
                UserName  = userCreateModel.Email
            };

            _mockedMapper.Setup(m => m.Map <GameUser>(It.IsAny <UserCreateModel>())).Returns(mappedUserEntity);
            _mockedRepository.Setup(x => x.AddGameUser(It.IsAny <GameUser>(), It.IsAny <string>()))
            .Returns(Task.FromResult(IdentityResult.Failed()));

            IActionResult result = _sut.CreateUser(userCreateModel);

            _mockedRepository.Verify(
                x => x.AddGameUser(It.IsAny <GameUser>(), It.Is <string>(p => p == userCreateModel.Password)), Times.Once);

            // Check returned result.
            UnprocessableEntityObjectResult badResult = Assert.IsType <UnprocessableEntityObjectResult>(result);

            Assert.Equal(422, badResult.StatusCode);
        }
示例#6
0
        private IActionResult CreateErrorResult(Result result)
        {
            ActionResult         actionResult;
            ModelStateDictionary modelState = GetErrors(result);

            ValidationResult res = result.Notifications.FirstOrDefault(x => !x.IsValid);

            if (res == null || res.Errors.Count == 0)
            {
                return(new BadRequestObjectResult(modelState));
            }

            switch (res.Errors.First().ErrorCode)
            {
            case nameof(ErrorType.NotFound):
                actionResult = new NotFoundObjectResult(modelState);
                break;

            case nameof(ErrorType.BadRequest):
                actionResult = new UnprocessableEntityObjectResult(modelState);
                break;

            case nameof(ErrorType.Unauthorized):
                actionResult = new UnauthorizedResult();
                break;

            default:
                actionResult = new BadRequestObjectResult(modelState);
                break;
            }

            return(actionResult);
        }
示例#7
0
        private static Task <bool> HandleChangeSetValidationException(
            ExceptionContext context,
            CancellationToken cancellationToken)
        {
            if (context.Exception is ChangeSetValidationException validationException)
            {
                var result = new
                {
                    error = new
                    {
                        code       = string.Empty,
                        innererror = new
                        {
                            message = validationException.Message,
                            type    = validationException.GetType().FullName,
                        },
                        message           = "Validaion failed for one or more objects.",
                        validationentries = validationException.ValidationResults,
                    },
                };

                // TODO: check that content negotiation etc works.
                var objectResult = new UnprocessableEntityObjectResult(result);
                context.Result = objectResult;
                return(Task.FromResult(true));
            }

            return(Task.FromResult(false));
        }
示例#8
0
    public void UnprocessableEntityObjectResult_SetsStatusCodeAndValue()
    {
        // Arrange & Act
        var obj    = new object();
        var result = new UnprocessableEntityObjectResult(obj);

        // Assert
        Assert.Equal(StatusCodes.Status422UnprocessableEntity, result.StatusCode);
        Assert.Equal(obj, result.Value);
    }
示例#9
0
    public void UnprocessableEntityObjectResult_ModelState_SetsStatusCodeAndValue()
    {
        // Arrange & Act
        var result = new UnprocessableEntityObjectResult(new ModelStateDictionary());

        // Assert
        Assert.Equal(StatusCodes.Status422UnprocessableEntity, result.StatusCode);
        var errors = Assert.IsType <SerializableError>(result.Value);

        Assert.Empty(errors);
    }
示例#10
0
        public void OnException(ExceptionContext context)
        {
            var           ex = context.Exception;
            IActionResult result;

            if (ex is TaskCanceledException || ex is OperationCanceledException)
            {
                // It doesn't matter what we return here since the client is not interested anymore
                result = new BadRequestResult();
            }
            else if (ex is ForbiddenException exf)
            {
                // The user is
                if (exf.NotMember)
                {
                    var headers = context.HttpContext.Response.Headers;

                    // Admin
                    headers.Set("x-admin-settings-version", Constants.Unauthorized);
                    headers.Set("x-admin-permissions-version", Constants.Unauthorized);
                    headers.Set("x-admin-user-settings-version", Constants.Unauthorized);

                    // Application
                    headers.Set("x-settings-version", Constants.Unauthorized);
                    headers.Set("x-definitions-version", Constants.Unauthorized);
                    headers.Set("x-permissions-version", Constants.Unauthorized);
                    headers.Set("x-user-settings-version", Constants.Unauthorized);
                }

                result = new StatusCodeResult((int)HttpStatusCode.Forbidden);
            }
            else if (ex is NotFoundException exnf)
            {
                result = new NotFoundObjectResult(exnf.GetIds());
            }
            else if (ex is ValidationException exv)
            {
                result = new UnprocessableEntityObjectResult(ToModelState(exv.ModelState));
            }
            else if (ex is ReportableException)
            {
                // Any exception inheriting from this can be safely reported to the client
                result = new BadRequestObjectResult(ex.Message);
            }
            else if (ex is System.Data.SqlClient.SqlException sx && sx.Number == 4060)
            {
                // A DB in single user mode returns 4060 error.
                result = new BadRequestObjectResult(_localizer["Error_SystemUnderMaintenance"]);
            }
示例#11
0
        public static ActionResult ToActionResult(this Result result)
        {
            var actionResult = default(ActionResult);

            if (result.IsFailed)
            {
                actionResult = new UnprocessableEntityObjectResult(result.Errors);
            }
            else
            {
                actionResult = new NoContentResult();
            }

            return(actionResult);
        }
        public void NotCreateUserWhenModelError()
        {
            _sut.ModelState.AddModelError("x", "Model Error");
            var userCreateModel = new UserCreateModel
            {
                FirstName = "Jess"
            };

            IActionResult result = _sut.CreateUser(userCreateModel);

            _mockedRepository.Verify(
                x => x.AddGameUser(It.IsAny <GameUser>(), It.Is <string>(p => p == userCreateModel.Password)), Times.Never);
            UnprocessableEntityObjectResult badResult = Assert.IsType <UnprocessableEntityObjectResult>(result);

            Assert.Equal(422, badResult.StatusCode);
        }
示例#13
0
        public void ConfigureServices(IServiceCollection services)
        {
            RegisterServices(services);
            RegisterDateTimeProvider(services);

            ConfigureDatabase(services);

            ConfigureCors(services);

            services.AddMediatR(typeof(Login.Handler).Assembly);
            services.AddGenericMediatorHandlers();
            services.AddAutoMapper(
                typeof(LoginDtoMappingProfile).Assembly,
                typeof(Modify.MappingProfile).Assembly);
            services.AddHealthChecks().AddDbContextCheck <ArpaContext>();

            services.Configure <ApiBehaviorOptions>(options => options.SuppressInferBindingSourcesForParameters = true);
            services
            .AddControllers()
            .AddJsonOptions(options => options.JsonSerializerOptions.Converters
                            .Add(new DateTimeJsonConverter()))
            .AddApplicationPart(typeof(Startup).Assembly)
            .AddFluentValidation(config =>
            {
                config.RegisterValidatorsFromAssemblyContaining <LoginDtoValidator>();
                config.RegisterValidatorsFromAssemblyContaining <Validator>();
                config.ValidatorFactoryType = typeof(HttpContextServiceProviderValidatorFactory);     // Workaround https://github.com/micro-elements/MicroElements.Swashbuckle.FluentValidation#error-systeminvalidoperationexception-cannot-resolve-ivalidatort-from-root-provider-because-it-requires-scoped-service-tdependency
            })
            .ConfigureApiBehaviorOptions(options =>
            {
                options.InvalidModelStateResponseFactory = context =>
                {
                    ProblemDetailsFactory problemDetailsFactory = context.HttpContext.RequestServices.GetRequiredService <ProblemDetailsFactory>();
                    ValidationProblemDetails problemDetails     = problemDetailsFactory.CreateValidationProblemDetails(context.HttpContext, context.ModelState, statusCode: 422);
                    var result = new UnprocessableEntityObjectResult(problemDetails);
                    result.ContentTypes.Add("application/problem+json");
                    result.ContentTypes.Add("application/problem+xml");
                    return(result);
                };
            });

            ConfigureSwagger(services);

            ConfigureAuthentication(services);

            ConfigureAuthorization(services);
        }
        public void NotUpdateUserWhenModelValidAndIdentityError(string id)
        {
            string userId          = "32c88adb-056a-48b9-a898-632ff09806c1";
            var    userUpdateModel = new UserUpdateModel
            {
                FirstName = "Jess",
                LastName  = "Brown",
                Email     = "*****@*****.**"
            };
            var foundUserEntity = new GameUser
            {
                Id        = userId,
                UserName  = "******",
                FirstName = "Jess",
                LastName  = "Scott",
                Email     = "*****@*****.**"
            };

            _mockedContext.SetupGet(x => x.User.Identity).Returns(_mockedIdentity.Object);
            _mockedRepository.Setup(x => x.GetUserId(It.IsAny <ClaimsPrincipal>()))
            .Returns(userId);
            _mockedRepository.Setup(x => x.GetUser(It.IsAny <string>()))
            .Returns(Task.FromResult(foundUserEntity));
            _mockedMapper.Setup(m => m.Map <UserUpdateModel, GameUser>(It.IsAny <UserUpdateModel>(), It.IsAny <GameUser>()))
            .Callback((UserUpdateModel userModel, GameUser userEntity) => {
                foundUserEntity.FirstName = userModel.FirstName;
                foundUserEntity.LastName  = userModel.LastName;
                foundUserEntity.Email     = userModel.Email;
                foundUserEntity.UserName  = userModel.Email;
            });
            _mockedRepository.Setup(x => x.UpdateGameUser(It.IsAny <GameUser>()))
            .Returns(Task.FromResult(IdentityResult.Failed()));

            IActionResult result = _sut.UpdateUser(id, userUpdateModel);

            _mockedRepository.Verify(
                x => x.GetUser(It.IsAny <string>()), Times.Once);
            _mockedRepository.Verify(
                x => x.UpdateGameUser(It.IsAny <GameUser>()), Times.Once);

            UnprocessableEntityObjectResult badResult = Assert.IsType <UnprocessableEntityObjectResult>(result);

            Assert.Equal(422, badResult.StatusCode);
        }
示例#15
0
        /// <summary>
        /// Méthode pour générer les ApiEnveloppe de type 422
        /// </summary>
        /// <param name="actionContext"></param>
        /// <returns></returns>
        public static IActionResult InvalidModelStateEnveloppeFactory(ActionContext actionContext)
        {
            var result = new UnprocessableEntityObjectResult(new ApiEnveloppe422
            {
                Messages = new List <Message>
                {
                    new Message
                    {
                        Id       = "API_001",
                        Code     = "422",
                        Severity = "1",
                        Text     = "Une ou plusieurs erreurs de validiton sont survenues"
                    }
                },
                Result = new ValidationProblemDetails(actionContext.ModelState).Errors
            });

            return(result);
        }
示例#16
0
        public static ActionResult <T> ToActionResult <T>(this Result <T> result)
        {
            var actionResult = default(ActionResult);

            if (result.IsFailed)
            {
                actionResult = new UnprocessableEntityObjectResult(result.Errors);
            }
            else if (result.IsSucceeded)
            {
                actionResult = new OkObjectResult(result.Container);
            }
            else
            {
                actionResult = new NoContentResult();
            }

            return(new ActionResult <T>(actionResult));
        }
示例#17
0
        public bool ValidatePost(
            TOfmForPost ofmForPost,
            out ObjectResult objectResult)
        {
            objectResult = null;
            if (ofmForPost == null)
            {
                _controller.ModelState.AddModelError(_shortCamelCasedControllerName, "The supplied body for the " + _shortCamelCasedControllerName + " is null.");
                objectResult = new BadRequestObjectResult(_controller.ModelState);
                return(false);
            }

            if (!_controller.ModelState.IsValid)
            {
                objectResult = new UnprocessableEntityObjectResult(_controller.ModelState);
                return(false);
            }
            return(true);
        }
示例#18
0
 // 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)
 {
     // Applicatioin Services
     services.AddScoped <IAccountRepository, AccountRepository>();
     services.AddControllers();
     // Model validation error response
     services.Configure <ApiBehaviorOptions>(options =>
     {
         options.InvalidModelStateResponseFactory = context =>
         {
             var errors = new SerializableError(context.ModelState);
             var result = new UnprocessableEntityObjectResult(new { errors });
             return(result);
         };
     });
     // Register Swagger generator.
     services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo {
             Title = "Thought.API", Version = "v1"
         }); });
 }
        public void NotUpdateUserWhenModelInvalid(string id)
        {
            // string userId = "32c88adb-056a-48b9-a898-632ff09806c1";
            var userUpdateModel = new UserUpdateModel
            {
                FirstName = "Jess",
                LastName  = "Brown",
                Email     = ""
            };

            _sut.ModelState.AddModelError("x", "Model Error");
            _mockedRepository.Setup(x => x.UpdateGameUser(It.IsAny <GameUser>()));

            IActionResult result = _sut.UpdateUser(id, userUpdateModel);

            _mockedRepository.Verify(
                x => x.GetUser(It.IsAny <string>()), Times.Never);
            _mockedRepository.Verify(
                x => x.UpdateGameUser(It.IsAny <GameUser>()), Times.Never);

            UnprocessableEntityObjectResult badResult = Assert.IsType <UnprocessableEntityObjectResult>(result);

            Assert.Equal(422, badResult.StatusCode);
        }
示例#20
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext <AppDbContext>(options =>
                                                 options.UseMySql(Configuration.GetConnectionString("DefaultConnection")));

            services.AddCors();

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

            // configure strongly typed settings objects
            var appSettingsSection = Configuration.GetSection("AppSettings");

            services.Configure <AppSetting>(appSettingsSection);

            // configure jwt authentication
            var appSettings = appSettingsSection.Get <AppSetting>();
            var key         = Encoding.ASCII.GetBytes(appSettings.Secret);

            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
                };
            });

            // configure DI for application services
            services.AddScoped <IAuthServices, AuthServices>();
            services.AddScoped <IUserRepository, UserRepository>();
            services.AddScoped <IUserService, UserService>();

            // configure DI for application generic services
            services.AddScoped(typeof(IGenericRepository <>), typeof(GenericRepository <>));
            services.AddScoped(typeof(IGenericService <>), typeof(GenericService <>));
            services.AddScoped(typeof(IGenericController <>), typeof(GenericController <>));

            // Register the Swagger generator, defining 1 or more Swagger documents
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new Info
                {
                    Version        = "v1",
                    Title          = "Base API",
                    Description    = "Test and study API",
                    TermsOfService = "None",
                    Contact        = new Contact
                    {
                        Name  = "Adriano Faria Alves",
                        Email = "*****@*****.**",
                        Url   = "https://github.com/sistemaswebbrasil"
                    },
                    License = new License
                    {
                        Name = "The MIT License",
                        Url  = "https://opensource.org/licenses/MIT"
                    }
                });
                // 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);
            });
            services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>();

            // Change validation failure status from 400 to 422
            services.Configure <ApiBehaviorOptions>(options =>
            {
                options.InvalidModelStateResponseFactory = context =>
                {
                    var result = new UnprocessableEntityObjectResult(context.ModelState);

                    result.ContentTypes.Add("application/json");
                    result.ContentTypes.Add("application/xml");

                    return(result);
                };
            });
        }
示例#21
0
文件: Startup.cs 项目: ulfjen/SMEIoT
        // This method gets called by the runtime. Use this method to add services to the container.
        public virtual void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext(Configuration);
            services.AddOptions();
            services.AddMemoryCache();
            services.Configure <IpRateLimitOptions>(Configuration.GetSection("IpRateLimiting"));
            services.Configure <IpRateLimitPolicies>(Configuration.GetSection("IpRateLimitPolicies"));

            services.AddInfrastructureServices(_env, Configuration);
            services.AddHangfire(InfrastructureSetup.ConfigureHangfire);

            services.AddHangfireServer(options =>
            {
                options.Queues = new[] { "critical", "default" };
            });

            services.AddSingleton <IIpPolicyStore, MemoryCacheIpPolicyStore>();
            services.AddSingleton <IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
            services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>();
            services.AddSingleton <IRateLimitConfiguration, RateLimitConfiguration>();

            services.AddTransient <ProblemDetailsFactory, SMEIoTProblemDetailsFactory>();
            services.AddScoped <ISensorAssignmentService, SensorAssignmentService>();
            services.AddScoped <IUserManagementService, UserManagementService>();
            services.AddScoped <IDeviceService, DeviceService>();
            services.AddScoped <IDashboardService, DashboardService>();
            services.AddScoped <ISensorValueService, SensorValueService>();
            services.AddScoped <IMqttEntityIdentifierSuggestionService, MqttEntityIdentifierSuggestionService>();
            services.AddTransient <ISecureKeySuggestionService, SecureKeySuggestionService>();
            services.AddTransient <IServerHostAccessor, ServerHostAccessor>();

            services.AddScoped <IToggleMqttEntityStatusJob, ToggleMqttEntityStatusJob>();
            services.AddScoped <IUpdateUserLastSeenAtTimestampJob, UpdateUserLastSeenAtTimestampJob>();

            services.ConfigureMqttClient(Configuration);

            StartupConfigureIdentity.Configure <User, IdentityRole <long>, ApplicationDbContext>(services, builder => {
                services.AddScoped <ICommonPasswordValidator, CommonPasswordValidator>();
                services.AddScoped <SecurityStampValidator <User>, StrictSecurityStampValidator>();
            });

            services.AddVersionedApiExplorer(options => options.GroupNameFormat = "'v'VVV");
            services.AddApiVersioning(options =>
            {
                options.ReportApiVersions = true;
                options.ApiVersionReader  = new MediaTypeApiVersionReader();
                options.AssumeDefaultVersionWhenUnspecified = true;
                options.ApiVersionSelector = new CurrentImplementationApiVersionSelector(options);
                options.DefaultApiVersion  = new ApiVersion(new DateTime(2019, 09, 27), 1, 0);
                options.Conventions.Add(new VersionByNamespaceConvention());
            });
            services.AddScoped <LastSeenFilter>();
            services.AddControllersWithViews(options => {
                options.Filters.Add(typeof(ActionExceptionFilter));
                options.Filters.Add(typeof(LastSeenFilter));
            })
            .AddJsonOptions(options =>
            {
                options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
                options.JsonSerializerOptions.PropertyNamingPolicy        = JsonNamingPolicy.CamelCase;
                options.JsonSerializerOptions.DictionaryKeyPolicy         = JsonNamingPolicy.CamelCase;
                options.JsonSerializerOptions.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
            })
            .ConfigureApiBehaviorOptions(options =>
            {
                options.InvalidModelStateResponseFactory = context =>
                {
                    if (context.HttpContext.RequestServices == null)
                    {
                        throw new InvalidOperationException("RequestServices is null.");
                    }

                    var pdFactory = context.HttpContext.RequestServices.GetRequiredService <ProblemDetailsFactory>();

                    var result = new UnprocessableEntityObjectResult(pdFactory.CreateValidationProblemDetails(context.HttpContext, context.ModelState, StatusCodes.Status422UnprocessableEntity));

                    result.ContentTypes.Add(MediaTypeNames.Application.Json);
                    result.ContentTypes.Add(MediaTypeNames.Application.Xml);

                    return(result);
                };
            });
            services.AddRouting(options =>
            {
                options.LowercaseUrls            = true;
                options.ConstraintMap["slugify"] = typeof(SlugifyParameterTransformer);
            });
            services.AddAntiforgery(options => {
                options.HeaderName  = "X-CSRF-TOKEN";
                options.Cookie.Name = "X-CSRF-TOKEN-COOKIE";
            });

            if (_env.IsDevelopment())
            {
                services.AddSwaggerGen(c =>
                {
                    c.OperationFilter <ApiVersionOperationFilter>();
                    c.SchemaFilter <RequiredSchemaFilter>();
                    c.MapType <SensorStatus>(() => new OpenApiSchema {
                        Type = "string", Enum = new List <IOpenApiAny>(Enum.GetNames(typeof(SensorStatus)).Select(n => new OpenApiString(n)))
                    });
                    c.SwaggerDoc("v1", new OpenApiInfo {
                        Title = "SMEIoT API", Version = "v1"
                    });
                });
            }
            services.AddSignalR();
            services.AddSingleton <IMqttMessageRelayService, MqttMessageRelayService>();

            services.AddMiniProfiler(options =>
            {
                options.RouteBasePath        = "/profiler";
                options.ShouldProfile        = request => request.Path.StartsWithSegments("/api");
                options.ResultsAuthorize     = request => request.HttpContext.User.IsInRole("Admin");
                options.ResultsListAuthorize = request => request.HttpContext.User.IsInRole("Admin");
            }).AddEntityFramework();
        }
        /// <summary>
        /// Creates an <see cref="IActionResult"/>  from a <see cref="HttpResponseMessage"/>.
        /// </summary>
        /// <param name="message">The <see cref="HttpResponseMessage"/> to convert.</param>
        /// <param name="location">The location of the created resource. This location is used only when a <see cref="HttpStatusCode.Created"/> is handled.</param>
        /// <param name="authenticationSchemes">The authentication schemes to challenge. This location is used only when a <see cref="HttpStatusCode.Forbidden"/> is handled.</param>
        /// <param name="authenticationProperties"><see cref="AuthenticationProperties"/> used to perform the authentication challenge. This location is used only when a <see cref="HttpStatusCode.Forbidden"/> is handled.</param>
        /// <param name="objectResultTypeIfNotSupported">The type of the <see cref="ObjectResult"/> to convert to if the <see cref="HttpResponseMessage.StatusCode"/> of the specified <paramref name="message"/> if not managed.</param>
        /// <returns>
        /// An <see cref="IActionResult"/>:
        ///     - containing the stringified <see cref="HttpResponseMessage.Content"/> of the specified <paramref name="message"/>.<para/>
        ///     - having its <see cref="IActionResult.StatusCode"/> property set to the <see cref="HttpResponseMessage.StatusCode"/> of the specified <paramref name="message"/>.
        /// </returns>
        /// <remarks>
        /// Only the following status codes are managed:<para/>
        ///     - HttpStatusCode.BadGateway<para/>
        ///     - HttpStatusCode.BadRequest<para/>
        ///     - HttpStatusCode.Conflict<para/>
        ///     - HttpStatusCode.OK<para/>
        ///     - HttpStatusCode.NotFound<para/>
        ///     - HttpStatusCode.Unauthorized<para/>
        ///     - HttpStatusCode.Created<para/>
        ///     - HttpStatusCode.NoContent<para/>
        ///     - HttpStatusCode.Forbidden<para/>
        ///     - UnprocessableEntity (422)
        /// </remarks>
        public static async Task <IActionResult> ToActionResultAsync(this HttpResponseMessage message,
                                                                     List <string>?authenticationSchemes = null,
                                                                     Microsoft.AspNetCore.Authentication.AuthenticationProperties?authenticationProperties = null,
                                                                     Uri?location = null,
                                                                     Type?objectResultTypeIfNotSupported = null)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            var messageContent = await message.Content.ReadAsStringAsync();

            ObjectResult?resultingObjectResult;

            switch (message.StatusCode)
            {
            case HttpStatusCode.OK:
                resultingObjectResult = new OkObjectResult(messageContent);
                break;

            case HttpStatusCode.Created:
                resultingObjectResult = new CreatedResult(location, messageContent);
                break;

            case HttpStatusCode.NotFound:
                resultingObjectResult = new NotFoundObjectResult(messageContent);
                break;

            case HttpStatusCode.BadRequest:
                resultingObjectResult = new BadRequestObjectResult(messageContent);
                break;

            case HttpStatusCode.Unauthorized:
                resultingObjectResult = new UnauthorizedObjectResult(messageContent);
                break;

            case HttpStatusCode.BadGateway:
                resultingObjectResult = new BadRequestObjectResult(messageContent);
                break;

            case HttpStatusCode.Conflict:
                resultingObjectResult = new ConflictObjectResult(messageContent);
                break;

            case HttpStatusCode.NoContent:
                return(new NoContentResult());

            case HttpStatusCode.Forbidden:
                return(new ForbidResult(authenticationSchemes, authenticationProperties));

            case HttpStatusCode.InternalServerError:
                return(new StatusCodeResult((int)HttpStatusCode.InternalServerError));

            default:
                if ((int)message.StatusCode == 422)
                {
                    resultingObjectResult = new UnprocessableEntityObjectResult(messageContent);
                }
                else
                {
                    objectResultTypeIfNotSupported ??= typeof(OkObjectResult);
                    resultingObjectResult = Activator.CreateInstance(objectResultTypeIfNotSupported) as ObjectResult;

                    if (resultingObjectResult == null)
                    {
                        throw new InvalidOperationException($"Can not create an instance of the given type {objectResultTypeIfNotSupported}. Should be an {nameof(ObjectResult)}");
                    }

                    resultingObjectResult.Value = messageContent;
                }
                break;
            }

            resultingObjectResult.StatusCode = (int)message.StatusCode;

            return(resultingObjectResult);
        }