Throwing an Exception

Introduction

As mentioned previously, the Exception class is equipped with a Message property that carries a message for the error that occurred. We also mentioned that the message of this property may not be particularly useful to a user. Fortunately, you can create your own message and pass it to an Exception object. To be able to receive custom messages, the Exception class provides the following constructor:

public Exception(string message);

As mentioned already, all exceptions classes derive directly or indirectly from Exception. As a result, all thoses classes are equipped with a default constructor and all of them inherit the constructor that takes a string as argument.

To use the constructor that uses a string parameter, in the section in which you are anticipating the error, type the throw keyword followed by a new instance of the Exception class using this constructor. Here is an example:

@{
    ViewBag.Title = "Calculations";
}

<h2>Calculations</h2>

@{
    string message = "";
    double result = 0.00;
    string oper = "";
    double number1 = 0.00, number2 = 0.00;


    if (IsPost)
    {
        try
        {
            number1 = double.Parse(Request["txtNumber1"]);
            number2 = double.Parse(Request["txtNumber2"]);
            oper = Request["txtNumber2"];

            if( (oper != "+") && (oper != "-") && (oper != "*") && (oper != "/") )
            {
                throw new Exception(oper);
            }

            switch (oper)
            {
                case "+":
                    result = number1 + number2;
                    break;
                case "-":
                    result = number1 - number2;
                    break;
                case "*":
                    result = number1 * number2;
                    break;
                case "/":
                    result = number1 / number2;
                    break;
                default:
                    message = "Bad Operation";
                    break;
            }

        }
        catch (Exception exc)
        {
            message = "The value you entered is not a valid number.";
        }
    }
}

@using (Html.BeginForm())
{
    <table>
        <tr>
            <td>Number 1:</td>
            <td>@Html.TextBox("txtNumber1", @number1)</td>
        </tr>
        <tr>
            <td>Operator:</td>
            <td>@Html.TextBox("txtOperator", @oper)</td>
        </tr>
        <tr>
            <td>Number 2:</td>
            <td>@Html.TextBox("txtNumber2", @number1)</td>
        </tr>
        <tr>
            <td>&nbsp;</td>
            <td><input type="submit" name="btnCalculate" value="Calculate" /></td>
        </tr>
        <tr>
            <td>Result:</td>
            <td>@Html.TextBox("txtResult", @result)</td>
        </tr>
    </table>

    <p>@message</p>
}

Calculator 1: Exception Handling

