Properties of Inner Exception are Disposed? - c#

I am writing a unit test for a WCF web service. I am deliberately sending an invalid request to the server which throws a WebExceptionFault<string>. In the unit test, the Exception that gets caught is an EndpointNotFoundException with the standard WebException in the InnerException property. I want to verify the body of the response matches the string that I think should be there.
I am coming accross a problem, however, as the Response property of the WebException (which is a System.Net.SyncMemoryStream) is Disposed and can not be read.
My code:
Clubs actual;
try
{
//"201" is an invalid argument for the first parameter
actual = new Clubs(channel.GetClubs("201", "123"));
}
catch (EndpointNotFoundException e)
{
WebException w = e.InnerException as WebException;
Assert.IsNotNull(w);
HttpWebResponse resp = w.Response as HttpWebResponse;
Assert.IsNotNull(resp);
Assert.AreEqual(resp.StatusCode, HttpStatusCode.NotFound);
//Next line throws an ArgumentException saying Stream not readable
//Investigation shows it has been disposed
using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
Assert.AreEqual(sr.ReadToEnd(), "League not allowed for selected club");
}
Is it normal that the properties of the InnerException are disposed? Is there any way around this?

Seems a Exception serialization issue. You might have to trap the error on server and custom build a error message
How to serialize an Exception object in C#?

Related

How to get JSON body from the stream in C# efficiently?

I am using Utf8 json library to deserialize my JSON using DeserializeAsync method of JsonSerializer class. And sometimes I am seeing it is throwing exception as -
Arithmetic operation resulted in an overflow.
So it looks like my JSON data has a value that's too large to fit in one of our object's properties causing this overflow exception. Below is the code I got where I am trying to print the json which is bad and causing this Arithmetic Overflow error but it's not logging that JSON whenever this exception happens.
using (var content = httpResponseMessage.Content)
{
if (content == null) return (default(T), statusCode);
using (var responseStream = await httpResponseMessage.Content.ReadAsStreamAsync())
{
try
{
deserializedValue = await JsonSerializer.DeserializeAsync<T>(responseStream, formatResolver);
}
catch (Exception ex)
{
var bodyString = (ex as JsonParsingException)?.GetUnderlyingByteArrayUnsafe();
var error = (bodyString != null) ? $"Bad json: {Encoding.UTF8.GetString(bodyString)}" : "Cannot Deserialize JSON";
logger.logError(error, ex.Message, "Deserialization Exception", ex.StackTrace, (int)statusCode);
return (default(T), HttpStatusCode.BadRequest);
}
}
}
For some reason bodyString is coming as null whenever this exception happens and that's why my condition is not getting evaluated to get the JSON body. My understanding was that it will throw JsonParsingException but looks like it is throwing some other exception.
Is there any way to get JSON body whenever this exception happens? or maybe write this in a better way to get JSON whenever this exception happens efficiently?
You wrote that you got an "Arithmetic Overflow" error, so the actual type of exception in the catch is probably OverflowException, not JsonParsingException
I think you should get bodyString from responseStream. You can reset the stream with responseStream.Position = 0 and read the body as a byte array from it.

How to handle specific HttpClient errors

When the HttpClient throws an exception trying to get a page it returns a HttpRequestException. This exception doesn't really have anything to categorize the error apart from the message so the only way i can see to handle errors is like so:
try
{
HttpResponseMessage response = await client.GetAsync("http://www.example.com/");
// ...
}
catch (HttpRequestException e)
{
if(e.Message == "Name or service not known")
{
HandleNotKnown();
return;
}
if(e.Message == "Some other specific message")
{
HandleOtherError();
return;
}
// ... etc
}
I don't like doing this because I feel like at some point the error text could change in an update and break my code.
Is there a better way to handle specific errors with HttpClient?
The HttpRequestException inherits from Exception and so it has the InnerException property
Gets the Exception instance that caused the current exception.
So check this Exception for more details.

Exception not handled in Grpc server when reading from a stream

