I have avoided using
and have not closed the Stream
after reading several posts in StackOverflow but still keep getting the error:
Cannot access a closed Stream.
Here is my asp.net core
middleware I wrote to decrypt the incoming payload and override the HttpContext.Request.Body
with the decrypted string.
public class DecryptMiddleware
{
private readonly RequestDelegate _next;
private X509Certificate2 cert;
public DecryptMiddleware(RequestDelegate next)
{
cert = new X509Certificate2(@"C:\Program Files\OpenSSL-Win64\bin\SandBox\07122020\my-cert.pfx", "xxxxxxxx");
_next = next;
}
public async Task InvokeAsync(HttpContext httpContext)
{
//body => stream
var encryptedRequestData = httpContext.Request.Body;
var encryptedAttributeData = string.Empty;
var decryptedResponseData = String.Empty;
if (httpContext.Request.Method == "POST")
{
//DeSerialize
var encryptedData = string.Empty;
StreamReader stream = null;
try
{
stream = new StreamReader(encryptedRequestData);
var body = await stream.ReadToEndAsync();
var request = JsonConvert.DeserializeObject<SecureTestClass>(body);
encryptedData = request.JData;
}
finally
{
if (stream != null) //I tried avoiding this code but still keep getting the error
{
stream.Close();
stream.Dispose();
}
}
//Decrypt
var rsa = (RSACng)cert.PrivateKey;
decryptedResponseData = Encoding.UTF8.GetString(
rsa.Decrypt(Convert.FromBase64String(encryptedData)
, RSAEncryptionPadding.Pkcs1)
);
httpContext.Request.Body = GenerateStreamFromString(decryptedResponseData);
}
await _next(httpContext);
await httpContext.Request.Body.DisposeAsync();
}
public static Stream GenerateStreamFromString(string s)
{
StreamWriter sw = null;
StreamReader sr = null;
MemoryStream ms = null;
try
{
ms = new MemoryStream();
sw = new StreamWriter(ms);
sr = new StreamReader(ms);
sw.WriteLine(s);
ms.Position = 0;
}
finally
{
if (sw != null) sw.Dispose();
if (sr != null) sr.Dispose();
}
return ms;
}
}
And the Error I am getting is:
{
"Message": "Cannot access a closed Stream.",
"Exception": "System.ObjectDisposedException: Cannot access a closed Stream.\r\n at System.IO.MemoryStream.Read(Byte[] buffer, Int32 offset, Int32 count)\r\n at System.IO.MemoryStream.ReadAsync(Memory`1 buffer, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)\r\n at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)\r\n at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)\r\n at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContext bindingContext)\r\n at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value)\r\n at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)\r\n at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)\r\n at BankServiceListener.Middleware.DecryptMiddleware.InvokeAsync(HttpContext httpContext) in C:\\Projects\\GIT\\JKSB\\BankServiceListener\\BankServiceListener\\Middleware\\DecryptionMiddleware.cs:line 69\r\n at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)\r\n at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)\r\n at BankServiceListener.Middleware.DeveloperExceptionMiddleware.InvokeAsync(HttpContext httpContext) in C:\\Projects\\GIT\\JKSB\\BankServiceListener\\BankServiceListener\\Middleware\\DeveloperExceptionMiddleware.cs:line 27",
"StackTrace": " at System.IO.MemoryStream.Read(Byte[] buffer, Int32 offset, Int32 count)\r\n at System.IO.MemoryStream.ReadAsync(Memory`1 buffer, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)\r\n at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)\r\n at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)\r\n at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContext bindingContext)\r\n at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value)\r\n at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)\r\n at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)\r\n at BankServiceListener.Middleware.DecryptMiddleware.InvokeAsync(HttpContext httpContext) in C:\\Projects\\GIT\\JKSB\\BankServiceListener\\BankServiceListener\\Middleware\\DecryptionMiddleware.cs:line 69\r\n at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)\r\n at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)\r\n at BankServiceListener.Middleware.DeveloperExceptionMiddleware.InvokeAsync(HttpContext httpContext) in C:\\Projects\\GIT\\JKSB\\BankServiceListener\\BankServiceListener\\Middleware\\DeveloperExceptionMiddleware.cs:line 27",
"Source": "System.Private.CoreLib"
}
Am I doing something wrong here? Can't figure it out.
seems you are disposing the StreamWriter sw, which in turn will dispose the memory stream passed to it
try using this
public static Stream GenerateStreamFromString(string s)
{
var ms = new MemoryStream(Encoding.Default.GetBytes(s));
return ms;
}