Practical LearningPractical Learning: Introducing Exception Handling

  1. Start Microsoft Visual Studio
  2. On the main menu of Microsoft Visual Studio, click File -> New -> Project...
  3. In the middle frame of the New Project dialog box, make sure ASP.NET Web Application (.NET Framework) is selected (if not, click it).
    Change the Name of the project to OFRE5
  4. Click OK
  5. In the New ASP.NET Web Application dialog box, in the list of templates, click MVC
  6. Click OK
  7. In the Solution Explorer, right-click OFRE5 -> Add -> New Folder
  8. Type Images and press Enter
  9. Add the following pictures to the Images folder:


    Campaign Campaign
    Campaign
  10. In the Solution Explorer, expand Content
  11. Double-click bootstrap.css to open it
  12. Find the following section in the document:
    @media screen and (min-width: 768px) {
      .jumbotron {
        padding-top: 48px;
        padding-bottom: 48px;
      }
      .container .jumbotron {
        padding-right: 60px;
        padding-left: 60px;
      }
      .jumbotron h1 {
        font-size: 63px;
      }
    }
  13. In that section, change the value of padding-botton from 48px to 4px
  14. In the Solution Explorer, right-click the Content folder -> Add -> Style Sheet
  15. Type FundRaising as the name of the file
  16. Click OK
  17. Create the following styles in the document:
    body {
        padding-top: 50px;
        padding-bottom: 20px;
    }
    
    .glued-part {
        top: 0;
        width: 100%;
        height: 75px;
        position: fixed;
        background-color: white;
    }
    
    .heading-format {
        font-weight: 800;
        font-family: Cambria, Cochin, Georgia, Times, Times New Roman, serif;
    }
    
    .heading1 {
        color: maroon;
        font-size: 2.52em;
        line-height: 2.05em;
    }
    
    .heading2 {
        color: #b71f1f;
        margin-top: 20px;
        font-size: 1.52em;
        line-height: 1.15em;
    }
    
    .navbar-fixed-top { top: 75px; }
    
    .navbar-inverse   {
        background-color: #581405;
        border-top: 3px solid black;
        border-bottom: 3px solid black;
    }
    
    .jumbotron {
        padding-top: 80px;
        background-color: white;
        border: 1px solid burlywood
    }
    
    .contents {
        width: 300px;
        margin: auto;
        margin-top: 40px;
    }
    
    .content2Parts { width:         300px;  }
    .content3Parts { width:         350px;  }
    .left-column   { width:         140px;  }
    .tbx-format    { width:         50px;   }
    .lead          { margin-bottom: 0;      }
    .pic-holder    { text-align:    center; }
    .left-column   { width:         140px;  }
    .tbx-format    { width:         40px;   }
  18. In the Solution Explorer, expand Views
  19. Expand Shared
  20. Double-click _Layout.cshtml to open it
  21. Change the document as follows:
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>OFRE :: @ViewBag.Title</title>
        @Styles.Render("~/Content/css")
        @Scripts.Render("~/bundles/modernizr")
        <link rel="stylesheet" type="text/css" href="~/Content/FundRaising.css" />
    </head>
    <body>
    <div class="glued-part">
        <p class="heading1 heading-format text-center">Organization for Fundraising Events</p>
    </div>
    
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li>@Html.ActionLink("About OFRE", "About", "Home")</li>
                    <li>@Html.ActionLink("Contact Us", "Contact", "Home")</li>
                </ul>
            </div>
        </div>
    </div>
    
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <h4 class="text-center">&copy; @DateTime.Now.Year :: Organization for Fundraising Events</h4>
        </footer>
    </div>
    
        @Scripts.Render("~/bundles/jquery")
        @Scripts.Render("~/bundles/bootstrap")
        @RenderSection("scripts", required: false)
    </body>
    </html>
  22. In the Solution Explorer, right-click Controllers -> Add -> New Scaffolded Item...
  23. In the Add Scaffold dialog box, click MVC 5 Controller - Empty
  24. Click Add
  25. Type Campaigns to get CampaignsController
  26. Click Add
  27. Change the class as follows:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    namespace OFRE5.Controllers
    {
        public class CampaignsController : Controller
        {
            // GET: Campaigns
            public ActionResult Index()
            {
                return View();
            }
    
            // GET: TwoWay
            public ActionResult TwoWay()
            {
                return View();
            }
    
            // GET: ThreeWay
            public ActionResult ThreeWay()
            {
                return View();
            }
            
            public int DistributeFirstPart(int amount, int portion1, int portion2)
            {
                int totalRatios = portion1 + portion2;
                int eachPart = amount / totalRatios;
                int result = eachPart * portion1;
    
                return result;
            }
    
            public int Subtract(int first, int second)
            {
                return first - second;
            }
        }
    }
  28. In the Solution Explorer, expand Views, right-click Campaigns -> Add -> New Scaffolded Item...
  29. In the Add Scaffold dialog box, click MVC 5 View
  30. Click Add
  31. Type TwoWay for the View Name
  32. Click Add
  33. In the Solution Explorer, right-click Campaigns -> Add > View...
  34. Type ThreeWay for the View Name
  35. Press Enter
  36. In the Solution Explorer, under Views, expand Home
  37. Under Home, double-click Index.cshtml to open it
  38. Change the document as follows:
    @{
        ViewBag.Title = "OFRE Home";
    }
    
    <div class="jumbotron">
        <h1>OFRE</h1>
        <p class="lead">
            The Organization for Fundraising Events, or OFRE, is a group of people who assist organizations, 
            communities, associations, schools, causes, religious institutions, etc, to plan, conduct, promote, 
            and run campaigns to raise money for any goal (cause, health issues, communities, school, politics, 
            ceremony, religion, catastrophe, business startup, etc). The Organization can provide a complete 
            service, including promoting the event, collecting, and delivering the funds. OFRE is a private, 
            independent, and a not-for-profit organization.
        </p>
    </div>
    
    <div class="row">
        <div class="col-md-4">
            <p class="pic-holder"><img src="~/Images/Campaign.png" alt="Plan With Us" width="248" height="137" /></p>
            <h2>Plan With Us</h2>
            <p>Are you ready for a memorable experience in fundraising? You reaached the right place. 
            Do you lack experience in fundraising? Don&#039;t take a chance. Don&#039;t worry about 
            a thing. Let us run your next campaign. Give us the opportunity to put our vast 
            experience at your disposal. You will enjoy the whole adventure.</p>
        </div>
        <div class="col-md-4">
            <p class="pic-holder"><img src="~/Images/TwoWay.png" alt="Two-Way Campaign" width="248" height="136" /></p>
            <h2>Two-Way Campaign</h2>
            <p>This is an already completely created program to run a campaign to raise funds for two 
            organizations or causes. This program consists of starting a compaign, collecting funds, 
            appropriately distributing them, and delivering a complete legal/business/financial 
            report of the campaign.</p>
            @Html.ActionLink("Two-Way Campaign", "TwoWay", "Campaigns", new { DontTryToFindOutWhatThisIs = "" }, new { @class = "btn btn-default" })
        </div>
        <div class="col-md-4">
            <p class="pic-holder"><img src="~/Images/ThreeWay.png" alt="Three-Way Distribution" width="248" height="136" /></p>
            <h2>Three-Way Distribution</h2>
            <p>In this program, the Organization runs a campaign to raise funds for three different 
            organizations or causes. The ratios of distribution are stated any way a group wants. 
            An effective computer application is intuitively ready to process all types of requests.</p>
            @Html.ActionLink("Three-Way Campaign Distribution", "ThreeWay", "Campaigns", new { ThisIsJustAPlaceHolder = "" }, new { @class = "btn btn-default" })
        </div>
    </div>
  39. Access the TwoWay.cs file and change its document as follows:
    @{
        ViewBag.Title = "Two-Way Campaign Distribution";
    }
    
    @{
        int amtPledged = 0;
        int ratio1 = 1;
        int ratio2 = 1;
    
        int portion1 = 0;
        int portion2 = 0;
    
        string strErrorMessage = "";
    
        if (IsPost)
        {
            try
            {
                amtPledged = Convert.ToInt32(Request["txtAllocation"]);
                ratio1 = Convert.ToInt32(Request["txtPortion1"]);
                ratio2 = Convert.ToInt32(Request["txtPortion2"]);
    
                OFRE5.Controllers.CampaignsController cc = new OFRE5.Controllers.CampaignsController();
    
                portion1 = cc.DistributeFirstPart(amtPledged, ratio1, ratio2);
                portion2 = cc.Subtract(amtPledged, portion1);
            }
            catch (FormatException)
            {
                strErrorMessage = "The value you entered for the amount to allocate or pledge is not valid. " +
                                  "Only natural numbers (such as 200, 1250, 5000, or 100000) are allowed.";
            }
        }
    }
    
    <p>&nbsp;</p>
    <p>&nbsp;</p>
    
    <div class="contents content2Parts">
        <p class="heading2 text-center heading-format">Pledge Distribution</p>
    
        <form name="frmDistribution" method="post">
            <table>
                <tr>
                    <td class="left-column">Amount to Allocate:</td>
                    <td><input type="text" name="txtAllocation" value=@amtPledged /></td>
                </tr>
            </table>
            <table>
                <tr>
                    <td class="left-column">In the Ratio:</td>
                    <td><input type="text" name="txtPortion1" class="tbx-format" value=@ratio1 /></td>
                    <td>:</td>
                    <td><input type="text" class="tbx-format" name="txtPortion2" value="@ratio2" /></td>
                    <td><input name="btnAllocate" type="submit" value="Allocate" /></td>
                </tr>
            </table>
            <hr />
            <table>
                <tr>
                    <td class="left-column">Part 1 Receives:</td>
                    <td><input type="text" name="txtPart1" value="@portion1" /></td>
                </tr>
                <tr>
                    <td>Part 2 Receives:</td>
                    <td><input type="text" name="txtPart2" value="@portion2" /></td>
                </tr>
            </table>
            <hr />
            <table>
                <tr>
                    <td>@strErrorMessage</td>
                </tr>
            </table>
        </form>
    </div>
  40. To execute the project, on the main menu, click Debug -> Start Without Debugging
  41. Close the browser and return to your programming environment
  42. Access the CampaignsController.cs file

