How to properly throw and handle exceptions with web services - c#

I'm following MVC pattern in my Application server. I'm trying to throw an exception but its not been properly thrown.
Here is the code from controller:
[HttpPost]
public IHttpActionResult PostAddSuperUser(SuperUserViewModel SU)
{
try
{
//more code
blHandler.addSuperUser((SuperUser)SU.user, SU.Password);
return Ok();
}
catch (EUserAlreadyExist ex)
{
var resp = new HttpResponseMessage(HttpStatusCode.NotAcceptable);
resp.Content = new StringContent(string.Format("Already exist ", SU.user.Mail));
resp.ReasonPhrase = "Already exist";
throw new HttpResponseException(resp);
}
Then the client side calls it as follow:
try{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:50687/");
HttpResponseMessage response = await client.PostAsJsonAsync<SuperUserViewModel>("/api/SuperUser/PostAddSuperUser", SUVM);
if (response.IsSuccessStatusCode)
{
new SuccesPupUp("", "SuperUser " + SupUserName + " was added");
}
this.Close();
}
}
catch (HttpResponseException Exc)
{
new ErrorPopUp("", Exc.Message);
}
According to this this I'm throwing it correctly, but when I run it I got this error
How can I fix it?
EDIT: I want to throw the exception to the client side, so as to it could ask the user for a new email address

The problem is within this block of code (seems obvious but bear with me):
catch (EUserAlreadyExist ex)
{
var resp = new HttpResponseMessage(HttpStatusCode.NotAcceptable);
resp.Content = new StringContent(string.Format("Already exist ", SU.user.Mail));
resp.ReasonPhrase = "Already exist";
throw new HttpResponseException(resp);
}
Whats happening is that you are catching an EUserAlreadyExist exception from the above try and then throwing a new exception without an accompanying try-catch block. So this means that just because you threw an exception within a catch, it won't auto-magically catch it, you would have to have a separate try-catch within your catch
Going further with this, the client-side call to this try-catch also won't catch the thrown exception because they (the catch statements) are catching different types of exceptions than what is being thrown.
To fix it would require you catching the exception that is being thrown in this case a HttpResponseException exception. So that would mean your code might look something like this:
catch (EUserAlreadyExist ex)
{
try{
var resp = new HttpResponseMessage(HttpStatusCode.NotAcceptable);
resp.Content = new StringContent(string.Format("Already exist ", SU.user.Mail));
resp.ReasonPhrase = "Already exist";
throw new HttpResponseException(resp);
}
catch(HttpResponseException ex2)
{
//do something here with the exception
}
}

Server side code should not need to catch the exception and re-throw it - what's the point? Just let it bubble up to the client. That's the beauty and power of exceptions. The trouble is MVC wants to return a View or an HTTP Status Code, not rich, strongly typed exception information.
You appear to be using MVC pattern in a rich client (client-server) situation, which makes no sense. MVC is best suited to thin client situations whereby the server serves up views, and the client just renders them. When you have a rich client, the MVVM pattern makes more sense. Server can serve up View Models (data) and client can take over all the user interaction, views etc.
Consider using an MVVM approach (with WCF) instead of MVC. Then both client and server will have a common understanding of the exception types that can be thrown. Server can throw, client can catch, easy.
Your client code would then be as simple as:
try
{
c.AddSuperUser(SUVM);
}
catch (Exception e)
{
// etc
}
where c is the WCF client proxy.

Related

possible exceptions from IClientProxy.SendAsync (from Microsoft.AspNetCore.SignalR)

In SignalR v2, I used code like this (below) to handle exceptions that happened when my connections failed. What is the equivalent in SignalR v3? Does SendAsync or SendAsyncCore throw some exception should connections fail or serialization fail?
private async void ManagerOnUserRemoved(UserDto userDto)
{
try
{
await Context.Clients.All.MyFunc(userDto);
}
catch (InvalidOperationException) { }
catch (AggregateException) { }
}
I didn't see any exceptions listed here: https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.signalr.client.hubconnectionextensions.sendasync?view=aspnetcore-3.0
Update: I have the same question for the calls from the client-side (to InvokeCoreAsync et al).
In SignalR V3 use HubException to capture exceptions that contain sensitive information, such as connection information.
https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.signalr.hubexception?view=aspnetcore-3.1
private async void ManagerOnUserRemoved(UserDto userDto)
{
try
{
await Context.Clients.All.MyFunc(userDto);
}
catch(Exception ex) {
//Now check exceptions what you want by exception message or exception code
}
}
With this code you can handle all exceptions, or you can do this:
hubConnection.Error += ex => Console.WriteLine("Error: {0}", ex.Message);
I think it will be help

