Solution - Challenge Postal Calculator Helper Methods

Tutorial Series: Free C# Fundamentals via ASP.NET Web Apps

Previous Article  |  Next Article


Get GitHub Code

This is the solution for the challenge called ChallengePostalCalculatorHelperMethods, the first of two challenges for the recent lessons covering the creation of helper methods. Because of the nature of this challenge, there are many different ways to solve it. If you created a program that functions according to the challenge's requirements, then you successfully completed the challenge; regardless of whether or not it matches this solution. This is simply one of many possible solutions, not necessarily even the best. That being said, here is one solution for this challenge.

Step 1: Create the Default.aspx Page

As per the first non-functional requirement of this challenge, create a new project and call it ChallengePostalCalculatorHelperMethods. Then, add the Default.aspx page as we've done throughout this course. Add the following text and server controls to the page:


Default


  1. widthTextBox
  2. heightTextBox
  3. lengthTextBox
  4. groundRadioButton
  5. airRadioButton
  6. nextDayRadioButton
  7. resultLabel

Next, add all three radioButtons to a common group called methodGroup.

Step 2: Create EventHandlers

In the requirements.txt document, the instruction is to produce a result on the screen as soon as the minimum amount of information is input. In order to do this, we'll need to post back to the server every time an input is changed. We'll do this by setting the AutoPostBack behavior. To do this, navigate to the properties window on a selected server control, and under Behavior, double click AutoPostBack:


AutoPostBack


Once this is completed for each of the server controls, we also need to create an EventHandler for when either the text is changed, or when a radioButton is selected. To do this, click on the lightning bolt in the properties window and double-click on either TextChanged (for TextBox) or CheckedChanged (for radioButton) under Action:


CheckChanged


Step 3: Generating your First Method

While there are different methods (EventHandlers) for each server control, they will all be calling a single helper method that will check to see if sufficient user input is available to perform a calculation. Underneath your last generated method, create a new private void method called called performChanged(). We'll worry about filling in the code for the method later.

Tip:

Another way to create a method is to generate a method stub. To do this, go in to one of the existing methods and type in performChanged(). Notice that there is a red squiggly, indicating that no such reference exists. If you hover your mouse over that line of code, however, you'll see a lightbulb icon called quick actions, and if you click on that you'll be able to generate a method stub:


GenerateMethod


Note: Inside of the generated method, there is a line that throws a new exception:


Exception


We'll cover exceptions and what they do in upcoming lessons in more detail. For now, know that it keeps Visual Studio from having a compilation error if you forget to fill in the method you generated.

Inside each of the EventHandlers, call the new performChanged() method.

Step 4: Creating your Code Outline

A useful way of creating code is to map out what the program needs to accomplish, in common terms, before writing your program. In this case, we need to:

  1. Check that there is sufficient data to perform a calculation
  2. Calculate the volume of the shipping container
  3. Determine the multiplier
  4. Calculate the total cost
  5. Display the cost to the user

What we can do now is generate methods to accomplish each of these tasks, then address each of them once they're all in place.

To begin with, we need to check that there are values in the TextBoxes and one of the CheckBoxes before performing our calculation. To do this, let's create a conditional check inside performChanged() that does the following:


performChanged


Note: This valuesExist() method has yet to be created, but we are referencing it here for the sake of having our logic in place. We know that whenever a value has changed and performChanged() is called, we need to check if valuesExist(). If they do not, then we'll cancel the operation.

Let's continue by generating a method stub for the valuesExist() method. Notice how Visual Studio already knows that the method type should be bool, since it was generated from within a conditional check:


valuesExistBool


We won't fill in the code logic for the methods until we've finished generating them. Next, let's create a method for calculating the volume based on the input from the users. This is a great opportunity to use an output parameter in our methods.

Inside performChanged(), create another conditional statement to check if the input from the users can be used to get a volume:


ifTryGetVolume


This tryGetVolume() method will eventually evaluate whether or not the text can be parsed to an int. It will return true if it can, and false if it cannot. If it returns false, then we will return out of the performChanged() method. Notice it also has an output parameter that corresponds to the volume variable created above it. Now, generate a method stub for the tryGetVolume() method, and see the results:


tryGetVolumeStub


See how it not only recognized that the method was a bool, but also that it has an integer output called volume.

Next, we need to determine what the postage multiplier will be based on the radioButton selected by the user. In order to do this, create a new double called postageMultiplier and set it equal to a new method called getPostageMultiplier() and generate a stub for it:


