System.ArgumentException HResult=0x80070057 Message=Stream is now writable Parameter name: stream

2

I have asp.net core 2 web api endpoint along with custom middleware. In order to accomplish the centralized exception handling and request validation for the project I referred the link: https://www.strathweb.com/2018/07/centralized-exception-handling-and-request-validation-in-asp-net-core/

Based on the reference I implemented the following code :

// Startup

public class Startup
{
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }

        app.UseGraphiQl();
        app.UseHttpsRedirection();
        app.UseExceptionHandler(errorApp =>
        {
            errorApp.Run(async context =>
            {
                var errorFeature = context.Features.Get<IExceptionHandlerFeature>();
                var exception = errorFeature.Error;
                // the IsTrusted() extension method doesn't exist and
                // you should implement your own as you may want to interpret it differently
                // i.e. based on the current principal
                var problemDetails = new ProblemDetails{Instance = $"urn:myorganization:error:{Guid.NewGuid()}"};
                if (exception is BadHttpRequestException badHttpRequestException)
                {
                    problemDetails.Title = "Invalid request";
                    problemDetails.Status = (int)typeof (BadHttpRequestException).GetProperty("StatusCode", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(badHttpRequestException);
                    problemDetails.Detail = badHttpRequestException.Message;
                }
                else
                {
                    problemDetails.Title = "An unexpected error occurred!";
                    problemDetails.Status = 500;
                    problemDetails.Detail = "Testing"; //exception.Demystify().ToString();
                }

                // log the exception etc..
                context.Response.StatusCode = problemDetails.Status.Value;
                context.Response.WriteJson(problemDetails, "application/problem+json");
            }

            );
        }

        );
        app.UseCommonResponser();
        app.UseMvc();
    }
}
// CommonResponseMiddleware

public class CommonResponseMiddleware
{
    private readonly RequestDelegate _next;
    private ICommonService _commonService;
    public CommonResponseMiddleware(RequestDelegate next, ICommonService commonService)
    {
        _next = next;
        _commonService = commonService;
    }

    public async Task Invoke(HttpContext context)
    {
        var currentBody = context.Response.Body;
        using (var memoryStream = new MemoryStream())
        {
            context.Response.Body = memoryStream;
            await _next.Invoke(context);
            context.Response.Body = currentBody;
            memoryStream.Seek(0, SeekOrigin.Begin);
            var readToEnd = new StreamReader(memoryStream).ReadToEnd();
        }
    }
} 

   // GraphQLController

[Route("[controller]")]
[ApiController]
public class GraphQLController : Controller
{
    private readonly IDocumentExecuter _documentExecuter;
    private readonly ISchema _schema;
    public GraphQLController(ISchema schema, IDocumentExecuter documentExecuter)
    {
        _schema = schema;
        _documentExecuter = documentExecuter;
    }

    [HttpPost]
    public async Task<IActionResult> Post([FromBody] GraphQLQuery query)
    {
        if (query == null)
        {
            throw new ArgumentNullException(nameof(query));
        }

        var inputs = query.Variables.ToInputs();
        var executionOptions = new ExecutionOptions{Schema = _schema, Query = query.Query, Inputs = inputs, UserContext = Request.Headers, //UserContext = new GraphQLUserContext { Headers = Request.Headers }
        };
        throw new Exception("Exception while fetching all the students from the storage.");
        var result = await _documentExecuter.ExecuteAsync(executionOptions).ConfigureAwait(false);
        if (result.Errors?.Count > 0)
        {
            return BadRequest(result);
        }

        return Ok(result);
    }
}

// HttpExtensions

public static class HttpExtensions
{
    private static readonly JsonSerializer Serializer = new JsonSerializer{NullValueHandling = NullValueHandling.Ignore};
    public static void WriteJson<T>(this HttpResponse response, T obj, string contentType = null)
    {
        response.ContentType = contentType ?? "application/json";
        using (var writer = new HttpResponseStreamWriter(response.Body, Encoding.UTF8))
        {
            using (var jsonWriter = new JsonTextWriter(writer))
            {
                jsonWriter.CloseOutput = false;
                jsonWriter.AutoCompleteOnClose = false;
                Serializer.Serialize(jsonWriter, obj);
            }
        }
    }
}

Now on invoking the graphqlcontroller endpoint, I am intentionally throwing an error which I am trying to catch in the global exception logic where I am trying to customize it before passing it to the customer.

I am getting an exception: Stream is now writable Parameter name: stream, while processing it in the HttpExtensions class at the below line:

using (var writer = new HttpResponseStreamWriter(response.Body, Encoding.UTF8))

Can anyone help me to fix this issue?

c#
asp.net-core-2.1

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0