2

Here's what I have tried so far:

 public async Task<IHttpActionResult> Post([FromBody]Word word)
    {
        try
        {
            db.Words.Add(word);

            await db.SaveChangesAsync(User, DateTime.UtcNow);
            return Ok(word);
        }
        catch (Exception ex)
        {
            return BadRequest(new JavaScriptSerializer().Serialize(ex));
        }
    }

When i try to serialize, i get the following error:

{"message":"An error has occurred.","exceptionMessage":"A circular reference was detected while serializing an object of type 'Entities.Models.Core.Word'.","exceptionType":"System.InvalidOperationException","stackTrace":" at .....

I want to return ex.Message and the InnerException. However I don't know if there will be one or more inner exceptions.

5
  • Is error occurred at "return Ok(word);" line? Commented May 3, 2016 at 7:17
  • For this particular case I was inserting a duplicate primary key and the inner exception told me this. my problem is 'how to report this and send back to the front-end' Commented May 3, 2016 at 7:19
  • i assume you have a error function in you ajax call? you get the response there and do response.exceptionMessage to get the error. Commented May 3, 2016 at 7:20
  • stackoverflow.com/q/486460/1660178 this one can solve.. Commented May 3, 2016 at 7:29
  • Possible duplicate of How To Fix Circular Reference Error When Dealing With Json Commented May 3, 2016 at 9:56

2 Answers 2

2

I usually use a helper function that deals with exception handling in my Web API projects. I pass the exception that's thrown as an argument to it, then return a HttpResponseException and throw that.

The thrown exception will automatically be serialized to the return type of your Http verb function. In my example I return a Task as it'll serialize any .Net type to a generic object.

If you look at my example below you'll see I have a Method called Get that has its return type set to Task. The object type will be serialized to JSON if the front-end app performs a HTTP GET (in your case a POST) with the Accept header set to 'application/json', when the method returns it'll serialize the return type of Task to json. This also works for the Accept type of text/xml.

I'd recommend filtering specific data in your helper method. you probably don't want people consuming your API to get full stack traces and the like after all, but obviously this is down to your requirements.

public async Task<Object> Get()
{
    object result = null;
    try
    {
        result = await methodThatThrowsException();
    }
    catch (Exception ex)
    {
        throw CreateHttpResponseException(ex);
    }
        return result;
}

Helper Method

private HttpResponseException CreateHttpResponseException(Exception ex)
{
    HttpResponseMessage message;
    if (ex.GetType() == typeof(FaultException<LoginFault>))
    {
        message = new HttpResponseMessage(HttpStatusCode.Forbidden);
    }
    else
    {
        message = new HttpResponseMessage(HttpStatusCode.InternalServerError);
    }

    message.Content = new StringContent(ex.Message);
    return new HttpResponseException(message);
}

In the helper Method, use a StringBuilder to build up what you want to display in your front end. Concatenate and format your error message as you require and then assign the string value to your MessageResponseMessage.Content field.

You'll need to iterate over the Exception InnerException and check to see if it's null, concatenating the exception message etc... as you need.

You could iterate over inner Exceptions using something like

StringBuilder exceptionMessage = new StringBuilder();
Exception inner = ex.InnerException;
while (inner != null)
{
    exceptionMessage.Append(inner.Message)
                    .Append(Environment.NewLine);
    inner = inner.InnerException;
}
Sign up to request clarification or add additional context in comments.

Comments

1

From you expcetion issue is following you try to save object of Entities.Models.Core.Word which probably have refference to something else and you are using lazy loading. So when serializer try to serialyze your object it fails. there is few ways to fix that.

In global.asax in application_start add

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;

Second option would be not to serialize everything but ony what you need

return BadRequest(new JavaScriptSerializer().Serialize(new
            {
                ex.Message,
                ex.StackTrace
            }));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.