PostageMultiplier


Next, we'll create a calculation for what the cost will be by multiplying the volume by the postageMultiplier:


Cost


Finally, we'll need to display the cost to the user in the resultLabel. We'll use a String.Format() to accomplish this:


resultLabel


Your performChanged() method should look like this:


performChangedFinal


Step 5: Filling in the Logic

Let's start filling in the code's logic with the valuesExist() method. We'll use two conditional statements to check if none of the radioButtons are checked, or if one of the two required TextBoxes are not filled in. If either of those cases are true, valuesExist() will return false. Otherwise, we'll return true:


valuesExist


Tip:

Remember that the Text.Trim() method evaluates the text after any blank spaces have been removed, or trimmed, from its value. This keeps the calculation from being affected by someone simply pressing the space bar within the text field.

Next, we'll work with the tryGetVolume() method stub we generated. What we need to do is determine if the values the user input can be converted to integers. To do this, we'll create integers for width, height and length, each set to 0. Then, we can use several conditional checks, each checking if(!int.TryParse()) for each for each of the TextBoxes, with the output being set to the appropriate variable (width, height or length). If width or height cannot be parsed, we'll return false. If length cannot be parsed, we will set length equal to 1, because it is an optional value. If all those conditional checks go through, we'll return true:


tryGetVolume


Finally, we need to work with the getPostageMultiplier() method. To do this, we'll create three conditionals to check which radioButton is checked, and return the appropriate decimal multiplier. If none are selected, we'll return 0:


getPostageMultiplier


Step 6: Test your Code and Refine

Now, save and run your project and see the result:


Test


At this point, your code is fully functional and meets the requirement set out in the challenge. However, we can still make it better. When you think about it, why should we need six different events all calling the exact same method? There is a way around this. What we can do is create a new event called handleChange:


handleChange


Now, you can delete all the EventHandlers that we previously had. What we'll now do is go back into the properties for each server control, and instead of having the event register where it previously did, we can change it to handleChange:


Properties


Save your project and run it. You'll see that it works exactly as it did before, but without the code redundancy we had before.

Tip:

The moral of the story is this: Even though we had six different server controls, they all shared the same method and method signature. When you recognize this, you can simply set the property for handling the event to a common method. This drastically reduces the length and complexity of your code. Whenever you see redundancy throughout your code, you should look for different ways to reduce the complexity.

Conclusion

This completes the solution for ChallengePostalCalculatorHelperMethods. While this solution is rather lengthy, the actual code behind it isn't very complicated. It requires a lot of thinking and creativity, but if you apply the concepts we've learned up until this point, it shouldn't be too difficult. Again, if you achieved the goal but used came up with a different solution, that's fine. In coding, there are many roads to the same destination. Keep up the great work, and keep reviewing for the first Mega Challenge coming up soon.


Related Articles in this Tutorial:

Lesson 1 - Series Introduction

Lesson 2 - Installing Visual Studio 2015

Lesson 3 - Building Your First Web App

Lesson 4 - Understanding What You Just Did

Lesson 5 - Working with Projects in Visual Studio

Lesson 6 - Simple Web Page Formatting in Visual Studio

Challenge 1

Solution 1

Lesson 7 - Variables and Data Types

Lesson 8 - Data Type Conversion

Lesson 9 - Arithmetic Operators

Lesson 10 - C# Syntax Basics

Challenge 2 - ChallengeSimpleCalculator

Solution - ChallengeSimpleCalculator

Lesson 11 - Conditional If Statements

Lesson 12 - The Conditional Ternary Operator

Challenge 3 - ChallengeConditionalRadioButton

Solution - Challenge Conditional RadioButton

Lesson 13 - Comparison and Logical Operators

Lesson 13 Challenge - First Papa Bob's Website

Solution - Challenge First Papa Bob's Website

Lesson 14 - Working with Dates and Times

Lesson 15 - Working With Spans of Time

Lesson 16 - Working with the Calendar Server Control

Challenge 4 - Challenge Days Between Dates

Solution - Challenge Days Between Dates

Lesson 17 - Page_Load and Page.IsPostBack

Lesson 18 - Setting a Break Point and Debugging

Lesson 19 - Formatting Strings

Challenge 5 - Challenge Epic Spies Assignment

Solution - Challenge Epic Spies Assignment

Lesson 20 - Maintaining State with ViewState

Lesson 21 - Storing Values in Arrays

Lesson 22 - Understanding Multidimensional Arrays

Lesson 23 - Changing the Length of an Array

Challenge 6 - Challenge Epic Spies Asset Tracker

Solution - Challenge Epic Spies Asset Tracker

Lesson 24 - Understanding Variable Scope

Lesson 25 - Code Blocks and Nested If Statements

Lesson 26 - Looping with the For Iteration Statement

Challenge 7 - Challenge For Xmen Battle Count

Solution - Challenge For Xmen Battle Count

Lesson 27 - Looping with the while() & do...while() Iteration Statements

Lesson 28 - Creating and Calling Simple Helper Methods

Lesson 29 - Creating Methods with Input Parameters

Lesson 30 - Returning Values from Methods

Lesson 31 - Creating Overloaded Methods

Lesson 32 - Creating Optional Parameters

Lesson 33 - Creating Names Parameters

Lesson 34 - Creating Methods with Output Parameters

Challenge 8 - Challenge Postal Calculator Helper Methods

Solution - Challenge Postal Calculator Helper Methods

Mega Challenge Casino

Solution - Mega Challenge Casino

Lesson 35 - Manipulating Strings

Challenge 9 - Phun With Strings

Solution - Challenge Phun With Strings

Lesson 36 - Introduction to Classes and Objects

Challenge - Hero Monster Classes Part 1

Solution - Hero Monster Classes Part 1

Challenge - Hero Monster Classes Part 2

Solution - Challenge Hero Monster Classes Part 2

Lesson 37 - Creating Class Files Creating Cohesive Classes and Code Navigation

Lesson 38 - Understanding Object References and Object Lifetime

Lesson 39 - Understanding the .NET Framework and Compilation

Lesson 40 - Namespaces and Using Directives

Lesson 41 - Creating Class Libraries and Adding References to Assemblies

Lesson 42 - Accessibility Modifiers, Fields and Properties

Lesson 43 - Creating Constructor Methods

Lesson 44 - Naming Conventions for Identifiers

Lesson 45 - Static vs Instance Members

Challenge 10 - Challenge Simple Darts

Solution - Challenge Simple Darts

Lesson 46 - Working with the List Collection

Lesson 47 - Object Initializers

Lesson 48 - Collection Initializers

Lesson 49 - Working with the Dictionary Collection

Lesson 50 - Looping with the foreach Iteration Statement

Lesson 51 - Implicitly-Typed Variables with the var Keyword

Challenge 11 - Challenge Student Courses

Solution - Challenge Student Courses

Mega Challenge War

Solution - Mega Challenge War

Lesson 52 - Creating GUIDs

Lesson 53 - Working with Enumerations

Lesson 54 - Understanding the switch() Statement

Lesson 55 - First Pass at the Separation of Concerns Principle

Lesson 56 - Understanding Exception Handling

Lesson 57 - Understanding Global Exception Handling

Lesson 58 - Understanding Custom Exceptions

Lesson 59 - Creating a Database in Visual Studio

Lesson 60 - Creating an Entity Data Model

Lesson 61 - Displaying the DbSet Result in an ASP.NET GridView

Lesson 62 - Implementing a Button Command in a GridView

Lesson 63 - Using a Tools-Centric Approach to Building a Database Application

Lesson 64 - Using a Maintenance-Driven Approach to Building a Database Application

Lesson 65 - Creating a New Instance of an Entity and Persisting it to the Database

Lesson 66 - Package Management with NuGet

Lesson 67 - NuGet No-Commit Workflow

Lesson 68 - Introduction the Twitter Bootstrap CSS Framework

Lesson 69 - Mapping Enum Types to Entity Properties in the Framework Designer

Lesson 70 - Deploying the App to Microsoft Azure Web Services Web Apps

Papa Bob's Mega Challenge

Papa Bob's Mega Solution Part 1 - Setting up the Solution

Papa Bob's Mega Solution Part 2 - Adding an Order to the Database

Papa Bob's Mega Solution Part 3 - Passing an Order from the Presentation Layer

Papa Bob's Mega Solution Part 4 - Creating the Order Form

Papa Bob's Mega Solution Part 5 - Adding Enums

Papa Bob's Mega Solution Part 6 - Creating an Order with Validation

Papa Bob's Mega Solution Part 7 - Calculating the Order Price

Papa Bob's Mega Solution Part 8 - Displaying the Price to the User

Papa Bob's Mega Solution Part 9 - Creating the Order Management Page


Comments

Please login or register to add a comment