Apache Ignite thin client Exception handling

I am using Apache Ignite 2.7.5 as Server and thin client in .Net core.
When I'm doing operation related to cache put, get and load, etc .net core application automatically getting to crash.
So I want to handle exception inside for loop particular exception coming like for example IgniteCheckedException, BinaryInvalidTypeException, ClassNotFoundException, etc then throw from catch block and exit for loop otherwise continue for loop iteration if only Exception block.
public async void loadData(string configPath,List<JObject> dataList)
{
using (var ldr = _ignite.GetDataStreamer<string, Employee>(cacheName))
{
foreach (var item in parsedObjectList)
{
try
{
JObject keyObj = new JObject();
foreach (var keyName in keyArray)
{
keyObj[keyName.ToString()] = item[keyName.ToString()];
}
var serializerSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
JsonConvert.PopulateObject(item.ToString(), emp, serializerSettings);
string json = JsonConvert.SerializeObject(keyObj, Formatting.None);
string base64EncodedKey = Convert.ToBase64String(Encoding.UTF8.GetBytes(json));
await ldr.AddData(base64EncodedKey, emp);
}
catch (IgniteCheckedException ex)//how to handle here
{
throw;
}
catch (BinaryInvalidTypeException ex)//how to handle here
{
throw;
}
catch (ClassNotFoundException ex)//how to handle here
{
throw;
}
catch (Exception ex)
{
//continue for loop if data parsing ,some normal exception
Console.WriteLine(ex);
}
}
}
}
Anyone suggests me, how to achieve this one in .net core c# application.
When you catch an exception from a thin .net client, the best course of action, as with any such client, to retry attempt, if it fails again, wait for some time, close connection, open new connection, try again. If that also fails, rethrow (write to log, fail current operation).

How to differ from writing exception to a reading one?

