简体   繁体   中英

How to properly throw and handle exceptions with web services

I'm following MVC pattern in my Application server. I'm trying to throw an exception but its not been properly thrown.

Here is the code from controller:

[HttpPost]
public IHttpActionResult PostAddSuperUser(SuperUserViewModel SU)
{
    try
    {
        //more code
        blHandler.addSuperUser((SuperUser)SU.user, SU.Password);
        return Ok();
    }
    catch (EUserAlreadyExist ex)
    {
        var resp = new HttpResponseMessage(HttpStatusCode.NotAcceptable);
        resp.Content = new StringContent(string.Format("Already exist ", SU.user.Mail));
        resp.ReasonPhrase = "Already exist";
        throw new HttpResponseException(resp);
    }

Then the client side calls it as follow:

try{
            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri("http://localhost:50687/");

            HttpResponseMessage response = await client.PostAsJsonAsync<SuperUserViewModel>("/api/SuperUser/PostAddSuperUser", SUVM);

            if (response.IsSuccessStatusCode)
            {
                new SuccesPupUp("", "SuperUser " + SupUserName + " was added");
            }
            this.Close();
        }
}
catch (HttpResponseException Exc)
{
    new ErrorPopUp("", Exc.Message);
}

According to this this I'm throwing it correctly, but when I run it I got this error 在此输入图像描述

How can I fix it?

EDIT: I want to throw the exception to the client side, so as to it could ask the user for a new email address

The problem is within this block of code (seems obvious but bear with me):

  catch (EUserAlreadyExist ex)
    {
        var resp = new HttpResponseMessage(HttpStatusCode.NotAcceptable);
        resp.Content = new StringContent(string.Format("Already exist ", SU.user.Mail));
        resp.ReasonPhrase = "Already exist";
        throw new HttpResponseException(resp);
    }

Whats happening is that you are catching an EUserAlreadyExist exception from the above try and then throwing a new exception without an accompanying try-catch block. So this means that just because you threw an exception within a catch, it won't auto-magically catch it, you would have to have a separate try-catch within your catch

Going further with this, the client-side call to this try-catch also won't catch the thrown exception because they (the catch statements) are catching different types of exceptions than what is being thrown.

To fix it would require you catching the exception that is being thrown in this case a HttpResponseException exception. So that would mean your code might look something like this:

  catch (EUserAlreadyExist ex)
    {
    try{
        var resp = new HttpResponseMessage(HttpStatusCode.NotAcceptable);
        resp.Content = new StringContent(string.Format("Already exist ", SU.user.Mail));
        resp.ReasonPhrase = "Already exist";
        throw new HttpResponseException(resp);
       }
       catch(HttpResponseException ex2)
       {
         //do something here with the exception
       }
    }

Server side code should not need to catch the exception and re-throw it - what's the point? Just let it bubble up to the client. That's the beauty and power of exceptions. The trouble is MVC wants to return a View or an HTTP Status Code, not rich, strongly typed exception information.

You appear to be using MVC pattern in a rich client (client-server) situation, which makes no sense. MVC is best suited to thin client situations whereby the server serves up views, and the client just renders them. When you have a rich client, the MVVM pattern makes more sense. Server can serve up View Models (data) and client can take over all the user interaction, views etc.

Consider using an MVVM approach (with WCF) instead of MVC. Then both client and server will have a common understanding of the exception types that can be thrown. Server can throw, client can catch, easy.

Your client code would then be as simple as:

try
{
    c.AddSuperUser(SUVM);
}
catch (Exception e)
{
    // etc
}

where c is the WCF client proxy.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM