Techniques of Dealing with Exceptions
Techniques of Dealing with Exceptions
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> </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>
}
Practical Learning: Introducing Exception Handling
@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; } }
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; }
<!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">© @DateTime.Now.Year :: Organization for Fundraising Events</h4> </footer> </div> @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/bootstrap") @RenderSection("scripts", required: false) </body> </html>
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; } } }
@{ 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't take a chance. Don'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>
@{ 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> </p> <p> </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>
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 Learning: Throwing an Exception from a Method
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;
}
}
}
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; } } }
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:
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> </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>
}
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:
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 Learning: Ending the Lesson
|
||
Previous | Copyright © 2001-2019, FunctionX | Next |
|