I have a socket and I'd like to send messages and read from it.
When I read/write with the socket while the other side is offline, I get the same Exception: System.IO.IOException: Unable to read data from the transport connection: Operation on non-blocking socket would block.
How can I identify in which of the two it happened besides having two separate try-catch blocks? Can't I just get a Timeout Exception when the reading timeout is over?
example:
try
{
SendData("!GetLocation!");
string data = GetData();
}
catch (Exception ex)
{
if (ex is System.IO.IOException)
{
//How can I identify if the exception was raised at the read method or the write method?
}
}
Yeah, exception handling is heavy resource wise, but sometimes is not so bad.
If you stick to only one try-catch you can check the error message.
Note: I have also added a second try-catch for generic (non IO) errors
try
{
SendData("!GetLocation!");
string data = GetData();
}
catch (System.IO.IOException ex)
{
if (ex.Message.IndexOf("Unable to read") != -1)
{
// GetData error
}
else if (ex.Message.IndexOf("Unable to write") != -1)
{
// SendData error
}
else
{
//Other IO errors
}
}
catch(Exception exc)
{
// Unspected errors
}
you could also set a boolean variable and check its value to know where it
broke your code.
bool sendCalled = false;
try
{
SendData("!GetLocation!");
sendCalled = true;
string data = GetData();
}
catch (System.IO.IOException ex)
{
if (sendCalled)
{
// GetData error
}
else
{
// SendData error
}
}
Not that I endorse either of these solutions, but an answer is an answer: you can either
analyze the stack trace of the exception to find out which call failed (e.g. name of the method at the top of the stack frame
set a flag after the write, and do logic based on that flag
Neither of these is as straight forward as wrapping each method call. In fact, wrapping each call conveys your intent. In the catch of your first call, you can return/break/skip the read call, which explicitly tells the reader you're bailing out fast.

C# try-catching and exception and throwing the exact exception back up

I'm incorporating telemetry into my product on all service requests, unfortunately that includes exceptions. A problem I'm having is I surround my requests with a try-catch and if it's successful I log the request and if there's a catch I log the exception than throw the exception so that it still gets propagated up so that it can be debugged. A problem I'm having is that with try-catch I lose all the original data from the original exception caught by my try-catch, which I think would be nice to propagate back up.
public void someFunction(object data)
{
try
{
var response = await request(data);
LogInformation(request: data, response: response);
}
catch (Exception e)
{
throw HandleAndLogException(data, e);
}
}
private HttpResponseException HandleAndLogException(object data, Exception e)
{
LogException(data: data, response: e.Message);
var resp = new HttpResponseMessage(HttpStatusCode.BadRequest) {
Content = new StringContent(e.Message)
};
return new HttpResponseException(resp);
}
So as you can see I create a new HttpResponseException and just append the message to it, but I'd rather propagate back up the exception thrown in it's entirety.
If you want to do something clever/evil, you can use the when keyword to introduce logging without breaking the stack trace on your exception.
See when contextual keyword in the C# reference on MSDN. It's supposed to be used as a filter (the method returns true or false, indicating whether that catch block should be used) but you can do whatever you want with
I think this is what you'd want, although I haven't tested it:
public void someFunction(object data)
{
try
{
var response = await request(data);
LogInformation(request: data, response: response);
}
catch (Exception e) when (HandleAndLogException(data, e))
{
throw;
}
}
private bool HandleAndLogException(object data, Exception e)
{
LogException(data: data, response: e.Message);
return true;
}

Handling Error "WebDev.WebServer.Exe has stopped working"

Is there a way to handle the error "WebDev.WebServer.Exe has stopped working" in ASP.NET and keep the page running or even the just the WebServer running? Or is this an impossible task and is essentially like asking how to save someone's life after they've died?
I have the error-causing code inside a try/catch block, but that doesn't make a difference. I've also tried registering a new UnhandledExceptionEventHandler, but that didn't work either. My code is below in case I'm doing something wrong.
Also to be clear, I'm not asking for help on how to prevent the error; I want to know if and when the error happens if there's anything I can do to handle it.
UPDATE 1: TestOcx is a VB6 OCX that passes a reference of a string to a DLL written in Clarion.
UPDATE 2: As per #JDennis's answer, I should clarify that the catch(Exception ex) block is not being entered either. If I removed the call to the OCX from the try\catch block it still won't reach the UnhandledException method. There are essentially two areas that don't ever get executed.
UPDATE 3: From #AndrewLewis, I tried to also add a regular catch block to catch any non-CLS compliant exceptions, and this did not work either. However, I later found that since .NET 2.0 on, all non-CLS exceptions are wrapped inside RuntimeWrappedException so a catch (Exception) will catch non-CLS compliant exceptions too. Check out this other question here for more info.
public bool TestMethod()
{
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
string input = "test";
string result = "";
try
{
TestOcx myCom = new TestOcx();
result = myCom.PassString(ref input); // <== MAJOR ERROR!
// do stuff with result...
return true;
}
catch (Exception ex)
{
log.Add("Exception: " + ex.Message); // THIS NEVER GETS CALLED
return false;
}
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
// THIS NEVER GETS CALLED
try
{
Exception ex = (Exception)e.ExceptionObject;
log.Add("Exception: " + ex.Message);
}
catch (Exception exc)
{
log.Add("Fatal Non-UI Error: " + exc.Message);
}
}
You should try catching non-CLS compliant exceptions to make sure nothing is being thrown (keep in mind you don't want to do this in production, always be specific!):
try
{
TestOcx myCom = new TestOcx();
result = myCom.PassString(ref input); // <== MAJOR ERROR!
// do stuff with result...
return true;
}
catch (Exception ex)
{
log.Add("Exception: " + ex.Message); // THIS NEVER GETS CALLED
return false;
}
catch
{
//do something here
}
Your code reads //THIS NEVER GETS CALLED.
If you catch the exception it is no longer un-handled. this is why it doesn't fire an unhandledexception event.

Categories