Exceptions and Methods

There are various ways you can involve exceptions in a method. When it comes to methods, one way you can use it to get out of the method at any time, for any reason. Consider the following code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Exercise.Controllers
{
    public class HomeController : Controller
    {
        public void ShowMessage()
        {
            throw new Exception();

            Response.Write("This is the wonderful world of C# programming.");       
        }
    }
}

In this example, the line that holds the message in the ShowMessage() method will never be reached so the next line will not display. One way you can proceed in a method is to throw an exception if something happens. That is, you can create a conditional statement that would consider, or throw an exception.

Practical LearningPractical Learning: Throwing an Exception from a Method

  1. Change the DistributeFirstPart() method as follows:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    namespace OFRE5.Controllers
    {
        public class CampaignsController : Controller
        {
            // GET: Campaigns
            public ActionResult Index()
            {
                return View();
            }
    
            // GET: TwoWay
            public ActionResult TwoWay()
            {
                return View();
            }
    
            // GET: ThreeWay
            public ActionResult ThreeWay()
            {
                return View();
            }
    
            public int DistributeFirstPart(int amount, int portion1, int portion2)
            {
                int totalRatios = portion1 + portion2;
    
                 if (totalRatios == 0)
                    throw new FormatException("The value provided for one or both ratios is not valid.");
    
                int eachPart = amount / totalRatios;
                int result = eachPart * portion1;
    
                return result;
            }
    
            public int Subtract(int first, int second)
            {
                return first - second;
            }
        }
    }
  2. To execute the project, on the main menu, click Debug -> Start Without Debugging
  3. In the top text box, type 1,250,000
  4. Click the Calculate button
  5. Close the browser and return to your programming environment
  6. One of the characteristics of a function is that it returns a value, which is done using the return keyword. Therefore, if a calculation made in a function may produce an error, you can create a conditional statement, such as an if...else or if...else if...else scenario where the last else is a throw condition.
    For an example, change the DistributeFirstPart() method as follows:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    namespace OFRE5.Controllers
    {
        public class CampaignsController : Controller
        {
            // GET: Campaigns
            public ActionResult Index()
            {
                return View();
            }
    
            // GET: TwoWay
            public ActionResult TwoWay()
            {
                return View();
            }
    
            // GET: ThreeWay
            public ActionResult ThreeWay()
            {
                return View();
            }
    
            public int DistributeFirstPart(int amount, int portion1, int portion2)
            {
                if (portion1 != 0)
                {
                    int totalRatios = portion1 + portion2;
    
                    int eachPart = amount / totalRatios;
                    int result = eachPart * portion1;
    
                    return result;
                }
                else
                    throw new FormatException("The value provided for the first ratio portion is not valid.");
            }
    
            public int Subtract(int first, int second)
            {
                if (first == 0)
                    throw new FormatException("The value provided for the amount to pledge must be a positive number.");
    
                return first - second;
            }
        }
    }
  7. To execute the project, on the main menu, click Debug -> Start Without Debugging
  8. In the Amount to Allocate text box, type a currency number such as 5000
  9. In the Ratio text box, type 0
  10. Click the Allocate button

    Throwing an Exception

  11. Click Continue
  12. Type a relatively small number in the In the Ratio text box, such as 5
  13. Click the Allocate button

    Throwing an Exception

  14. Close the browser and return to your programming environment

