2

So I am looking for a pattern on how to handle exceptions. Specifically I want to be able to pass the exception message on to the client from a Web API controller.

The client is using a third party library which deals with a call to the API as

this.msgs = [];
let xhr = new XMLHttpRequest(),
formData = new FormData();


for(let i = 0; i < this.files.length; i++) {
    formData.append(this.name, this.files[i], this.files[i].name);
}

xhr.upload.addEventListener('progress', (e: ProgressEvent) => {
    if(e.lengthComputable) {
      this.progress = Math.round((e.loaded * 100) / e.total);
    }
  }, false);

xhr.onreadystatechange = () => {
    if(xhr.readyState == 4) {
        this.progress = 0;

        if(xhr.status == 200)
            this.onUpload.emit({xhr: xhr, files: this.files});
        else
            this.onError.emit({xhr: xhr, files: this.files});

        this.clear();
    }
};

xhr.open('POST', this.url, true);
xhr.send(formData);

My current call back function is such

errorComplete(event: any) {
    console.log("upload error");
}

notice that on error the library just wraps up the XMLHttpRequest and passes it on to my call back function.

so in the controller I have created a test line as follows

throw new Exception("This is a test message");

This is to simulate an unexpected exception

currently the return code in the XMLHttpRequest is a 500 and the text is the html that .Net generates when an exception occurs.

yes the method in my controller will need to wrapper in a try-catch but I am not sure of what code to put in the catch so I can send the error message down to the client and it can handle it and not take down the application.

the current use case I am looking at is the user uploads a file to the system but there is already a file with the specified name in the system. And renaming the file is not an option! I need to notify the user that there is already a file with that name in the system.

google has not revealed a way to pass the message back so I can process it.

1
  • Don't use try catch in controller. use cross cutting concerns via an ExceptionHandler derived class. Have that class return you error code and body. Usually 500 Internal Server Error. The body can have any custom details specific to the app Commented Mar 29, 2017 at 23:25

1 Answer 1

1

Thank you Nkosi- your comment got me on the right track. I implemented some middleware.

public class UIExceptionHandler
{
    RequestDelegate _next;
    public UIExceptionHandler(RequestDelegate next)
    {
        this._next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        try
        {
            await this._next(context);
        }
        catch (Exception x)
        {
            if (!context.Response.HasStarted)
            {
                context.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
                context.Response.Headers["Message"] = x.Message;
            }
        }
    }
}

public static class UIExcetionHandlerExtensions
{
    public static IApplicationBuilder UseUIExceptionHandler(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<UIExceptionHandler>();
    }
}

and in the configure method of the startup

app.UseUIExceptionHandler();

then on the client I can do

errorComplete(event: any) {
    var errorMessage = event.xhr.getResponseHeader('Message');
    console.log(errorMessage);
}

If anyone sees an issue with this solution please let me know

Sign up to request clarification or add additional context in comments.

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.