I need to know how to catch and recognize timeout error in comparison to other WebException errors. Request timeout is set to "1" to make environment to be able to catch the exception. I just need to know how to recognize it. (i.e. default working value = 60000). Here is my code:
// some code here
request.Timeout = 1;
// some code here
catch (WebException wex)
{
Console.WriteLine(wex);
try
{
response_code = ((int)((HttpWebResponse)wex.Response).StatusCode);
State_show.ForeColor = System.Drawing.Color.Red;
if (response_code == 404)
{
State_show.Text = "Error 404. Retrying the request";
request_1();
}
if (response_code != 400 || response_code != 503 || response_code != 404)
{
State_show.Text = "Error " + response_code + ". Please try again";
FlashWindow.Flash(this);
}
}
catch (Exception exc)
{
Console.WriteLine(exc);
MessageBox.Show("Check internet connection");
}
}
So it catches good if I received bad http status code. But it throws additional exception if response has timed out. The simplest way is to get
string wex_modified = wex.ToString();
If (wex_modified.contains("Timeout"))
{
// some handling here
}
But I don't really like it. I tried to use wex.GetType() and other available functions, but without success.
Is there any other way to recognize the exception?
The WebException.Status property returns a WebExceptionStatus enum. One of the enumeration values is Timeout.
if (wex.Status == WebExceptionStatus.Timeout)
{
// We have a timeout!
}
Related
I'm trying to show a Duplicate Record error message in an WebAPI service. I'm using .net5 and mysql. I cannot seem to find a way to pull the duplicateEntry message from the exception response. I'd like to key in on the ErrorCode field and use this to tailor a response to the user. I can see the Message property, but cannot figure out how to access the innerException.
{
try
{
module.Id = Guid.NewGuid();
await _moduleRepository.Add(module);
await _uow.CompleteAsync();
return true;
}
catch (DbUpdateException ex)
{
logger.LogWarning("Module - Add Error: " + ex.Message);
return false;
}
}
You may try to catch an Exception object which has a InnerException attribute. Also, you may also check DbEntityValidationException class.
Reference: link
Found something that worked. Made a helper function, but this is highly coupled to Mysql. Had to check the InnerException to see if it was of type MsyqlException.
{
public static string GetExceptionMessage(Exception ex)
{
var message = ex.Message;
var innerException = ex.InnerException;
if (innerException != null && (innerException.GetType() == typeof(MySqlException)))
{
var dbException = (MySqlException)innerException;
if(dbException.ErrorCode == MySqlErrorCode.DuplicateKeyEntry)
{
return ErrorMessages.RecordExists;
} else
{
return ErrorMessages.UnknownError;
}
}
return message;
}
}
My app produces the following error randomly. I havent been able to re-produce it on my machine, but on users who have installed it, it happens to them.
System.Net.WebException: The request was aborted: The request was canceled.
at System.Net.ConnectStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.IO.StreamReader.ReadBuffer()
at System.IO.StreamReader.ReadToEnd()
Whats odd is, ReadToEnd() cant product a WebException error (Found out by hovering over it and seeing what type of exceptions it can cause), yet from this Crash Dump it is?, To make sure I even put a WebException try catch and it still happens.
I read online a tiny bit and see it might be caused by ServicePointManager.DefaultConnectionLimit so I added that in with 1000 int value, and now im not sure if it fixed it - I havent seen any reports, but that doesnt mean its not happening.
using (HttpWebResponse resp = (HttpWebResponse)r.GetResponse())
using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
string s = "";
try { s = sr.ReadToEnd(); }
catch (IOException) { return "2"; }
catch (WebException) { return "2"; }
}
This is the code im using, if needed, I can provide r's values. Just know that I use quite a lot.
EDIT: I can confirm on the client's side that even with the ServicePointManager.DefaultConnectionLimit set to 1000 it still occurs.
I had a similar problem to this some time ago. Can you handle the WexException doing something like this:
public static HttpWebResponse GetHttpResponse(this HttpWebRequest request)
{
try
{
return (HttpWebResponse) request.GetResponse();
}
catch (WebException ex)
{
if(ex.Response == null || ex.Status != WebExceptionStatus.ProtocolError)
throw;
return (HttpWebResponse)ex.Response;
}
}
I borrowed the code above from the answerer here: HttpWebRequest.GetResponse throws WebException on HTTP 304
Then the first line of your code would do this:
using (HttpWebResponse resp = GetHttpResponse(r))
Found out what managed to fix it, no idea WHY, but this works:
try
{
using (HttpWebResponse resp = httpparse.response(r))
{
if(resp != null)
{
using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
string s = "";
try { s = sr.ReadToEnd(); }
catch (IOException) { return "2"; }
}
} else
{
return "2";
}
}
}
catch (WebException)
{
return "2";
}
Makes no sense, the error occurs at sr.ReadToEnd(), yet putting the Try Catch over the response() makes it fixed?
We have an image upload page that will timeout if the user's upload is taking longer than 15 minutes.
We're catching the HttpException that occurs with a timeout. But how can we know that the exception occurred because of a timeout, so we can return a specific message?
Our code:
try
{
// do stuff here
}
catch (HttpException ex)
{
// What can we check to know if this is a timeout exception?
// if (ex == TimeOutError)
// {
// return "Took too long. Please upload a smaller image.";
// }
return "Error with image. Try again.";
}
catch (Exception ex)
{
return "Error with image. Try again.";
}
And what the timeout error looks like:
System.Web.HttpException (0x80004005): Request timed out.
at System.Web.HttpRequest.GetEntireRawContent()
at System.Web.HttpRequest.GetMultipartContent()
at System.Web.HttpRequest.FillInFormCollection()
at System.Web.HttpRequest.EnsureForm()
at System.Web.HttpRequest.get_Form()
at MyStore.upload.ProcessRequest(HttpContext context)
ex.ErrorCode=-2147467259
ex.GetHttpCode=500
ex.WebEventCode=0
I'm hesitant to simply do an if statement that compares the error codes above.
HttpCode 500 seems to be a generic Internal Server Error code that could happen for more than just a timeout exception.
ErrorCode -2147467259 is something I'm unfamiliar with. If that number will remain constant for timeout errors, and will never occur with non-timeout exceptions, then I could do an if comparison on this number.
I'm thinking there has to be a simple way to know if the HttpException is a timeout exception, ala something like:
if (ex == TimeoutError) // what should this be?
UPDATE:
I just now tried catching TimeoutException, like the following, but it still is only caught by the HttpException.
try
{
// do stuff here
}
catch (TimeoutException ex)
{
// Timeout doesn't get caught. Must be a different type of timeout.
// So far, timeout is only caught by HttpException.
return "Took too long. Please upload a smaller image.";
}
catch (HttpException ex)
{
// What can we check to know if this is a timeout exception?
// if (ex == TimeOutError)
// {
// return "Took too long. Please upload a smaller image.";
// }
return "Error with image. Try again.";
}
catch (Exception ex)
{
return "Error with image. Try again.";
}
You can catch a couple timeout conditions with:
bool IsTimeout(HttpException httpex)
{
switch ((HttpStatusCode)httpex.GetHttpCode())
{
case HttpStatusCode.RequestTimeout: //408
case HttpStatusCode.GatewayTimeout: //504
return true;
default: return false;
}
}
You need to use
ex.getType() is subClassException
As TimeoutException is a subclass. That would be how to catch that type of execption if it was a possible throw...
Although, httpexpection will always be thrown even if it did time out (refer https://msdn.microsoft.com/en-us/library/system.web.httprequest(v=vs.110).aspx from what each method throws). So you need to do something like,
if(e.Message.Contains("timed out"))
//Do something because it timed out
I am trying to simplify error handling in my client application which consumes a ServiceStack REST service using the JsonServiceClient.
My custom exceptions that I throw on the server are serialised in the ResponseStatus object, and I can see a WebServiceException is thrown.
But at the moment I am having to check for my exception types, by matching the WebServiceException ErrorCode to the type name of my exception class. (Which is exposed in the shared DTO class):
/** Current Method **/
try {
client.Get(new RequestThatWillFail());
} catch(WebServiceException ex) {
if(ex.ErrorCode == typeof(ValidationFailedException).Name)
Console.WriteLine("Validation error");
else if(ex.ErrorCode == typeof(UnauthorizedException).Name)
Console.WriteLine("Not logged in");
else if(ex.ErrorCode == typeof(ForbiddenException).Name)
Console.WriteLine("You're not allowed to do that!");
else
throw; // Unexpected exception
}
Ideally I was hoping that JsonServiceClient would contain some helper method or overridable conversion function that would allow me to translate the WebServiceException to my known exception type; So that I could use my try ... catch in a more traditional way:
/** Ideal Method **/
try {
client.Get(new RequestThatWillFail());
} catch(ValidationFailedException ex) { // (WebServiceException is converted)
Console.WriteLine("Validation error");
} catch(UnauthorizedException ex) {
Console.WriteLine("Not logged in");
} catch(ForbiddenException ex) {
Console.WriteLine("You're not allowed to do that!");
}
Update (for clarification)
I have exceptions working, I can debug, and get all the information I need to.
But I would like to ultimately be able to catch my own exception instead of the generic WebServiceException
I am not looking to extend additional properties on the exception, it's ultimately a convenience of not having to do lots of typeof(MyException).Name == ex.ErrorCode within the catch.
I would envisage being able to provide JsonServiceClient with a map of:
{ Type typeof(Exception), string ErrorCode }
i.e. Something like
JsonServiceClient.MapExceptionToErrorCode = {
{ typeof(BadRequestException), "BadRequestException" },
{ typeof(ValidationFailedException), "ValidationFailedException" },
{ typeof(UnauthorizedException), "UnauthorizedException" },
{ typeof(AnotherException), "AnotherException" }
// ...
}
Similar to how the server currently maps exceptions to Http status codes.
Then the ThrowWebServiceException<TResponse> and the HandleResponseError<TResponse> within the JsonServiceClient could look the ErrorCode up in the map and if it matches, return a new Exception of that type, passing the WebServiceException as a parameter, or alternatively Translate the properties.
But with the ultimate goal of throwing a more useable error. If there wasn't a match, go ahead and continue throwing the WebServiceException.
I'd override ThrowWebServiceException<TResponse> and the HandleResponseError<TResponse> but I don't think this is possible. And I don't wan't to build my own version to provide this functionality.
I hope I have explained this OK.
My approach for exception handling is to do in service side what is described in the Structured Error Handling and Overriding the default Exception handling
I use my ServiceRunner and I override the HandleException.
If my API exception is thrown then I create a custom response.
public override object HandleException(IRequestContext requestContext,T request,
Exception ex)
{
APIException apiex = ex as APIException; // custo application exception
if (apiex != null)
{
ResponseStatus rs = new ResponseStatus("APIException", apiex.message);
rs.Errors = new List<ResponseError>();
rs.Errors.Add(new ResponseError());
rs.Errors[0].ErrorCode = apiex.errorCode.ToString();
rs.Errors[0].FieldName = requestContext.PathInfo;
rs.Errors[1].ErrorCode = apiex.detailCode.ToString();
// create an ErrorResponse with the ResponseStatus as parameter
var errorResponse = DtoUtils.CreateErrorResponse(request, ex, rs);
Log.Error("your_message", ex); // log only the the error
return errorResponse;
}
else
return base.HandleException(requestContext, request, ex);
}
UPDATE :
In client side, I create an wrapper for the service call and in WebServiceException,
I check the ResponseStatus.Errors. In case of my error code, then I rethrow my exception.
T ServiceCall<T>(string command, string rest_uri, object request)
{
try
{
if (command == "POST")
return client.Post<T>(serverIP+rest_uri, request);
}
catch (WebServiceException err)
{
if (err.ErrorCode == "APIException" && err.ResponseStatus.Errors != null
&& err.ResponseStatus.Errors.Count > 0)
{
string error_code = err.ResponseStatus.Errors[0].ErrorCode;
string path_info = err.ResponseStatus.Errors[0].FieldName;
string detail_error = err.ResponseStatus.Errors[1].ErrorCode;
throw new APIException(error_code,detail_error,path_info);
}
} finally {}
}
I'm using this code, to fetch the latest version of my app in *Form1_Load*:
string result1 = null;
string url1 = "http://site.com/version.html";
WebResponse response1 = null;
StreamReader reader1 = null;
try
{
HttpWebRequest request1 = (HttpWebRequest)WebRequest.Create(url1);
request1.Method = "GET";
response1 = request1.GetResponse();
reader1 = new StreamReader(response1.GetResponseStream(), Encoding.UTF8);
result1 = reader1.ReadToEnd();
}
catch (Exception ex)
{
// show the error if any.
}
finally
{
if (reader1 != null)
reader1.Close();
if (response1 != null)
response1.Close();
}
The problem is that when I shut the server down the whole application is stucking and a window is popping out,saying:
Unable to connect to the remote server
Which seems legit.
Is there a way to bypass this crash (when the server is down) and break out of the version checking?
Add an additional catch block that catches the specific Exception type that you're seeing... the code will look like...
try
{
//*yadda yadda yadda*
}
catch (System.Net.WebException WebEx)
{
//*Correctly set up a situation where the rest of your program will know there was a connection problem to the website.*
}
catch (Exception ex)
{
//*Do the error catching you do now*
}
finally
{
//*yadda yadda*
}
This construction will allow you to handle WebExceptions differently from other kinds of exceptions: note that all Exceptions derive from one base class, Exception, and you can make your own for uses like this.