3

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 errorenter image description here

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

Community
  • 1
  • 1
Rodrigo Laguna
  • 1,796
  • 1
  • 26
  • 46
  • 1
    as you can see it throws `HttpResponseException` which you're not catching, just add first catch - `catch(HttpResponseException ex)` – Michael May 28 '15 at 20:26
  • 3
    Since you are asking about "properly handling exceptions", please note its a "best practice" to name your exceptions with a suffix of Exception instead of a prefix "E". For example, `EInvalidPassword` should be named `InvalidPasswordException`, yes, its longer, but its much more evident what it is. – Ron Beyer May 28 '15 at 20:33
  • in `catch()` you must handle `HttpResponseException`, not `EUserAlredyExist`, becouse you dont throw `EUserAlredyExist` exception. – Daniel Petrovaliev May 28 '15 at 20:38
  • This question is related to http://stackoverflow.com/questions/19287426/what-happens-if-an-exception-occurs-in-catch-block-in-c-also-what-would-be-the. If you throw an Exception from within a catch block, and there is no catch block outside of that one, the Exception is unhandled. – John Washam May 28 '15 at 21:38
  • 1
    @DanielPetrovaliev, it's likely that his blHandler.addSuperUser() method could throw the `EUserAlreadyExist` exception, which is why he's catching it. – John Washam May 28 '15 at 21:44
  • An unhandled HttpResponseException simply causes the request processing to end and a specific status code to be returned to the client. It doesn't "throw the exception to the client side". The client just sees the response, it has no idea what occured on the server to cause it. That is how HTTP works. You either need to handle this response yourself on the client, or use a framework which will encode exception information into the response, decode it on the client, and "magically" rethrow it. For example, this can be done with WCF or with ASP.NET Web Services. – svinja May 28 '15 at 23:08

2 Answers2

0

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
       }
    }
Pseudonym
  • 2,052
  • 2
  • 17
  • 38
  • This doesn't seem right, why would you throw an exception and then catch it right away? – Ron Beyer May 28 '15 at 20:44
  • Per @Rodrigo's question and code, this answer technically should work, but I would agree it doesn't make much sense to throw an exception in this way. – John Washam May 28 '15 at 21:41
  • @Pseudonym all I want to do with my try catch on server side is to throw the exception to the client side, so how will catching my own exception help me to do it? As I see, if I add a new try-catch, I'll catch it again but I still don't know what to do with it or how to send it to the client side – Rodrigo Laguna May 28 '15 at 22:01
0

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.

saille
  • 9,014
  • 5
  • 45
  • 57