WCF Web Services, returning an Error/exception str

2019-01-28 10:21发布

I have a set of WCF web services, which, if an exception occurs, will use OutgoingWebResponseContext to return the error description back to the caller.

My problem is that sometimes, when something goes wrong, the web service is shown as failed, with an ERR_CONNECTION_RESET message, rather than returning the error message, and I would like to prevent this from happening.

For example, here's my beautiful C# code which queries my Northwind database, and returns a list of Customer names.

Or rather, it would do, but I've deliberately stuck an exception in there.

public List<string> GetAllCustomerNames()
{
    //  Get a list of unique Customer names.
    //
    try 
    {
        throw new Exception("Oh heck, something went wrong !");

        NorthwindDataContext dc = new NorthwindDataContext();
        var results = (from cust in dc.Customers select cust.CompanyName).Distinct().OrderBy(s => s).ToList();

        return results;
    }           
    catch (Exception ex)
    {
        OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse;
        response.StatusCode = System.Net.HttpStatusCode.InternalServerError;
        response.StatusDescription = ex.Message;
        return null;
    }
}

In my AngularJS controller, I can call this web service...

$http.get('http://localhost:15021/Service1.svc/getAllCustomerNames')
    .then(function (data) {
        //  We successfully loaded the list of Customer names.
        $scope.ListOfCustomerNames = data.GetAllCustomerNamesResult;

    }, function (errorResponse) {

        //  The WCF Web Service returned an error

        var HTTPErrorNumber = errorResponse.status;
        var HTTPErrorStatusText = errorResponse.statusText;

        alert("An error occurred whilst fetching Customer Names\r\nHTTP status code: " + HTTPErrorNumber + "\r\nError: " + HTTPErrorStatusText);

    });

...and if this exception occurs, I do see the full exception message...

enter image description here

Wonderful.

For all readers, who've wanted to know a simple, generic way to return and display Exceptions from your WCF web services, there's your solution !

Okay, so now I'll remove my Exception line of code, and the web service runs fine again. The Customer data is returned to the Angular controller without any problems.

But.. if an exception occurs when connecting to the database (for example, it times out, I have the wrong database name in my connection string, etc), then the following line of code does throw an exception...

NorthwindDataContext dc = new NorthwindDataContext();

...my catch code does kick in (I put a breakpoint on it to check), and we set the StatusDescription to the Exception message..

Exception

But the response which is sent back doesn't contain either my HTTP Status number or text.

My Angular controller just receives an HTTP Status Code of 0, with no StatusMessage.

And if I hit F12 in Chrome, you can see that it actually says the web service failed, rather than returning Status Code 403, and there's no message.

enter image description here

So my question is simply, is there a way to prevent this failure from happening ?

Obviously, its much friendlier to return a description of what went wrong, rather than just "The web service failed miserably... but we can't tell you why."

If I can get over this issue, this'd be a nice way to make all of our WCF web services error-message friendly in our in-house apps. But of course, for production systems, sure, you wouldn't really want to bombard the user with technical exception messages.

Update, many hours later..

I found the cause, and the solution.

Are you ready for this?

The problem was that when the DataContext line threw an exception...

NorthwindDataContext dc = new NorthwindDataContext();

...the exception message had a line-feed in it.

Cannot open database "Northwind" requested by the login. 
The login failed.Login failed for user 'MikesWrongUserName'.This session has been assigned a tracing ID of '1f0513d1-9ce1-47ef-9d44-1f4546eb0b73'.  Provide this tracing ID to customer support when you need assistance.

That line-feed was causing the problem. If you attempt to return that in a StatusDescription field, it causes the entire web service to be reported as "failed".

So, the solution is to simply remove any line-feeds before you return the exception message.

So here, finally, is an example of how to use a try..catch in your WCF web services, so they'll always return exception messages back to the caller.

public List<string> GetAllCustomerNames()
{
    //  Get a list of unique Company Names.
    //
    try
    {
        NorthwindDataContext dc = new NorthwindDataContext();
        var results = (from cust in dc.Customers select cust.CompanyName).Distinct().OrderBy(s => s).ToList();

        return results;
    }
    catch (Exception ex)
    {
        OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse;
        response.StatusCode = System.Net.HttpStatusCode.InternalServerError;

        //  If a database Exception occurs, it might have a line-feed in it, 
        //  which will cause the web service to completely fail  (no Status
        //  Code or Status Message will get returned.)
        response.StatusDescription = ex.Message.Replace("\r\n", "");
        return null;
    }
}

Thanks for all of your suggestions!

0条回答
登录 后发表回答