Exceptions and Properties

If you create a non-automatic property that processes some data and returns a valid result, if there is a possibility that something could go wrong in the calculation, you can make the property throw an exception. You can perform some procesing in the write clause of the property. In that clause, you can throw an exception. Here is an example:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace ASPNETMVC01.App_Code
{
    public class WorkDay
    {
        private double tw;

        public WorkDay(double time)
        {
            tw = time;
        }

        public double TimeWorked
        {
            get
            {
                return tw;
            }
            set
            {
                if (tw > 24)
                    throw new FormatException("Nobody can work more than 24 hours in one day.");

                tw = value;
            }
        }
    }
}

Or you can handle the exception in the read clause.

Topics on Handling Exceptions

Catching Various Exceptions

In the above examples, when we anticipated some type of problem, we instructed the compiler to use our default catch section. We left it up to the compiler to find out when there was a problem and we provided a catch section to deal with it. A secttion of code with numerous or complex operations and requests can also produce different types of errors. You should be able to face different problems and deal with them individually, each by its own kind. To do this, you can create different catch sections, each made for a particular error. The formula to follow is:

try {
	// Code to Try
}
catch(Arg1)
{
	// One Exception
}
catch(Arg2)
{
	// Another Exception
}

The compiler would proceed from top-down:

  1. Following the normal flow of the program, the compiler enters the try block
  2. If no exception occurs in the try block, the rest of the try block executes.
    If an exception occurs in the try block, the compiler registers the type of error that occurred. If there is a throw line, the compiler registers it also:
    1. The compiler gets out of the try section
    2. The compiler examines the first catch section. If the first catch clause matches the thrown error, that catch section executes and the exception handling routine may end. If the first catch doesn't match the thrown error, the compiler proceeds with the next catch clause
    3. The compiler checks the next match, if any, and proceeds as in the first catch. This continues until the compiler finds a catch clause that matches the thrown error
    4. If one of the catch clauses matches the thrown error, its body executes. If no catch clause matches the thrown error, the compiler calls the Exception class and uses the default message

