If someone doesn't have a profile picture, a NotFound exception kicks me out of the code. How can I work around this?
My Method:
if(graphManager.Client.Users[user.Id].Photo.Content.Request().GetAsync().IsNull())
{
Debug.Log("profilepicture not found");
}
else
{
var photo = await graphManager.Client.Users[mitarbeiter.Id].Photo.Content.Request().GetAsync();`
}
Response: It skips the if cause it thinks it's not null
What I need is a Method to create a Debug.Log if the exception happens and not throw me out
It seems that getting an exception when a photo is not found is a valid case. See docs on errors.
Try to handle it in the following way:
try
{
Stream photoContent = await graphManager.Client.Users[user.Id].Photo.Content.Request().GetAsync();
}
catch (ServiceException ex) when (ex.IsMatch(GraphErrorCode.ItemNotFound.ToString()))
{
Debug.Log("profilepicture not found");
}
P.S. I'm not sure precisely which GraphErrorCode should be used here.
I don't know the library you are using but is it possible that in the moment you do
graphManager.Client.Users[user.Id].Photo.Content.Request().GetAsync().IsNull()
what happens is you are basically doing
var asyncResult = graphManager.Client.Users[user.Id].Photo.Content.Request().GetAsync();
if(asyncResult.IsNull())
which of course would be true since you didn't give it any time to actually perform the request and finish.
It should probably rather be
var photo = await graphManager.Client.Users[mitarbeiter.Id].Photo.Content.Request().GetAsync();
if(photo.IsNull() )
{
Debug.Log("profilepicture not found");
}
else
{
...
}
Related
So I've been searching like a mad man after a way to solve this issue, but I can't seem to find an answer.
So, I need to send a POST request with HTTPClient in C# to a server, and if the server isn't running it will keep sending the request until it connects (or dies after a nr of attempts). But I always get the exception System.Net.Http.HttpRequestException, which wouldn't be a problem if I just could store it (or something) and try again.
I found a couple of ways that people tried to do this, and I've tried them all. Creating a for-loop that loops and catches the exception that the program throws, adds to the counter and tries again. Creating a while-loop that loops until the HttpResponseMessage.IsSuccessStatusCode == true. I've even gone to such lengts as restarting the program if it can't connect (yeah, I'm that desperate).
So, I had to see if anyone of you guys might have a solution to this problem, or if you maybe had a better way to solve this problem.
Here is the code im running, thanks for your help!
EDIT: Just to add some clarity, the exception is thrown at the "rep"-variable, and the code never runs further than to that variable. And I've tried to make the HTTPResponseMessage variable just a "var" and await the Postasync method to.
HttpResponseMessage rep = new HttpResponseMessage();
try
{
rep = client.PostAsync("https://localhost:9999/", content).Result;
}
catch (Exception e)
{
}
Task t1 = Task.Factory.StartNew(() => ContinueTrasmission(client, c1.name, c1.state));
You have to look for retry libraries, for example Polly
var policy = Policy
.Handle<HttpRequestException>()
.WaitAndRetry(_retryCount, retryAttempt =>
TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
policy.Execute(() => DoSomething());
A solution could be:
bool success = false;
while (!success)
{
var rep = new HttpResponseMessage();
try
{
rep = client.PostAsync("https://localhost:9999/", content).Result;
//No exception here. Check your condition and set success = true if satisfied.
}
catch (Exception e)
{
//Log your exception if needed
}
}
I've encountered a few dificulties trying to handle some errors in the best way possible. One of my cases for example is NullReferenceException.
To be more clear let me explain it in a few words. When I make a call to a server to receive some pieces of information, in some cases the server might have some problems and it will return of course null.
What I've done is I display an alert to let the user know that he can try later again. After this I try to send him in the previous page for example. And after all this my app still crushes.
What I'd like to do is to simply display the alert and then let the user stay in the same page without the application crushing.
These are a few pieces of my code:
tasks.cs
public async Task<List<Idea>> GetIdeaAsync(string accesToken)
{
List<Idea> ideas = null;
try
{
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accesToken);
var json = await client.GetStringAsync("http://www.getdata.de/api/ideas/");
var ideas = JsonConvert.DeserializeObject<List<Idea>>(json);
}
catch (Exception ex)
{
await Application.Current.MainPage.DisplayAlert("Server Error", "There has been an server error. Please try later.", "OK");
if (ideas == null)
{
await Application.Current.MainPage.Navigation.PopAsync(); //actually I would like to stay in the same page
}
}
return ideas;
}
view.xaml.cs
private async void Button_Clicked(object sender, EventArgs e)
{
Tasks ts = new Tasks();
var ideas = await ts.GetIdeasAsync();
if (ideas == null)
{
Debug.WriteLine("hello");
//do nothing since the display alert is already shown
}
else
{
//code here
}
I would really appreciate if anyone can guide me to a "best-practice" approach. Thanks :)
You are declaring ideas in the try block, and then trying to access it in the catch block, where it is out of scope. (Visual Studio should give an Intellisense error)
Also, whenever manipulating the UI, you should always do it on the main thread. so move your DisplayAlert() code into
Device.BeginInvokeOnMainThread(async () =>
{
// await DisplayAlert(); move it into here
});
In addition, any PopAsync or PushAsync calls should also be done on the main UI thread. But calling PopAsync after an asynchronous call to an API not be a good idea, as the user may have already pressed the back button by the time the call returns.
As for the NullReferenceException, check to see if json is null before passing it to the DeserializeObject() function.
The problem it was pretty obvious actually since I after catch-ing the exception I would later continue with the code. So what I did was :
public async Task<List<Idea>> GetIdeaAsync(string accesToken)
{
List<Idea> ideas = null;
try
{
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accesToken);
var json = await client.GetStringAsync("http://www.getdata.de/api/ideas/");
var ideas = JsonConvert.DeserializeObject<List<Idea>>(json);
}
catch (Exception ex)
{
await Application.Current.MainPage.DisplayAlert("Server Error", "There has been an server error. Please try later.", "OK");
if (ideas == null)
{
//actually I would like to stay in the same page
return null; //-- added this line
}
}
return ideas;
}
Maybe it's not the best idea but it's working for me. Any other approach would be highly appreciated. :)
When using the Google Firebase Authentication plugin in Unity, how do you read error codes of faulted requests?
For example, within this code:
auth.SignInWithEmailAndPasswordAsync(email, password).ContinueWith(task => {
if(task.IsFaulted){
Debug.Log("ERROR ENCOUNTERED: " + task.Exception);
return;
}
if(task.IsCompleted){
// Success!
}
});
You can see that if an error occurs I can log the exception out, which prints the following:
ERROR ENCOUNTERED: System.AggregateException: Exception of type 'System.AggregateException' was thrown.
Firebase.FirebaseException: There is no user record corresponding to this identifier. The user may have been deleted.
That's very human-readable, but not very elegant to put into a switch statement. Is there any way for me to cast the task.Exception to be a FirebaseException so I can grab the error code? And is there a list of these error codes somewhere? I can find the documentation for the FirebaseException, but the error codes aren't there. Thanks for the help!
Edit:
So while I am still hoping for an answer, I've come to think that Google expects developers to use blanket error statements based on the context of the request. For example, when failing to sign in with an email and password (as in the above code), we should use the common statement of "Email or password is incorrect." The problem with that is that I can't let the user know the difference between them providing the incorrect details versus them entering an email which doesn't have an account associated with it at all.
Hopefully you've solved this by now but I've just come across the exact same problem and I'll share my solution:
According to MSDN, System.AggregateException is a representation of one or more errors that may occur during the task execution.
Therefore, you'll need to loop through the InnerException(s) presented by the AggregateException, and look for the suspected FirebaseException:
Retrieving the FirebaseException:
AggregateException ex = task.Exception as AggregateException;
if (ex != null) {
Firebase.FirebaseException fbEx = null;
foreach (Exception e in ex.InnerExceptions) {
fbEx = e as Firebase.FirebaseException;
if (fbEx != null)
break;
}
if (fbEx != null) {
Debug.LogError("Encountered a FirebaseException:" + fbEx.Message);
}
}
Getting the Error Code:
Wish I could help here but I haven't found anything - these aren't documented within the official API, AFIK. The only reference states: "If the error code is 0, the error is with the Task itself, and not the API. See the exception message for more detail."
I encountered the same dilemma trying to find out which error code I get from Firebase and display appropriate message for the user.
The correct way to read the Firebase Exception is with this function I created:
bool CheckError(AggregateException exception, int firebaseExceptionCode)
{
Firebase.FirebaseException fbEx = null;
foreach (Exception e in exception.Flatten().InnerExceptions)
{
fbEx = e as Firebase.FirebaseException;
if (fbEx != null)
break;
}
if (fbEx != null)
{
if (fbEx.ErrorCode == firebaseExceptionCode)
{
return true;
}
else
{
return false;
}
}
return false;
}
And you can use it like this:
auth.SignInWithEmailAndPasswordAsync("test#gmail.com", "password").ContinueWith(task => {
if (task.IsCanceled)
{
Debug.LogError("SignInWithEmailAndPasswordAsync was canceled.");
return;
}
if (task.IsFaulted)
{
if(CheckError(task.Exception, (int)Firebase.Auth.AuthError.EmailAlreadyInUse))
{
// do whatever you want in this case
Debug.LogError("Email already in use");
}
Debug.LogError("UpdateEmailAsync encountered an error: " + task.Exception);
}
}
Here is some more code samples from firebase:
https://github.com/firebase/quickstart-unity/blob/master/auth/testapp/Assets/Firebase/Sample/Auth/UIHandler.cs
I got the answer from this thread:
https://github.com/firebase/quickstart-unity/issues/96
I hope this will help someone. All the best!
I am referencing this answer to another, very similar question (the only difference being the use of PHP).
I have seen an example of getting detailed error information from an exception throw by AWS DynamoDB's DescribeTable method in PHP (see above linked answer); however, I have had trouble finding similar information in C#.
Here is what I have mimicked so far:
var describeTableResponse = _client.DescribeTable(tableName);
var responseStatusCode = describeTableResponse.HttpStatusCode;
if (responseStatusCode == HttpStatusCode.OK)
{
return true;
}
else if(responseStatusCode == HttpStatusCode.BadRequest)
{
var error = // get detailed information; looking for ResourceNotFoundException
}
throw new AmazonDynamoDBException("Error performing the DescribeTable operation");
Above, client is a correctly configured DB client of type AmazonDynamoDBClient.
Any thoughts on how to do the equivalent of:
$error_type = $response->body->__type;
$error_code = explode('#', $error_type)[1];
if($error_code == 'ResourceNotFoundException')
{
echo "Table ".$table_name." exists.";
}
I actually ended up going a completely different route due to the specification surrounding the .Net DescribeTable() function -- it throws the ResourceNotFoundException.
try
{
_client.DescribeTable(tableName);
}
catch (AmazonServiceException amazonServiceException)
{
if (amazonServiceException.GetType() != typeof(ResourceNotFoundException))
{
throw;
}
return false;
}
return true;
I rewritten my question as I think it was too wordy and maybe what I am trying to achieve was lost.
I written this code in notepad so it may have mistakes and some stuff maybe not well thoughout but it is to illustrate what I see my options are.
// I wrap all code send back from service layer to controller in this class.
public class ResponseResult
{
public ResponseResult()
{
Errors = new Dictionary<string, string>();
Status = new ResponseBase();
}
public void AddError(string key, string errorMessage)
{
if (!Errors.ContainsKey(key))
{
Errors.Add(key, errorMessage);
}
}
public bool IsValid()
{
if (Errors.Count > 0)
{
return false;
}
return true;
}
public Dictionary<string, string> Errors { get; private set; }
public ResponseBase Status { get; set; }
}
public class ResponseResult<T> : ResponseResult
{
public T Response { get; set; }
}
public class ResponseBase
{
public HttpStatusCode Code { get; set; }
public string Message { get; set; }
}
Option 1 (what I am using now)
//controller
public HttpResponseMessage GetVenue(int venueId)
{
if (venueId == 0)
{
ModelState.AddModelError("badVenueId", "venue id must be greater than 0");
if (ModelState.IsValid)
{
var venue = venueService.FindVenue(venueId);
return Request.CreateResponse<ResponseResult<Venue>>(venue.Status.Code, venue);
}
// a wrapper that I made to extract the model state and try to make all my request have same layout.
var responseResult = new ResponseResultWrapper();
responseResult.Status.Code = HttpStatusCode.BadRequest;
responseResult.Status.Message = GenericErrors.InvalidRequest;
responseResult.ModelStateToResponseResult(ModelState);
return Request.CreateResponse<ResponseResult>(responseResult.Status.Code, responseResult);
}
// service layer
public ResponseResult<Venue> FindVenue(int venueId)
{
ResponseResult<Venue> responseResult = new ResponseResult<Venue>();
try
{
// I know this check was done in the controller but pretend this is some more advanced business logic validation.
if(venueId == 0)
{
// this is like Model State Error in MVC and mostly likely would with some sort of field.
responseResult.Errors.Add("badVenueId", "venue id must be greater than 0");
responseResult.Status.Code = HttpStatusCode.BadRequest;
}
var venue = context.Venues.Where(x => x.Id == venueId).FirstOrDefault();
if(venue == null)
{
var foundVenue = thirdPartyService.GetVenue(venueId);
if(foundVenue == null)
{
responseResult.Status.Code = HttpStatusCode.NotFound;
responseResult.Status.Message = "Oops could not find Venue";
return responseResult;
}
else
{
var city = cityService.FindCity(foundVenue.CityName);
if(city == null)
{
city = cityService.CreateCity(foundVenue.CityName);
if(city.Response == null)
{
responseResult.Status.Code = city.Status.Code;
responseResult.Status.Message = city.Status.Message;
return responseResult;
}
CreateVenue(VenueId, city.Response, foundVenue.Name);
responseResult.Status.Code = HttpStatusCode.Ok;
// I don't think I would return a success message here as the venue being displayed back to the user should be good enough.
responseResult.Status.Message = "";
reponseResult.Response = foundVenue;
}
}
return responseResult;
}
}
catch (SqlException ex)
{
ErrorSignal.FromCurrentContext().Raise(ex);
responseResult.Status.Code = HttpStatusCode.InternalServerError;
responseResult.Status.Message = GenericErrors.InternalError;
// maybe roll back statement here depending on the method and what it is doing.
}
// should I catch this, I know it should be if you handle it but you don't want nasty messages going back to the user.
catch (InvalidOperationException ex)
{
ErrorSignal.FromCurrentContext().Raise(ex);
responseResult.Status.Code = HttpStatusCode.InternalServerError;
responseResult.Status.Message = GenericErrors.InternalError;
}
// should I catch this, I know it should be if you handle it but you don't want nasty messages going back to the user.
catch (Exception ex)
{
ErrorSignal.FromCurrentContext().Raise(ex);
responseResult.Status.Code = HttpStatusCode.InternalServerError;
responseResult.Status.Message = GenericErrors.InternalError;
}
return responseResult;
}
// another service layer.
// it is ResponseResult<City> and not city because I could have a controller method that directly calls this method.
// but I also have a case where my other method in another service needs this as well.
public ResponseResult<City> CreateCity(string CityName)
{
ResponseResult<City> responseResult = new ResponseResult<City>();
try
{
City newCity = new City { Name = "N" };
context.Cities.Add(newCity);
context.SaveChanges();
responseResult.Status.Code = HttpStatusCode.Ok;
responseResult.Status.Message = "City was succesfully added";
}
// same catch statmens like above
catch (SqlException ex)
{
ErrorSignal.FromCurrentContext().Raise(ex);
responseResult.Status.Code = HttpStatusCode.InternalServerError;
responseResult.Status.Message = GenericErrors.InternalError;
// maybe roll back statement here depending on the method and what it is doing.
}
return responseResult;
}
As you can see the methods are all wrapped in the status codes as they could be directly called by the controller being public. FindCity() and CreateVenue() could also have this wrapping.
Option 2
public HttpResponseMessage GetVenue(int venueId)
{
try
{
if (venueId == 0)
{
ModelState.AddModelError("badVenueId", "venue id must be greater than 0");
if (ModelState.IsValid)
{
var venue = venueService.FindVenue(venueId);
return Request.CreateResponse<ResponseResult<Venue>>(HttpSatusCode.Ok, venue);
}
// a wrapper that I made to extract the model state and try to make all my request have same layout.
var responseResult = new ResponseResultWrapper();
responseResult.Status.Code = HttpStatusCode.BadRequest;
responseResult.Status.Message = GenericErrors.InvalidRequest;
responseResult.ModelStateToResponseResult(ModelState);
return Request.CreateResponse<ResponseResult>(responseResult.Status.Code, responseResult);
}
catchcatch (SqlException ex)
{
// can't remember how write this and too tried to look up.
return Request.CreateResponse(HttpStatusCode.InternalServerError;, "something here");
}
}
public Venue FindVenue(int venueId)
{
try
{
// how to pass back business logic error now without my wrapper?
if(venueId == 0)
{
// what here?
}
var venue = context.Venues.Where(x => x.Id == venueId).FirstOrDefault();
if(venue == null)
{
var foundVenue = thirdPartyService.GetVenue(venueId);
if(foundVenue == null)
{
// what here?
}
else
{
var city = cityService.FindCity(foundVenue.CityName);
if(city == null)
{
city = cityService.CreateCity(foundVenue.CityName);
if(city == null)
{
// what here?
}
CreateVenue(VenueId, city.Response, foundVenue.Name);
}
}
return venue;
}
}
catch (SqlException ex)
{
// should there be a try catch here now?
// I am guessing I am going to need to have this here if I need to do a rollback and can't do it in the controller
// throw exception here. Maybe this won't exist if no rollback is needed.
}
return null;
}
public City CreateCity(string CityName)
{
// if it crashes something I guess will catch it. Don't think I need to rollback here as only one statement being sent to database.
City newCity = new City { Name = "N" };
context.Cities.Add(newCity);
context.SaveChanges();
return newCity;
}
As you see with option 2, I might still need to wrap it in try catches for rollbacks and I am not sure how to handle advanced business validation.
Also with catching everything in the controller and sending back vanilla objects(without my wrapper) I am unsure how to do fine grain HttpStatus codes(say like notFound,Create and such)
Sorry for the brief response, but here is my general rule - if an exception occurs which you expect might happen, deal with it - either by retrying or telling the user something went wrong and giving them options to fix it.
If an unexpected exception occurs, if it's something you can deal with (e.g a timeout which you can retry) try to deal with it, otherwise get out - just think what any MS app does - e.g. office - you get an apology that something went wrong and the app ends. It's better to end gracefully than to potentially corrupt data and leave things in a real mess.
This is an article with Java-specific concepts and examples, but the broad principles here are the way to go.
Distinguish between fault exceptions, which are catastrophic and unrecoverable, and contingency exceptions, which are very much recoverable. Let the faults "bubble" to the fault barrier, where you handle appropriately. For example, you might log the error, E-mail someone or send a message to a message queue, and present the user with a nice, informative error page.
Whatever you do, be sure to preserve all the exception information from the source.
Hope that helps.
Throw an exception wherever your code determines that something has gone wrong.
You always need to handle exceptions in methods which are called directly by the end-user. This is to cater for unexpected errors which your code doesn't have specific handling for. Your generic handling code would typically log the error and may or may not include letting the user know that an unexpected error has occurred.
But if there are errors which you can expect ahead of time, you'll often want to handle these lower down in the code, nearer to the point at which they occur, so that your application can "recover" from the error and continue.
I think exceptions are useful any time you need to return details of a failure from a method, whilst being able to use the ideal return type for the method you're calling.
You said in your question:
Now for me I try to return error messages back to the the controller
and try not to really catch anything in the controller.
If the service method is supposed to ideally return a Venue object, how do you return this potential error message back to the controller? an out parameter? change the return type to something which has an error message property on it?
If you're doing either of those options, I think you're reinventing the wheel... i.e. creating a way to return exception information when one already exists.
Finally, Exceptions are strongly typed representations of what went wrong. If you return an error message, then that is fine to send back to the user, but if you need to programatically do different things based on the details of the error, then you don't want to be switching on magic string.
For example, wouldn't it be handy to differentiate between authorization errors and not found errors so you can return the most appropriate http status code to the user?
Don't forget that the Exception class has a Message property you can simply return to the user if you want to use it that way
To make sure I understand the question, your are creating a web service and want to know when to handle and when to throw exceptions.
In this situation I would strongly recommend that you catch all exceptions. "Unhandled" exceptions are very bad form. On web sites they result in displays that range from meaningless to dangerous by exposing internal information that you do no want the public to see.
If this is a good sized program I suggest that you create your own MyException class which derives from System.Exception. The purpose of this is provide a place for you to add additional information specific to your application. Here are some typical things I like to add to my MyException classes:
An ID number that will help me find the location in the code where the problem occurred.
A "LogMessage" method that logs the exception, sometimes to the Windows Event Log. Whether or not you log and to which log you write depends on what you want recorded, and the severity of the situation.
An indicator that shows the exception has been logged so the above method will not log twice even if it gets called more than once.
Anything else that might be useful given the circumstance.
I also like to put the text of the messages in an external resource file, like an XML document, and key them to the error number that you assign. This allows you to change the error text to improve clarity without having to redeploy the application.
Catch all exceptions and create a new instance of your MyException type and put the original exception into inner exception property. Below the first level of my application, I always throw one of my MyException instances rather than the original exception.
At the top level (application level), NEVER let an exception go unhandled and never throw your own exception. A better way is to return an error code and message in your data contract. That way the client application will only get what you want them to see. The only exceptions they'll need to worry about are the ones outside your scope, i.e. configuration errors or communication failures. In other words if they are able to invoke your service and the network stays connected you should give them a response they can interpret.
Hope this helps.
PS I didn't include a sample exception as I am sure a little searching will find many. Post if you want me to put up a simple sample.
Use try catch at all levels and bubble it up. Optionally, log the error in a file or database. I use text file - tab delimited. Capture at each level
1. Module Name (Use C# supplied methods to get this)
2. Method Name
3. Code Being Executed (User created - "Connecting to database")
4. Error Number
5. Error Description
6. Code Being Executed (User created - "Accessing database")
7. Error Number for the end user
8. Error Description for the end user
Additionally, I also pass a unique identifier like - Session Id in case of Web, Logged in User Id, User Name (if available)
I always have the Exception catch block. In here I set the error number as -0 and the message from the exception object as the error description. If it is SQL Server related - I capture SQL Exception. This generates an error number - I use that.
I want to extend this some more though.