/// <summary>
        /// Writes the specified problem details object to the HTTP response stream.
        /// </summary>
        /// <param name="problemDetails">
        ///   The problem details.
        /// </param>
        /// <param name="response">
        ///   The HTTP response.
        /// </param>
        /// <param name="stream">
        ///   The destination response stream.
        /// </param>
        /// <returns>
        ///   A <see cref="Task"/> that will perform the write.
        /// </returns>
        private async Task WriteProblemDetailsToStream(ProblemDetails problemDetails, IOwinResponse response, Stream stream)
        {
            // Set response status code
            if (problemDetails.Status.HasValue)
            {
                response.StatusCode = problemDetails.Status.Value;
            }
            ;

            // Create a new buffer, and then create and serialize a problem details object
            // into the new buffer.
            using (var ms = new MemoryStream()) {
                var content = new ObjectContent(
                    problemDetails.GetType(),
                    problemDetails,
                    new JsonMediaTypeFormatter(),
                    ClientErrorDataDefaults.MediaType
                    );
                await content.CopyToAsync(ms).ConfigureAwait(false);

                // Now set the content type and content length on the response, and copy
                // the content of the new buffer into the original response stream.
                response.ContentType   = content.Headers.ContentType.ToString();
                response.ContentLength = ms.Length;
                ms.Position            = 0;
                await ms.CopyToAsync(stream).ConfigureAwait(false);
            }
        }
        private static async Task WriteResponseAsync(IWebHostEnvironment env, HttpContext context, ProblemDetails problemDetails, HttpStatusCode statusCode)
        {
            context.Response.StatusCode  = (int)statusCode;
            context.Response.ContentType = "application/problem+json";

            var options = new JsonSerializerOptions
            {
                PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
                WriteIndented        = env.IsDevelopment()
            };
            var json = JsonSerializer.Serialize(problemDetails, problemDetails.GetType(), options);
            await context.Response.WriteAsync(json);
        }
Beispiel #3
0
        public void GetProvider_ReturnsWrapper_ForProblemDetails()
        {
            // Arrange
            var providerFactory = new ProblemDetailsWrapperProviderFactory();
            var instance        = new ProblemDetails();
            var context         = new WrapperProviderContext(instance.GetType(), isSerialization: true);

            // Act
            var provider = providerFactory.GetProvider(context);

            // Assert
            var result  = provider.Wrap(instance);
            var wrapper = Assert.IsType <ProblemDetailsWrapper>(result);

            Assert.Same(instance, wrapper.ProblemDetails);
        }
Beispiel #4
0
        public void TestWrite()
        {
            JsonSerializerOptions options = new JsonSerializerOptions();

            options.SetupExtensions();

            object value = new ProblemDetails()
            {
                Status = 400
            };
            const string json = @"{""type"":null,""title"":null,""status"":400,""detail"":null,""instance"":null}";

            string result = JsonSerializer.Serialize(value, value.GetType(), options);

            Assert.Equal(json, result);
        }
        private Task WriteProblemDetails(HttpContext context, ProblemDetails details)
        {
            var routeData = context.GetRouteData() ?? _emptyRouteData;

            var actionContext = new ActionContext(context, routeData, _emptyActionDescriptor);

            var result = new ObjectResult(details)
            {
                StatusCode   = details.Status ?? context.Response.StatusCode,
                DeclaredType = details.GetType(),
            };

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

            return(_executor.ExecuteAsync(actionContext, result));
        }
        public static Task WriteProblemDetailsAsync(this HttpContext context, ProblemDetails details)
        {
            if (String.IsNullOrWhiteSpace(details.Instance))
            {
                details.Instance = context.Request.Path;
            }

            var result = new ObjectResult(details)
            {
                StatusCode   = details.Status ?? context.Response.StatusCode,
                DeclaredType = details.GetType(),
            };

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

            return(context.ExecuteResultAsync(result));
        }
Beispiel #7
0
        public void GetProvider_Returns21CompatibleWrapper_ForProblemDetails()
        {
            // Arrange
            var xmlOptions      = new MvcXmlOptions();
            var providerFactory = new ProblemDetailsWrapperProviderFactory(xmlOptions);
            var instance        = new ProblemDetails();
            var context         = new WrapperProviderContext(instance.GetType(), isSerialization: true);

            // Act
            var provider = providerFactory.GetProvider(context);

            // Assert
            var result = provider.Wrap(instance);

#pragma warning disable CS0618 // Type or member is obsolete
            var wrapper = Assert.IsType <ProblemDetails21Wrapper>(result);
#pragma warning restore CS0618 // Type or member is obsolete
            Assert.Same(instance, wrapper.ProblemDetails);
        }
        public static RequestDelegate CreateExceptionHandler(IWebHostEnvironment env)
        {
            return(async context =>
            {
                var exceptionHandlerFeature = context.Features.Get <IExceptionHandlerFeature>();

                var state = new Dictionary <string, object>();
                var logger = context.RequestServices.GetRequiredService <ILogger <ExceptionHandler> >();

                var problem = new ProblemDetails
                {
                    Status = 500,
                    Title = exceptionHandlerFeature.Error.Message,
                    Detail = env.IsDevelopment() ? exceptionHandlerFeature.Error.ToString() : null,
                    Type = exceptionHandlerFeature.Error.GetType().Name ?? string.Empty
                };

                switch (exceptionHandlerFeature.Error)
                {
                case ValidationException ve:
                    var validationProblemDetails = new ValidationProblemDetails();
                    validationProblemDetails.Status = 400;
                    validationProblemDetails.Type = ve.GetType().Name;     // or just use ValidationException constant

                    if (ve.ValidationResult is ValidationResult failure)
                    {
                        validationProblemDetails.Errors.Add(failure.MemberNames.FirstOrDefault() ?? "_", new[] { failure.ErrorMessage });

                        state.Add("ValidationErrors", JsonSerializer.Serialize(validationProblemDetails.Errors));
                    }

                    using (logger.BeginScope(state))
                    {
                        logger.LogInformation("Validation problem with status {response_status}", 400);
                    }

                    problem = validationProblemDetails;
                    break;

                case ServiceException se:
                    state.Add("ServiceException", se.InnerException?.GetType().FullName ?? string.Empty);
                    state.Add("ServiceMessage", se.InnerException?.Message ?? string.Empty);

                    using (logger.BeginScope(state))
                    {
                        logger.LogError(se, "External Service returned error");
                    }
                    break;

                default:
                    logger.LogError(exceptionHandlerFeature.Error, "Unexpected Exception");
                    break;
                }

                var traceId = Activity.Current?.TraceId.ToString() ?? context?.TraceIdentifier;
                if (traceId != null)
                {
                    problem.Extensions["traceId"] = traceId;
                }

                context !.Response.StatusCode = problem.Status ?? 500;
                context.Response.ContentType = ApplicationProblemJson;
                var stream = context.Response.Body;
                await JsonSerializer.SerializeAsync(stream, problem, problem.GetType()).ConfigureAwait(false);
            });
        }