Multiple catch clauses are written if or when a try block is expected to throw different types of errors. For example, in our calculator, we want to consider only the addition, the subtraction, the multiplication, and the division. It is also likely that the user may type one or two invalid numbers. This leads us to know that our project can produce at least two types of errors. Based on this, we can address them using two catch clauses as follows:

@{
    string message = "";
    double result = 0.00;
    string oper = "";
    double number1 = 0.00, number2 = 0.00;


    if (IsPost)
    {
        try
        {
            number1 = double.Parse(Request["txtNumber1"]);
            number2 = double.Parse(Request["txtNumber2"]);
            oper = Request["txtOperator"];

            if( (oper != "+") && (oper != "-") && (oper != "*") && (oper != "/") )
            {
                throw new Exception(oper);
            }

            switch (oper)
            {
                case "+":
                    result = number1 + number2;
                    break;
                case "-":
                    result = number1 - number2;
                    break;
                case "*":
                    result = number1 * number2;
                    break;
                case "/":
                    result = number1 / number2;
                    break;
                default:
                    message = "Bad Operation";
                    break;
            }

        }
        catch (FormatException)
        {
            message = "You type an invalid number. Please correct it";
        }
        catch (Exception ex)
        {
            message = "Operation Error: " + ex.Message + " is not a valid operator";
        }
    }
}