I made a simple app where chunks of a file are streamed from client to server. Server-side I have handled exceptions such that a response of my own is returned to the client. When I throw an exception before reading from the stream has been completed, however, even though it gets caught and a custom response is returned, client-side I still get an unhandled RpcException with status Cancelled.
public override async Task<UploadFileResponse> UploadFile(
IAsyncStreamReader<UploadFileRequest> requestStream,
ServerCallContext context)
{
try
{
bool moveNext = await requestStream.MoveNext();
using (var stream = System.IO.File.Create($"foo.txt"))
{
while (moveNext)
{
// If something goes wrong here, before the stream has been fully read, an RpcException
// of status Cancelled is caught in the client instead of receiving an UploadFileResponse of
// type 'Failed'. Despite the fact that we catch it in the server and return a Failed response.
await stream.WriteAsync(requestStream.Current.Data.ToByteArray());
moveNext = await requestStream.MoveNext();
throw new Exception();
}
// If something goes wrong here, when the stream has been fully read, we catch it and successfully return
// a response of our own instead of an RpcException.
// throw new Exception();
}
return new UploadFileResponse()
{
StatusCode = UploadStatusCode.Ok
};
}
catch (Exception ex)
{
return new UploadFileResponse()
{
Message = ex.Message,
StatusCode = UploadStatusCode.Failed
};
}
}
Perhaps the way I approach implementing this operation is wrong. I can see why the server would return a Cancelled RPC exception because we indeed cancel the call before the stream has been fully read but I don't understand why it overrides the custom response. It might be that handling both would have to be done client-side - a failed response and a potential RPC exception.
I found some materials on the topic - Server and Client.
Apparently it is common to throw RpcExceptions whenever there should be an invalid response as also shown in the official gRPC Github repository here.

How to properly catch exceptions from C#'s HttpClient getAsync so the error says more than "One or more errors occurred"?

The following is some code that downloads a file using System.Net.Http.HttpClient
try
{
var responseResult = new System.Net.Http.HttpClient().GetAsync(fileUrl);
using (var memStream = responseResult.Result.Content.ReadAsStreamAsync().Result)
{
using (var fileStream = File.Create(saveToPath))
{
memStream.CopyTo(fileStream);
}
}
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
}
Sometimes I call this and a file fails to download. In that situation, the catch is called but doesn't contain any information of the issue:
One or more errors occurred.
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
at System.Threading.Tasks.Task`1.get_Result()
at SpPrefetchIndexBuilder.FileDownloader.StartDownloads(Int32 timeout)
How can I get it to the cause of this exception?
Task.Result throws AggregateException, so you can catch that. All exceptions will be inside InnerExceptions property of that exception (there can be multiple in theory, but in your case there will be just one). First of those exceptions (or the only one if there is just one) is also in InnerException property.
If you don't want to dig inside AggregateException, use .GetAwaiter().GetResult() instead of .Result - this will not wrap exception into AggregateException and will throw it as is.
Since you're calling .Result on the task, original exception will be held in InnerException property of catched exception. You could access it with following construct:
string message = e?.InnerException.Message ?? e.Message;
Not really sure if this applies but have you tried?: Console.WriteLine(ex.GetBaseException().ToString().StackTrace)

.NET exception doesn't get passed from class to main program

I created a simple console application using C#. It creates an instance of a class and calls one of the class' methods. This method contains a try-catch block to catch exceptions of the type System.Net.WebException and rethrow it so that the main method can catch it and act appropriately. When I execute the compiled application the exception does not get passed to the main class and the user would never see my custom error message. Instead this screen pops up telling me that there was an unhandled WebException (it's in German but I think it can be recognized anyway ;-)):
alt text http://img29.imageshack.us/img29/4581/crapq.png
This is the method inside my class named BuffaloRouter:
public void Login()
{
string sUrl = _sUrl + "/somestuff.htm";
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(sUrl);
CredentialCache credCache = new CredentialCache();
credCache.Add(new Uri(sUrl), "Basic", _credential);
request.Credentials = credCache;
try
{
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream receiveStream = response.GetResponseStream();
StreamReader reader = new StreamReader(receiveStream, Encoding.UTF8);
_sContent = reader.ReadToEnd();
response.Close();
receiveStream.Dispose();
reader.Dispose();
_parseSessionIds();
}
catch (WebException)
{
throw;
}
}
And this is the method inside my main class:
private static bool _login()
{
_router = new BuffaloRouter(_sIP, new System.Net.NetworkCredential("root", _sPassword));
try
{
Console.WriteLine("Login...");
_router.Login();
return true;
}
catch (System.Net.WebException)
{
_showErrorMessage("Could not connect to " + _sIP);
return false;
}
}
UPDATE:
I feel more than a little embarrassed and would rather not talk about it. But like a few times before I didn't relly look at what I was doing ;-)
The method inside the main class was not even invoked when I was running the app. The one that was invoked didn't have a try-catch block so that the exception thrown inside my class' method made the app do what it was supposed to, i.e. CRASH!!
I'm stupid, sorry for wasting everone's time.
If all you're doing is rethrowing the exception, then you don't need to catch it in the first place. Just remove the try...catch from your Login method.
Having done that temporarily edit your code to catch the general exception and debug it to find out what exception is actually being raised. Having done that edit the code again to catch that exception (and that exception alone).
As ChrisF has indicated you don't need to rethrow the error in the Login method. If your catch block is not running in the _login method, then I would guess your not catching the right exception.
Are you positive your getting a System.Net.WebException

Categories

Resources