@using (Html.BeginForm())
{
    <table>
        <tr>
            <td>Number 1:</td>
            <td>@Html.TextBox("txtNumber1", @number1)</td>
        </tr>
        <tr>
            <td>Operator:</td>
            <td>@Html.TextBox("txtOperator", @oper)</td>
        </tr>
        <tr>
            <td>Number 2:</td>
            <td>@Html.TextBox("txtNumber2", @number2)</td>
        </tr>
        <tr>
            <td>&nbsp;</td>
            <td><input type="submit" name="btnCalculate" value="Calculate" /></td>
        </tr>
        <tr>
            <td>Result:</td>
            <td>@Html.TextBox("txtResult", @result)</td>
        </tr>
    </table>

    <p>@message</p>
}

Calculator 1: Exception Handling

This webpage works fine as long as the visitor types two valid numbers and a valid arithmetic operator. Anything else, such an invalid number or an unexpected operator would cause an error:

Exception

Obviously various bad things could happen when this webpage is used. Imagine that the user wants to perform a division. You need to tell the webpage what to do if the user enters the denominator as 0 (or 0.00). If this happens, one of the options you should consider is to display a message and get out. Fortunately, the .NET Framework provides the DivideByZeroException class to which we were introduced in the previous lesson to deal with an exception caused by division by zero. As done with the message passed to the Exception class, you can compose your own message and pass it to the DivideByZeroException(string message) constructor.

Exception Filters

Sometimes you will have different controls that may throw the same type of exception. The problem is that these controls may present the same error message. For example, if you have more than two text boxes that expect numeric values, if a valid value is not provided, each of the control would throw a FormatException exception. The problem is that when one of those controls throws the exception, you may need a way to either know what control threw the exception or what exception was thrown.

Filtering an exception consists of specifying a criterion by which a particular exception, among others, would be selected. The C# language provides a mechanism that allows you to get more details about an exception. To start, you must use a technique that would apply to each particular error. One way to do this is to use the throw keyword to create a custom message when an exception is thrown. To help you select an exception, the C# language provides the when keyword. The formular to use it is:

try
{
	. . .
}
catch(exception-parameter) when (condition)
{
	. . .
}

In the catch clause, pass an exception-parameter as we have done so far. This is followed by the when keyword that is used as in an if() conditional statement. In its parentheses, provide a logical expression that can evalue to true or false. If that expression is true, the body of the catch clause would execute.

Nesting an Exception

You can create an exception inside of another. This is referred to as nesting an exception. This is done by applying the same techniques we used to nest conditional statements. This means that you can write an exception that depends on, and is subject to, another exception. To nest an exception, write a try block in the body of the parent exception. The nested try block must be followed by its own catch clause(s). To effectively handle the exception(s), make sure you include an appropriate throw in the try block. Here is an example:

@{
    string message = "";
    double result = 0.00;
    string oper = "";
    double number1 = 0.00, number2 = 0.00;


    if (IsPost)
    {
        try
        {
            number1 = double.Parse(Request["txtNumber1"]);
            number2 = double.Parse(Request["txtNumber2"]);
            oper = Request["txtOperator"];

            if( (oper != "+") && (oper != "-") && (oper != "*") && (oper != "/") )
            {
                throw new Exception(oper);
            }

            switch (oper)
            {
                case "+":
                    result = number1 + number2;
                    break;
                case "-":
                    result = number1 - number2;
                    break;
                case "*":
                    result = number1 * number2;
                    break;
                case "/":
                    try
                    {
                        if (number2 == 0)
                        {
                            throw new DivideByZeroException("Division by zero is not allowed");
                        }

                        result = number1 / number2;
                    }
                    catch (DivideByZeroException ex)
                    {
                        message = ex.Message;
                    }
                    break;
                default:
                    message = "Bad Operation";
                    break;
            }
        }
        catch (FormatException)
        {
            message = "You type an invalid number. Please correct it";
        }
        catch (Exception ex)
        {
            message = "Operation Error: " + ex.Message + " is not a valid operator";
        }
    }
}

Practical LearningPractical Learning: Ending the Lesson


Previous Copyright © 2001-2019, FunctionX Next