You are on page 1of 293

ASP.

NET for Web Developers


Amelia Garripoli

Version 1.1, September 25, 2016


Table of Contents
License . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  1
Dedication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  2
Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  3
1. Web Development . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  5
1.1. What the user sees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  5
1.2. What you write . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  5
1.3. Where your code sits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  6
1.4. Microsoft’s Alphabet Soup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  6
1.5. Pobody’s nerfect . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  8
1.6. Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  10
1.7. Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  21
1.8. Exercises. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  21
1.9. Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  21
2. Web Pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  23
2.1. ASP.NET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  23
2.2. Visual Studio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  24
2.3. Web Pages Layouts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  28
2.4. Layout Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  28
2.5. Making Layout Setting DRY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  29
2.6. Web Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  30
2.7. Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  34
2.8. Exercises. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  34
2.9. Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  35
3. Razor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  36
3.1. Razor’s Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  37
3.2. An example: a simple calculator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  41
3.3. Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  43
3.4. Exercises. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  43
3.5. Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  44
4. C# Variables and Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  45
4.1. Declaring variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  45
4.2. Assignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  46
4.3. State diagrams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  47
4.4. Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  48
4.5. Displaying values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  48
4.6. Data types in C# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  49
4.7. Arithmetic operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  51
4.8. Floating-point numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  53
4.9. String operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  55
4.10. Comparison and Boolean Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  58
4.11. Precedence of operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  58
4.12. Composition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  60
4.13. General operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  61
4.14. Method calls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  61
4.15. Classes and Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  62
4.16. Types of errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  68
4.17. Data types in C# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  70
4.18. Namespaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  73
4.19. Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  74
4.20. Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  74
4.21. Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  77
5. C# Statements, Arrays, and Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  78
5.1. Blocks, Loops, and Branches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  78
5.2. Algorithm Development . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  87
5.3. The while and do..while Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  97
5.4. The while statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  98
5.5. The for Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  104
5.6. The if Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  115
5.7. The switch Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  124
5.8. Variables and Scope . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  130
5.9. Exception Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  130
5.10. Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  134
5.11. When good code has bugs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  148
5.12. There’s more … . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  148
5.13. Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  148
5.14. Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  148
5.15. Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  152
6. Deploying Web Page Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  153
6.1. Choosing a service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  153
6.2. Platform as a Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  153
6.3. Deploying on AppHarbor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  154
6.4. Deployed on AppHarbor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  158
6.5. Access a Deployed Application on AppHarbor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  160
6.6. Got Database? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  160
6.7. Your Second Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  161
6.8. Summary of Deployment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  162
6.9. Removing an Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  162
6.10. Keeping it Free . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  164
6.11. Debugging on the Internet. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  164
6.12. Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  170
6.13. Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  170
6.14. Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  171
7. C# Methods, Classes, and Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  172
7.1. Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  172
7.2. Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  182
7.3. Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  190
7.4. Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  195
7.5. Overloading and Overriding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  197
7.6. Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  200
7.7. The ASP.NET and .NET Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  201
7.8. There’s more … . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  202
7.9. Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  202
7.10. Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  202
7.11. Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  206
8. Collections and Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  207
8.1. Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  207
8.2. Database Access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  210
8.3. Application Database Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  229
8.4. File Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  230
8.5. Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  237
8.6. Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  238
8.7. Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  240
9. Security and Accessibility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  241
9.1. Injection Attacks. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  241
9.2. Authentication and Session Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  242
9.3. Cross-site scripting. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  255
9.4. Security Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  257
9.5. Sensitive Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  258
9.6. Check at every level. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  258
9.7. Updating the .NET Framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  259
9.8. Redirects and Forwards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  259
9.9. Accessibility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  259
9.10. Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  261
9.11. Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  261
9.12. Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  262
10. Validation and Helpers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  263
10.1. Input values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  263
10.2. Check if user’s input matches validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  267
10.3. Check if all validation tests pass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  267
10.4. Display validation errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  268
10.5. Client-side validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  269
10.6. HTML5 validation tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  272
10.7. Helpers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  274
10.8. Other helpers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  277
10.9. Other HTTP request data sources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  277
10.10. Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  279
10.11. Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  280
10.12. Lab . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  280
11. ASP.NET MVC 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  281
11.1. Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  281
Addendum A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  283
Razor Quick-Reference. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  283
Addendum B . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  286
C# Quick Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  286
Colophon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  287
Bibliography . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  288
License
© Copyright 2016, Amelia Read Garripoli

Amelia Read Garripoli (agarripoli@olympic.edu)


Information Systems
Department of Business & Technology
Olympic College
Bremerton, WA 98337

Like those that came before it, this book can be distributed in unmodified form for non-commercial
purposes. Modified versions can be made and distributed for non-commercial purposes provided
they are distributed under the same license as the original. More specifically: This work is licensed
under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 License. To view a copy of
this license, visit http://creativecommons.org/licenses/by-nc-sa/4.0/. Other uses require permission
from the author.

The website for this book is: http://faculty.olympic.edu/agarripoli/New2ASP .

The source of this book and all sample code can be downloaded from
https://github.com/argoc/ASP.NET-for-Web-Developers/archive/master.zip

This book is provided “as-is”. It may contain errors of spelling, grammar, or semantics. Information
and views expressed in this document may change without notice. You bear the risk of using it.
Examples depicted herein are provided for illustration only and are fictitious.

This book references websites from external sources not under my control. The web addresses may
change, the content may change, and in particular they may have an invasive privacy policy. It is
your responsibility to be aware of this and to act accordingly. You use the links in this text at your
own risk.

Use shall constitute acceptance of the terms listed.

Microsoft, Windows, Visual Studio, IIS, and ASP.NET are either registered trademarks or
trademarks of Microsoft Corporation in the United States and/or other countries.

1
Dedication
This book is dedicated to my family for not minding me doing this project while on summer break;
to my peers at Olympic College, for giving me this opportunity; and to all the developers I have
enjoyed working with in the past — isn’t it crazy how the internet has taken over every facet of
what we do?

2
Preface
I wrote this book over my 2016 summer break, off-contract from my position as tenure-track
Information Systems Faculty at Olympic College, using only personal resources. My goal was to
make the Introduction to ASP.NET class something approachable without requiring a heavy math
background or a career in software development. It assumes that you have had some programming
courses and written small (100-line or more) programs successfully in an object-oriented language
(such as Java or JavaScript); put together multi-page websites in HTML and CSS succcessfully; have
used SQL in database systems; and desire to learn the ASP.NET environment.

Due to time constraints, I’ve made heavy use of excellent OER resources written for Java; C# and
Java share many similarities. That said, this could not have been accomplished without the
excellent Microsoft Developer’s Network resources at http://www.asp.net/ and
http://www.msdn.com/

This book will be covering Razor, C#, and the ASP.NET library. It assumes you have already taken
these Olympic College courses:

• CIS 155, Web Development I. This course covers HTML and CSS.

If you need a refresher on HTML, I recommend the Microsoft Academy course, HTML5 & CSS3
Fundamentals: Development for Absolute Beginners

• CIS 210, Introduction to SQL. This course covers SQL.

If you need a refresher on SQL, I recommend SQLZoo’s Tutorial or Learn Code The Hard Way’s
Learn SQL The Hard Way.

• Either CIS 255, Web Development II, which covers programming in JavaScript, or CIS 142, Java
Programming I, which covers OO programming in Java.

If you need a refresher on programming, I recommend finding a "learn to program" course on


JavaScript, Java or C# that includes Object Orientation (OO) in its description; look on Udemy,
EdX, Coursera, or other platform. (If you have a specific one you recommend, let me know).

It’s always a good idea to know the history behind what you are learning, so here is a short look
into the history behind this technology:

ASP.NET was first released in 2002 by Microsoft as a web application framework on top of the .NET
platform (first released in 2000), their common framework and engine for several programming
languages. It provides a library and framework to support web development, and replaced the
earlier Active Server Pages tehnology developed by Microsoft.

Razor was developed in 2010 by Andrew Nurse (http://vibrantcode.com/) for Microsoft it replaces
Active Server Pages' (.aspx’s) inlining syntax with a simpler form that has been embraced by the
Microsoft developer community. It streamlines the transition between HTML and code.

C# was developed in 1999 by Microsoft. Who designed paticular features we do not know, but the
team lead was Anders Hejlsberg. If you know Java, some of the changes may seem silly

3
(IndexOutOfBoundsException instead of ArrayIndexOutOfBoundsException, for example) but some
changes are helpful — the foreach loop in C# resulted in the definition of a similar structure in Java,
after C# did it. C# also introduced many helpful shorthands in defining classes, so properties really
are properties, and not directly tied to class instance variables. Was C# a response to Java’s license
requiring no changes to Java? we will never know, but its lead developer claims that C# is "not a
Java clone" but is more related to C++.

For more background, see

• https://en.wikipedia.org/wiki/.NET_Framework

• https://en.wikipedia.org/wiki/ASP.NET

• https://en.wikipedia.org/wiki/ASP.NET_Razor

• https://en.wikipedia.org/wiki/C_Sharp_(programming_language)

4
Chapter 1. Web Development
Welcome to ASP.NET for Web Developers. In this text we cover the basics of building full-stack
websites in the ASP.NET environment. A full-stack website has three layers: the client browser
(Users), the Web Server, and a backing database (BD). The clients share that backing database, but
each have their own personal view of it, provided to them by the web server. The users' only way to
communicate is through the HTTP protocol, via web pages and asynchronous partial-page AJAX
requests.

Figure 1. Website Server Architecture CC-BY Ph.HENCHES

1.1. What the user sees


All that the user can see on their side is HTML, rendered by CSS, and supplemented with JavaScript.
Every so often, something they do (including the passage of time) triggers a trip back to the web
server that can alter the contents on the page or move them to another page. The web server may
in turn want to access the backing datastore, typically a database or file system.

Great web design without functionality is like a sports car with no engine.

— Paul Cookson

1.2. What you write


When you develop a website or web application in the ASP.NET environment, you write HTML,
JavaScript, and CSS, and then you add server-side coding and databases using Razor to embed C# in
your page/application and call out to your own C# classes and those of the ASP.NET library. The
database access can be done in several ways; we will be executing SQL classes using the ASP.NET
SQLClient. Microsoft also provides LINQ, with provides both a library and another language for
database access. The LINQ language is like SQL — similar to how C# is like Java.

You write your application code in Visual Studio, and when it is run within Visual Studio, it runs in
a local web server using IIS Express. IIS is Internet Information Services, Microsoft’s web server; IIS
Express is a lightweight version for development use. In deployed mode, your application would be
packaged and deployed in Internet Information Services (IIS) for Windows® Server or some other

5
web server supporting ASP.NET.

Web applications can be a bit more disorganized than a typical computer program — web sites turn
into spaghetti really easily. So it is best to do some design up front, with a wire-frame diagram, and
lay out that design in your development environment — use directories to separate portions of your
code. You will find that the Visual Studio IDE provides some framework for you, separating
different types of files into different directories. We’ll walk through the Visual Studio organization
in the next chapter.

1.3. Where your code sits


The code you write is meant to live on a file system that is managed by a web server. When a
person puts a URL in their browser (or clicks on a search result linking to a URL), that URL is fed to
a web server. URLs identify the target machine and then the target page on that machine. The web
server takes the target page as input and locates the data to return. It doesn’t actually have to go
directly to a file, but in our case it will.

Our users' URLs will map to pages in our web sites. The web server will find the page, and then it
will run the C# code on that page and return an HTML page free of Razor and C# to the requesting
browser. That means all of your C# code runs on the web server; only JavaScript code runs on the
browser. You will need to keep this in mind as you develop your web site: the user’s only
interaction with your web site is via HTML, that is, links being clicked, forms being submitted, and
JavaScript requests being issued. Your only way to communicate back is to provide HTML that is
rendered in the user’s browser. Keep that in mind, because it is both very limiting and very freeing,
like trying to rent an apartment when you have a cat. Some things aren’t going to be feasible, or
require solutions unlike those you use in traditional stand-alone applications.

1.4. Microsoft’s Alphabet Soup


.NET, ASP.NET, CLR, MSIL, MVC — there are many different names behind the Microsoft
technologies. Let’s take a look at how they fit together and where we will be working in this text.

6
.NET stands for "dot-net". The N-E-T is not an acronym. It’s meant to imply network,
TIP internet — those netty things that drive computers. All of our other letter-words are
acronyms.

The .NET framework is the underpinning of all managed code that runs on a Windows machine. If
you write unmanaged code, you are writing raw code that runs against the operating system
unchecked. Managed code is run inside the Common Language Runtime (CLR), where there are
services for memory management, type safety, thread management, and other features to provide
additional security and robustness to your code. The CLR requires that your code be compiled
down to Microsoft Intermediate Language (MSIL). It has a just-in-time compiler within it that
compiles that code down to machine code. Microsoft provides compilers (such as those within
Visual Studio) that will compile C#, Visual Basic, F#, C++, and other languages to MSIL to be run in
the CLR.

The .NET Framework class library provides a large library of classes that can be used by any
language compiled to MSIL. This includes basic type services such as string manipulation, file
services, database access (often referred to separately as ADO.NET), and collection types. There are
also a variety of environments provided in the .NET Framework for developing GUI
applications — we won’t be looking into those in this course, as our focus is web applications.

For Web support, ASP.NET provides additional libraries and classes to write richly-functional web

7
sites. Best practices for this, and emerging web technologies, has resulted in 5 different ASP.NET
technologies. They share a common core set of classes for HTTP support on the server side, but
provide different envirnoments for developing.

• Web Forms provides a very GUI-like experience for users, with widgets on the web page that
interact with the server side. This was the first ASP.NET technology and is in wide use. However,
it "breaks" several key philosophies in web-site development, and so has been overshadowed by
MVC. ASP.NET provides the widgets and the framework for supporting their execution. If you
see a URL ending in .aspx, it is using Web Forms.

• Web Pages is a very light-weight framework providing direct hooks between web page content
and the server. It uses Razor as a templating language to embed C# in HTML pages. ASP.NET
provides a rich set of Helpers and its core functionality to enable rapid development. Web
Pages' light-weight ness means it doesn’t tend to scale to large web-sites. For that, developers
move to MVC. If you see a web page ending in .cshtml, it is using Web Pages.

• MVC is Microsoft’s version of the Model-View-Controller design pattern done with C# and Razor.
It provides a rich environment for developing web applications in that pattern, as well as rich
add-ons such as the Entity Framework for automatic database migration and object-relational
mapping. MVC web pages typically are 'just words', with no file extension (on disk, your web
pages end in .cshtml, but MVC includes a rich routing engine that maps names to web pages).

• Web API is a way to develop not a web site, but a web service. It relies on the four HTTP verbs
(GET, POST, PUT, DELETE) to provide those services. This makes your URL available to service a
wider variety of requests, not just web page requests. Microsoft has been folding this technology
into MVC, as web sites often want to provide services as well, such as the "APIs" we see that let
you put Paypal checkout buttons on boutique websites.

• Signal R provides a web sockets experience, where client and server communicate
bidirectionally. It uses web sockets in modern browsers, and provides fall-back support in older
browsers. This lets servers push information to clients without a prior client request, useful in
situations such as auction sites and near-real-time information sharing.

In this text we will be exploring Web Pages. This is a good entry point for programmers learning C#
from another language, giving you time to play with the language in the small before entering the
much more rigorous MVC environment.

1.5. Pobody’s nerfect


Once you start coding you will discover it’s hard to write perfect code. You will have to isolate and
repair errors in your code to make it work correctly; we call this debugging.

8
Figure 2. An early computer bug (Public Domain; work of a federal government employee)

Bill Burke’s journal entry on September 9, 1947 captures an early use of the term bug for a problem
in a computer - in this case a real bug, a moth in a relay.

Debugging websites can be more challenging than your typical program, since the error can occur
at several levels: database, server-side code, and client-side code. Each has their own software
environment and code you’ve written for them.

The cause of an error can be syntax errors, runtime errors, or semantic errors.

Compilers typically catch syntax errors, when you mistype a keyword or variable name. Runtime
errors occur when you run out of memory or access memory incorrectly. Semantic errors are the
trickiest to catch and may not be apparent, as they occur when your program simply doesn’t do the
right thing. For example, your program runs without errors, but does not implement the requested
behavior.

Just like written English, where Word cannot catch a "word" error that is not a spelling error, you
may use the wrong variable name - when it doesn’t match up to any variable, the compiler catches
it; but when it matches the wrong variable, the compiler cannot help you.

It can be frustrating to work through any of these. You may not see the syntax error, and the
message provided by the compiler may misdirect you. Runtime errors can be hard to isolate, and
may be caused by a different part of your code executed long before the error occurred. Semantic
errors can be a simple oversight, forgetting a requirement. These can have the most serious
repercussions, so it is always a good idea to double-check requirements once your code is complete.

One of the most important skills to develop as a programmer is debugging; the ability to track down
the source of an issue and resolve it appropriately. It can be frustrating, but it is always necessary. A
typical developer’s first job is to take on existing code and "maintain" it. Don’t fool
yourself — maintain is another word for "debug". Very few programs are out there that are
completely bug-free. Even long-time code has issues. See, for example, the Heartbleed bug in

9
OpenSSL.

When you have a bug, you need to be a detective. The behavior you see is a clue. You need to
unwind the clues to discover the root cause and fix it there.

1.6. Debugging
based on material from Think Python and Think Java

I realize you do not yet know C#, Razor, and ASP.NET; however, the advice here works for any
environment; so compare these ideas to the development work you have already done and see how
they are applicable there. Review this section as you learn more about ASP.NET to fit it into what
you learn about C# and Razor along the way.

Different kinds of errors can occur in a program, and it is useful to distinguish among them in
order to track them down more quickly:

• Syntax errors are produced by HTML, CSS, JavaScript, Razor, and C# when Visual Studio first
encounters them. If you are running "on the wire", without Visual Studio, then they are detected
at the first piece of software to handle them. HTML, CSS, and JavaScript syntax errors may not
be detected until the browser sees them; most browsers try to recover gracefully, but may also
output error messages or bad pages when handed syntactically incorrect HTML, CSS, or
JavaScript. Razor and C# syntax errors are detected at compile time (C#) or interpretation time
(Razor). It is the web server that interprets Razor and turns it into HTML for the client to
display. Syntax errors indicatye that there is something wrong with the syntax of the program.
Example: Omitting the semicolon at the end of a C# statement yields an error unexpected
keyword when the next keyword is found at the start of the next statement.

• Runtime errors are produced by the interpreter if something goes wrong while the program is
running. Most runtime error messages include information about where the error occurred and
what methods or functions were executing. Example: An infinite recursion eventually cases the
runtime error StackOverflowException.

• Semantic errors are problems with an application that runs without producing error messages
but doesn’t do the right thing. Example: An expression may not be evaluated in the order you
expect, yielding an incorrect result.

The first step in debugging is to figure out which kind of error you are dealing with. Although the
following sections are organized by error type, some techniques are applicable in more than one
situation.

1.6.1. Syntax errors

Syntax errors are usually easy to fix once you figure out what they are. Unfortunately, the error
messages are often not helpful. The most common messages are SyntaxError: invalid syntax and
SyntaxError: invalid token, neither of which is very informative.

On the other hand, the message does tell you where in the program the problem occurred. Actually,
it tells you where Visual Studio noticed a problem, which is not necessarily where the error is.
Sometimes the error is prior to the location of the error message, often on the preceding line.

10
If you are building the program incrementally, you should have a good idea about where the error
is. It will be in the last line you added.

If you are copying code from a book, start by comparing your code to the book’s code very carefully.
Check every character. At the same time, remember that the book might be wrong, so if you see
something that looks like a syntax error, it might be.

Nevertheless, you might find yourself in one of the following situations. For each situation, we have
some suggestions about how to proceed.

The compiler is spewing error messages.

If the compiler reports 100 error messages, that doesn’t mean there are 100 errors in your program.
When the compiler encounters an error, it often gets thrown off-track for a while. It tries to recover
and pick up again after the first error, but sometimes it reports spurious errors.

Only the first error message is truly reliable. We suggest that you only fix one error at a time, and
then recompile the program. You may find that one semicolon or brace “fixes” 100 errors.

I’m getting a weird compiler message, and it won’t go away.

First of all, read the error message carefully. It may be written in terse jargon, but often there is a
carefully hidden kernel of information.

If nothing else, the message will tell you where in the program the problem occurred. Actually, it
tells you where the compiler was when it noticed a problem, which is not necessarily where the
error is. Use the information the compiler gives you as a guideline, but if you don’t see an error
where the compiler is pointing, broaden the search.

Generally the error will be prior to the location of the error message, but there are cases where it
will be somewhere else entirely. For example, if you get an error message at a method invocation,
the actual error may be in the method definition itself.

If you don’t find the error quickly, take a breath and look more broadly at the entire program. Make
sure each file is indented properly; that makes it easier to spot syntax errors.

Here are some ways to avoid the most common syntax errors:

1. Make sure you are not using a HTML, CSS, JavaScript, Razor, or C#, keyword for a variable
name.

2. Check that all parentheses and brackets are balanced and properly nested. All method
definitions should be nested within a class definition. All program statements should be within
a method definition or a Razor code block.

3. Remember that uppercase letters are not the same as lowercase letters.

4. Check for semicolons at the end of statements, but no semicolons after a compound statement’s
curly braces.

5. Make sure that any strings in the code have matching quotation marks. Make sure that you use
double quotes for strings and single quotes for characters in C# and JavaScript code. Make sure
that all quotation marks are "straight quotes", not “curly quotes”. Be careful if you paste in text

11
from another source.

6. If you have multiline strings, make sure you have terminated the string properly. An
unterminated string may cause an invalid token error at the end of your program, or it may
treat the following part of the program as a string until it comes to the next string. In the second
case, it might not produce an error message at all!

7. Make sure that the types in your comparison, assignment, or method invocation statement are
all compatible and convert correctly: pay attention to the type conversions that automatically
occur.

8. For each assignment statement, make sure that the expression on the left is a variable name or
something else that you can assign a value to (like an element of an array).

9. An unclosed opening operator--(, {, <, or [-- makes most languages continue with the next line as
part of the current statement. Generally, an error occurs almost immediately in the next line.

10. Check for the classic = instead of == inside a comparison.

11. Check for object identity versus value comparison (== vs. === in JavaScript).

12. Check the indentation to make sure it lines up the way it is supposed to. The best way to avoid
this problem is to use automatic code formatting that generates consistent indentation.

13. If you have non-ASCII characters in the code (including strings and comments), that might cause
a problem, although most languages usually handle non-ASCII characters. Be careful if you
paste in text from a web page or other source.

If nothing works, move on to the next section…

I can’t get my application to compile no matter what I do.

If Visual Studio says there is an error and you don’t see it, that might be because you and the IDE
are not looking at the same code. Check your development environment to make sure the
application you are editing is the application the IDE is compiling.

This situation is often the result of having multiple copies of the same file. You might be editing one
version of the file, but compiling a different version.

If you are not sure, try putting an obvious and deliberate syntax error right at the beginning of the
program. Now compile again. If the compiler doesn’t find the new error, you are not compiling the
code you are editting.

There are a few likely culprits:

• You edited the file and forgot to save the changes before running it again. Some programming
environments do this for you, but some don’t.

• You changed the name of the file, but you are still running the old name.

• Something in your development environment is configured incorrectly.

If you get stuck and you can’t figure out what is going on, one approach is to start again with a new
program like “Hello, World!”, and make sure you can get a known program to run. Then gradually
add the pieces of the original program to the new one. If you don’t want to restart, then try this
instead…

12
If you have examined the code thoroughly, and you are sure the compiler is compiling the right
source files, it is time for extreme measures: debugging by halves.

• Make a backup of the file you are working on. If you are working on Bob.cs, make a copy called
Bob.cs.old.

• Delete about half the code from Bob.cs. Try compiling again.

• If the program compiles now, you know the error is in the code you deleted. Bring back about
half of what you deleted and repeat.

• If the program still doesn’t compile, the error must be in the code that remains. Delete about
half of the remaining code and repeat.

• Once you have found and fixed the error, start bringing back the code you deleted, a little bit at
a time. This process is ugly, but it goes faster than you might think, and it is very reliable. It
works for other programming languages too!

I did what the compiler told me to do, but it still doesn’t work.

Some error messages come with tidbits of advice, like “class Golfer must be declared abstract. It
does not define int compareTo(java.lang.Object) from interface java.lang.Comparable.” It sounds
like the compiler is telling you to declare Golfer as an abstract class, and if you are reading this
book, you probably don’t know what that is or how to do it.

Fortunately, the compiler is wrong. The solution in this case is to make sure Golfer has a method
called compareTo that takes an Object as a parameter.

Don’t let the compiler lead you by the nose. Error messages give you evidence that something is
wrong, but the remedies they suggest are not always appropriate.

1.6.2. Runtime errors

Once your application is syntactically correct, IIS (the web server) can read it and at least start
running it. What could possibly go wrong?

My application does absolutely nothing.

This problem is most common when your application consists of Razor code blocks does not
actually generate HTML, or does not have a web page target to land on. This may be intentional if
you only plan to import this module to supply classes and methods.

If it is not intentional, make sure there is HTML in the application, and make sure the flow of
execution reaches it (see “Flow of Execution” below).

My application hangs.

If an application stops and seems to be doing nothing, it is “hanging”. Often that means that it is
caught in an infinite loop or infinite recursion.

• If there is a particular loop that you suspect is the problem, add a print statement immediately
before the loop that says “entering the loop” and another immediately after that says “exiting

13
the loop”. Run the program. If you get the first message and not the second, you’ve got an
infinite loop. Go to the “Infinite Loop” section below.

• Most of the time, an infinite recursion will cause the program to run for a while and then
produce a “RuntimeError: Maximum recursion depth exceeded” error. If that happens, go to the
“Infinite Recursion” section below. If you are not getting this error but you suspect there is a
problem with a recursive method or function, you can still use the techniques in the “Infinite
Recursion” section.

• If neither of those steps works, start testing other loops and other recursive functions and
methods.

• If that doesn’t work, then it is possible that you don’t understand the flow of execution in your
program. Go to the “Flow of Execution” section below.

Infinite Loop

If you think you have an infinite loop and you think you know what loop is causing the problem,
add a print statement at the end of the loop that prints the values of the variables in the condition
and the value of the condition.

For example:

while (x > 0 && y < 0) {


  // do something to x
  // do something to y

  <p>x: @x</p>
  <p>y: @y</p>
  <p>condition: @(x > 0 && y < 0)</p>
}

Now when you run the program, you will see three lines of output for each time through the loop.
The last time through the loop, the condition should be false. If the loop keeps going, you will be
able to see the values of x and y, and you might figure out why they are not being updated correctly.

You can also test your program by stepping through it with the Visual Studio debugger and
displaying the values not only of the variables, but also of the boolean expression.

Infinite Recursion

Recursion means that a function or method calls itself.

Most of the time, infinite recursion causes the program to run for a while and then produce a
StackOverflowException error.

If you suspect that a function is causing an infinite recursion, make sure that there is a base case.
There should be some condition that causes the function to return without making a recursive
invocation. If not, you need to rethink the algorithm and identify a base case.

If there is a base case but the program doesn’t seem to be reaching it, add a print statement at the

14
beginning of the function that prints the parameters. Now when you run the program, you will see
a few lines of output every time the function is invoked, and you will see the parameter values. If
the parameters are not moving toward the base case, you will get some ideas about why not.

You can also test your application by stepping through it with the Visual Studio debugger and
displaying the parameter values and the call stack at each invocation of the function.

Flow of Execution

If you are not sure how the flow of execution is moving through your application, add print
statements to the beginning of each function with a message like “entering function foo”, where foo
is the name of the function.

Now when you run the application, it will print a trace of each function as it is invoked.

In the days of IDEs, this type of "print" debugging is becoming old-school. You can use the debugger
to step through your code, line by line, and examine the call stack, the value of parameters,
variables and expressions, and the state of the system environment at each step along the way.
However, in the multi-faceted ASP.NET web application environment, you may find it useful to
include "print"-style debugging by generating information that shows up in your HTML on the
client side to aid in debugging an active web application.

When I run the program I get an exception.

When an exception occurs, IIS displays a message that includes the name of the exception, the line
of the program where the exception occurred, and a “stack trace”. The stack trace includes the
method that was running, the method that invoked it, the method that invoked that one, and so on.
In other words, it traces the sequence of calls that got you to where you are, including the file and
line number where each call occurred. Many of these may be ASP.NET infrastructure methods;
examine the list carefully to locate your files and methods in the list.

In deployed mode, IIS will not display this information, as it would be a security leak to show
information about the internals of your server-side program.

The first step is to examine the place in the program where the error occurred and see if you can
figure out what happened. Here are some common exceptions:

NullReferenceException: You tried to access an instance variable or invoke a method on an object


that is currently null. You should figure out which variable is null and then figure out how it got to
be that way. Remember that when you declare a variable with an array type, its elements are
initially null until you assign a value to them. For example, this code causes a
NullReferenceException:

Point[] array = new Point[5];


<p>array[0].x</p>

IndexOutOfRangeException: The index you are using to access an array is either negative or

15
greater than array.Length - 1. If you can find the site where the problem is, add a print statement
immediately before it to display the value of the index and the length of the array. Is the array the
right size? Is the index the right value?

Now work your way backwards through the program and see where the array and the index come
from. Find the nearest assignment statement and see if it is doing the right thing. If either one is a
parameter, go to the place where the method is invoked and see where the values are coming from.

StackOverflowExeption: See “Infinite recursion”.

FileNotFoundException: Your application didn’t find the file it was looking for. If you are using
Visual Studio, you might have to import the file into the project. Otherwise make sure the file exists
and that the path is correct. This problem depends on your file system, so it can be hard to track
down.

DivideByZeroException: Something went wrong during an arithmetic operation causing a value to


be divided by zero.

NotFiniteNumberException: Something went wrong during an arithmetic operation causing an


operation to occur on or return a NaN (not a number) or infinite value.

OverflowException: Something went wrong during an arithmetic operation causing the result to
be too large for the target variable or property.

The Visual Studio debugger is useful for tracking down exceptions because it allows you to examine
the state of the application immediately before the error. You can read about Debugging in Visual
Studio at https://msdn.microsoft.com/en-us/library/sc65sadd.aspx.

I added so many print statements I get inundated with output.

One of the problems with using print statements for debugging is that you can end up buried in
output. There are two ways to proceed: simplify the output or simplify the application.

To simplify the output, you can remove or comment out print statements that aren’t helping, or
combine them, or format the output so it is easier to understand.

To simplify the application, there are several things you can do. First, scale down the problem the
application is working on. For example, if you are searching a list, search a small list. If the
application takes input from the user, give it the simplest input that causes the problem.

Second, clean up the application. Remove dead code and reorganize the application to make it as
easy to read as possible. For example, if you suspect that the problem is in a deeply nested part of
the application, try rewriting that part with simpler structure. If you suspect a large function, try
splitting it into smaller functions and testing them separately.

Often the process of finding the minimal test case leads you to the bug. If you find that an
application works in one situation but not in another, that gives you a clue about what is going on.

16
If you find that a program works in one situation but not in another, that
gives you a clue about what is going on.

— Allen Downey

Similarly, rewriting a piece of code can help you find subtle bugs. If you make a change that you
think shouldn’t affect the application, and it does, that can tip you off.

1.6.3. Semantic errors

In some ways, semantic errors are the hardest to debug, because IIS and the IDE provide no
information about what is wrong. Only you know what the application is supposed to do.

The first step is to make a connection between the application text and the behavior you are seeing.
You need a hypothesis about what the application is actually doing. One of the things that makes
that hard is that computers run so fast.

You will often wish that you could slow the application down to human speed, and with some
debuggers you can. But the time it takes to insert a few well-placed print statements is often short
compared to setting up the debugger, inserting and removing breakpoints, and “stepping” the
application to where the error is occurring.

1.6.4. My application doesn’t work.

You should ask yourself these questions:

• Is there something the application was supposed to do but which doesn’t seem to be happening?
Find the section of the code that performs that function and make sure it is executing when you
think it should.

• Is something happening that shouldn’t? Find code in your application that performs that
function and see if it is executing when it shouldn’t.

• Is a section of code producing an effect that is not what you expected? Make sure that you
understand the code in question, especially if it involves other files. Read the documentation for
the functions you call. Try them out by writing simple test cases and checking the results. In
order to program, you need a mental model of how applications work. If you write a application
that doesn’t do what you expect, often the problem is not in the application; it’s in your mental
model.

The best way to correct your mental model is to break the application into its components and test
each component independently. Once you find the discrepancy between your model and reality,
you can solve the problem.

Of course, you should be building and testing components as you develop the application. If you
encounter a problem, there should be only a small amount of new code that is not known to be
correct.

17
1.6.5. I’ve got a big hairy expression and it doesn’t do what I expect.

Writing complex expressions is fine as long as they are readable, but they can be hard to debug. It
is often a good idea to break a complex expression into a series of assignments to temporary
variables.

For example:

this.Hands[i].AddCard(this.Hands[this.FindNeighbor(i)].PopCard());

This can be rewritten as:

neighbor = this.FindNeighbor(i);
pickedCard = this.hands[neighbor].PopCard();
this.hands[i].AddCard(pickedCard);

The explicit version is easier to read because the variable names provide additional documentation,
and it is easier to debug because you can check the types of the intermediate variables and display
their values.

Another problem that can occur with big expressions is that the order of evaluation may not be
what you expect. For example, if you are translating the expression x/2 π into C#, you might write:

y = x / 2 * Math.Pi;

That is not correct because multiplication and division have the same precedence and are
evaluated from left to right. So this expression computes x π / 2.

A good way to debug expressions is to add parentheses to make the order of evaluation explicit:

 y = x / (2 * Math.Pi);

Whenever you are not sure of the order of evaluation, use parentheses. Not only will the program
be correct (in the sense of doing what you intended), it will also be more readable for other people
who haven’t memorized the order of operations.

1.6.6. I’ve got a function that doesn’t return what I expect.

If you have a return statement with a complex expression, you don’t have a chance to print the
result before returning. Again, you can use a temporary variable. For example, instead of:

return this.Hands[i].RemoveMatches();

you could write:

18
count = this.Hands[i].RemoveMatches();
return count;

Now you have the opportunity to display the value of count before returning.

1.6.7. I’m really, really stuck and I need help.

First, try getting away from the computer for a few minutes. Computers emit waves that affect the
brain, causing these symptoms:

• Frustration and rage.

• Superstitious beliefs (“the computer hates me”) and magical thinking (“the program only works
when I wear my hat backward”).

• Random walk programming (the attempt to program by writing every possible code bite and
choosing the one that does the right thing).

• Sour grapes (“this program is lame anyway”).

If you suffer from any of these symptoms, get up and go for a walk. When you are calm, think about
the program. What is it doing? What are possible causes of that behavior? When was the last time
you had a working program, and what did you do next?

If you suffer from any of these symptoms, get up and go for a walk. When you are calm, think about
the application.
What is it doing?
What are some possible causes of that behavior?
When was the last time you had a working application, and what did you do next?

Sometimes it just takes time to find a bug. I often find bugs when I am away from the computer and
let my mind wander. Some of the best places to find bugs are buses, parks, and in the gym or on a
walk.

1.6.8. No, I really need help.

It happens. Even the best programmers occasionally get stuck. Sometimes you work on a program
so long that you can’t see the error. You need a fresh pair of eyes.

Before you bring someone else in, make sure you are prepared. Your application should be as
simple as possible, and you should be working on the smallest input that causes the error. You
should have print statements in the appropriate places (and the output they produce should be
comprehensible). You should understand the problem well enough to describe it concisely.

When you bring someone in to help, be sure to give them the information they need:

• What kind of bug is it, syntax, run-time, or semantic?

• If there is an error message, what is it and what part of the program does it indicate?

• What was the last thing you did before this error occurred? What were the last lines of code
that you wrote, or what is the new test case that fails?

19
• What have you tried so far, and what have you learned?

By the time you explain the problem to someone, you might see the answer. This phenomenon is so
common that some people recommend a debugging technique called “rubber ducking”. Here’s how
it works:

Figure 3. Rubber Ducky CC-BY-SA-3.0

1. Buy a standard-issue rubber duck (or, just use the picture above).

2. When you are really stuck on a problem, put the rubber duck on the desk in front of you and
say, “Rubber duck, I am stuck on a problem. Here’s what’s happening…”

3. Explain the problem to the rubber duck.

4. Discover the solution.

5. Thank the rubber duck.

We’re not kidding, it works! See https://en.wikipedia.org/wiki/Rubber_duck_debugging.

1.6.9. I found the bug!

When you find the bug, it is usually obvious how to fix it. But not always. Sometimes what seems to
be a bug is really an indication that you don’t understand the program, or there is an error in your
algorithm. In these cases, you might have to rethink the algorithm, or adjust your mental model.
Take some time away from the computer to think, work through test cases by hand, or draw
diagrams to represent the flow of control.

After you fix the bug, don’t just start in making new errors. Take a minute to think about what kind
of bug it was, why you made the error, how the error manifested itself, and what you could have
done to find it faster. Next time you see something similar, you will be able to find the bug more
quickly. Or even better, you will learn to avoid that type of bug for good.

Remember, the goal is not just to make the application work. The goal is to learn how to make the
application work.

20
1.7. Further Reading
• ASP.NET 4.5 overview

• .NET 4.5 overview

• SignalR, WebAPI, MVC, Web Forms, Web Pages home pages on asp.net

1.8. Exercises
We have only touched on concepts in this chapter, no concrete programming as of yet has been
covered. So our "exercises" are thought exercises to consider as we move into technical aspects of
programming Web Pages.

1. What bugs in your own code have been the most difficult for you to identify and solve? What
tactics will make resolving similar bugs easier for you in the future?

2. When is it appropriate to put code on the server-side versus on the browser-side?

3. What is the difference between a web site and a web application? How are they similar?

4. What is the difference between a mobile application and a web application? How are they
similar?

1.9. Project
Our goal for the course is to develop a full-stack web application: one that uses a database, server-
side code, client-side code, HTML, and CSS. What that may be is wide open. Here are some
suggestions, or perhaps you have a favorite website or app you’d like to pursue:

• Pokemon Go (Ingress). Yes, it’s a mobile app. Consider a cut-down version that you could do
with HTML forms/buttons and your current level of JavaScript skills (don’t, whatever you do,
put this book down and go spend three months learning a JavaScript game engine such as
Phaser). Pokemon Go has alot going on in it — GPS tracking, capturing Pokemon, Gym battles,
shopping, creature growth/repair, starting Gyms, placing Pokestops, and on and on — it’s a
game, a shopping experience, and so much more. Pick some aspect that interests you and run
with it.

• craigslist.org (or if you’d prefer Monster.com or some other job/resume posting board) — a way
to post your things for sale/search and to see what others have posted. Possibly the simplest UI,
but not the simplest UX. Definitely looks a bit dated, but easy to mimic with basic HTML skills.
Or perhaps you want to make a more modern craigslist — and you can name it after yourself,
since Craig did.

• AirBnB — much prettier than craigslist, its focus is on renting rooms; has a full shopping cart
experience. There are many specialty sales sites out there, this is just one possible example.

• Uber (Lyft) — connecting people who are near one another, one giving a ride, one needing a
ride; so not only a service provider and a customer, but also location information.

• Amazon — go big or go home; a shopping experience with lots of organization, suggested items,
wishlists, and on and on. What part of it do you find irresistible and want to explore?

21
• RottenTomatoes (Flixster, AngiesList) — a site that posts in a particular genre (RottenTomatos is
movies, AngiesList is services) and lets users rate them and post comments about them. It
maintains an overall average score of ratings.

• Facebook (or if you’d rather, MySpace, Twitter, Instagram, LinkedIn) — social networking; your
profile and posts make it to your friends. Find people, make friends, have flame wars, start
groups, … more here than meets the eye. What interests you?

• Wikipedia: community-driven information site. Fan wikipedias include comments, not just
community editing with editorial approval.

• Yummly (allrecipes). Sharing recipes, comments and ratings on recipes, sharing photos of
results of cooking them. … could be any sort of sharing site, perhaps sharing photos, parenting
advice, or something else.

• Yelp. Restaurants, their menus and statistics, and customer reviews. (Yelp actually publishes
their data as a huge JSON bundle to see if programmers could come up with interesting new
analyses of it.)

• Google Drive. Users upload files, download, browse. Each user sees only their own files. Then
there’s sharing: you let someone see a file or directory of yours, with either read or delete
access. Google docs takes this even further with multi-user editing, but that’s a bit beyond the
scope of this text.

• The Internet Archive — capturing web pages and making them searchable. This has saved me so
many times, I love it. It also has a way for the original author to get contents removed (not
everyone wants a permanent presence). Make a craigslist wayback machine, that would be
handy (the only one I’ve found costs money and requires a law enforcement certification to
use).

The internet is your oyster — find something you’d like to figure out how to do in ASP.NET Web
Pages. Make sure it has persistent server data, and write up a proposal. Nothing fancy — we’ll get
into prototyping in the next chapter.

Whichever one you pick as your course project, know that you all will be evaluating each others' a
few times in the quarter, providing feedback to your peers on their work to help it improve and to
highlight its strong points.

22
Chapter 2. Web Pages
This text assumes you are already familiar with the client-side languages: HTML, CSS, and
JavaScript.

For an excellent CSS reference, download Smashing Magazine’s cheat sheet at


https://www.smashingmagazine.com/wp-content/uploads/images/css3-cheat-sheet/css3-cheat-
sheet.pdf

For an excellent HTML reference, download Smashing Magazine’s cheat sheet at


https://www.smashingmagazine.com/wp-content/uploads/images/html5-cheat-sheet/html5-cheat-
sheet.pdf

For a JavaScript reference, download both Pam’s JavaScript Cheat Sheet at


http://thewebivore.com/wp-content/uploads/2013/02/PamsJavascriptCheatSheet.pdf and
cheatography’s cheat sheet at https://www.cheatography.com/davechild/cheat-sheets/javascript/pdf/

As none of these are creative commons, I have not included them here.

2.1. ASP.NET
ASP.NET operates on several levels in our environment.

1. It provides the engine on which our C# code runs, the Common Language Runtime. Microsoft
has several languages that compile to the binary format understood by the CLR, which is called
"Microsoft Intermediate Language", or MSIL, pronounced "missile".

2. It provides the infrastucture for understanding and moving around in websites; each page of
your website is actually a Page object in ASP.NET, and as such has properties that you can get
and set, and actions that you can perform. We will see many such useful objects: Page, Session,
HttpRequest, and others as we develop our web applications.

3. It provides a rich set of functionality, often referred to as a library, that you can access as
actions performed by objects. There is quite a bit of code that you will not have to write because
it is already available to you in ASP.NET. For example, "substring" has already been written, and
so has "WebMail.Send", which when configured properly will send an email for you.

The ASP.NET library actions can look like function calls at times. However, when a
NOTE target object is not identified, the current object is implicit. In your .cshtml files, this
is the Page object, identifying the current page being rendered in the system.

ASP.NET runs within Microsoft Internet Information Services, which is the Microsoft web server.
You install your web application within the web server, and when users request pages that reside
in your web application, ISS renders them and provides them to the client.

From within Visual Studio, a local IIS Express engine is started up when you "run" your application,
and automatically loads and starts your web application at its root page, Default.cshtml. Your
machine operates as both client and server, providing both the IIS web server and the web browser
that accesses its contents. We will cover deployment to a separate server later, but keep in mind it

23
means that the local file system cannot be assumed to be where your web application lives.

How does IIS know where to find the root page? It looks in the root directory for a
file with a recognizable extension (.html, .htm, .aspx, .cshtml, .php even) and with a
NOTE recognizable file name (Default, Index). Since Windows is not case sensitivie with
respect to file names, it could even find defaulT.CSHtml. By convention, our projects
always start at Default.cshtml.

2.2. Visual Studio


For this book, I have assembled a template available through the Visual Studio Gallery. This section
describes that template’s organization, which follows Microsoft conventions.

To start your project with that template, in Visual Studio 2015’s menu, choose File → New →
Project. On the left column of the New Project panel, select Templates → Visual C# → Web.

To install the template the first time, click the link at the bottom of the center panel that reads "Click
here to go online and find templates.". In the search box (upper right corner, with the text "Search
Online Templates" in it), enter "Identity,Razor". The template named "ASP.NET Web Pages Starter
Site with Identity" will appear in the list. Select that template, replace "WebPagesSite1" with the
name of your project, make sure "create directory for solution" is unclicked, verify the location for
your project, and then click OK. This will create a new project with that template for you. Here is
the screen showing that selection:

Figure 4. First Project in Visual Studio

24
All future projects will find ASP.NET Web Pages Starter Site with Identity listed under the Visual C#
Web templates, along with the Empty web site:

Figure 5. Template in Visual Studio

You can select the template there, enter an appropriate Name and Location, and click OK to start
from that template in your next projet.

If you choose File → New → Project → C# ASP.NET Web Application → Empty or File → New → Web
Site → ASP.NET Empty Web Site, you will get just a single file (Web.config) and no supporting
infrastructure to work with. We will use that for some of our smaller examples, but want to make
use of the template site for our more complete projects.

There is a Microsoft-supplied template available in Visual Studio when you create


your site with File → New → Web Site → ASP.NET Web Site (Razor v3). This creates
you something similar to what is described here, but uses the old user login system
NOTE
of ASP.NET Membership, which relies on SQLCE. This isn’t compatible with
deploying (Chapter 6) and so we use an alternative template that provides a user
login system using the current ASP.NET Identity library.

25
Figure 6. Web Site Template Tree

If there is no App_Data directory, create it by right-clicking on the prject name, and selecting Add →
Add ASP.Net Folder → App_Data. This ensures the project knows about this special folder.

2.2.1. Review of website initial directories

• Account holds the pages that access the Microsoft ASP.NET Identity system. This is a basic system,
sufficient for our needs, and well-tested from wide distribution. It is unlikely you will need to
alter the contents of this directory unless you choose to expand it with Identity plug-ins such as
external authentication or two-factor authorization.

The files in Account are a great, in-depth collection of code for a single purpose; review
TIP their contents as you learn Razor, C#, and ASP.NET until you can understand how they
work.

• App_Code holds some startup code for the identity system (Startup.cs). You will add any C# files
you create to this directory; the parent directory contains only configuration and Razor-
enhanced html files (.cshtml)

• App_Data holds the database(s) for your website; you start out with one for the user accounts,
and may add to it or create a second one for your application data. You would also put text data
files in this directory. The Identity database is usually stored in a file named Identity.mdf, and is
created the first time you access the identity system on your website (create a login or attempt
to login).

• bin contains libraries to make your application self-contained; it is populated by Visual Studio
when your C# code is compiled. "bin" is short for "binary", i.e. compiled code — taken from text
to a binary format, MSIL (MicroSoft Intermediate Language), that is understood and executed
by the CLR (Common Language Runtime). You never directly change the contents of this
directory.

• Content contains the CSS used by your web application. It is pre-populated with the CSS used by
the template website, which includes JQuery.

26
The Content and Scripts directories have the same file twice, once with .min between
the file name and the prefix, and once without. .min means "minified", which is a
TIP processing of the CSS and JavaScript to remove any unneeded whitespace and
compress internal names. This is done to reduce the network traffic required for the
website - though it also makes the files pretty unreadable.

• Images contains the image files used by your web application. It is pre-populated with the
images used by the template website.

• obj contains the compiled files before they are packaged up and put in the bin directory. You
should never need to directly alter the contents of this directory.

• Scripts contains the JavaScript used by your web application. It is pre-populated with JQuery,
Knockout, and Modernizr, three well-known frameworks used by the template website.

2.2.2. Review of website initial files

Only the top-level files are discussed here; the ones within the directories are
IMPORTANT
mentioned in the previous section.

• _AppStart.cshtml contains HTML that is executed at the first request of any page in the site. (Not
each page, the very first request only.) It is used if you have application-wide setup or values to
prepare.

• _PageStart.cshtml. This will let us use a common layout among our pages.

• _SiteLayout.cshtml sets up to use the Web Pages templating convention, complete with a
common title bar for user account login/registration and the outer tags of any HTML page. This
is a powerful tool, used to give all of your pages a common look and feel.

• About.cshtml, Contact.cshtml, and Default.cshtml are template pages provided to jump-start


your website. You can see that they are not stand-alone HTML pages; they rely on Web Pages
integrating it with _SiteLayout.cshtml and _PageStart.cshtml to become complete web pages.

You may be wondering where the Login pages are? They are in the Account folder. It is
TIP common to organize a website so that separate portions are kept in their own
subdirectories.

• favicon.ico is a small image file used as the icon in the web browser’s tab bar for your website.
It must be a 16-pixel by 16-pixel bitmap file; you can create them, or edit this one, in Microsoft
Paint or from within Visual Studio.

• packages.config lists all external packages your web application depends on.

• Web.config, you may notice, appears to be both a file and a directory. In File Explorer, you will
find it is just a file, and that there are two more files right after it, Web.debug.config and
Web.release.config. The debug file sets up additional parameters for removing items you don’t
want visible in production code such as stack traces. Web.release.config does the opposite,
removing configuration that makes a website easier to debug but less secure.

27
2.3. Web Pages Layouts
The layout structure supplied in Web Pages makes it easy to have a common template within which
your pages appear.

This is a good thing, as it lets you give your website a consistent look without having to repeat the
HTML across all the files.

Web Page Layouts let you lay out a "parent file" that specifies the layout of all your pages as well as
separate header and footer files pulled in for your pages. You can isolate down portions that need
to be the same and portions that need to change.

Don’t Repeat Yourself

TIP This Web Pages feature embodies an important programming concept: D.R.Y.: Don’t
Repeat Yourself. (oops)

Layouts are done using the ASP.NET library. This requires that you learn the first step of Razor: how
to embed an ASP.NET function call in your code.

This is done by prefixing the function call with the @ symbol.

2.4. Layout Functions


Here are the ASP.NET functions used to manage layouts:

Table 1. ASP.NET Layout Functions

Function Example Description

RenderPage @RenderPage("header.cshtml") Finds the named page and pulls


its contents in to the current
location.

RenderBody @RenderBody() Pulls in the main HTML from


the file this template is being
applied to.

RenderSection @RenderSection("help", Pulls in the named section from


required:false) the file this template is being
applied to; if required is true or
not specified, the section must
exist.

2.4.1. Identifying the Template

You get the template by creating a layout file (_SiteLayout.cshtml is the one supplied) and then
having a _PageStart.cshtml that identifies it in a Razor code block, like so:

28
@{
  Layout="~/_SiteLayout.cshtml";
}

This is doing several things:

• @{..} embeds a C# code block - this is our second Razor construct.

• Layout=… is a C# assignment statement that assigns a value to the page Layout property, which
will cause the template to be pulled in and used along with the contents of this file. Layout is a
page property, which says what layout to use for the page. That layout file will contain
instructions on how to use the rest of the content of your page.

• "~/_SiteLayout.cshtml" is a C# string value that will be used to find the template file. This one in
particular uses the ASP.NET convention for a file name, ~ represents the root directory of the
website. You should always use either ~ rooted references or relative references, since your
website’s location in a particular directory is not guaranteed and will be different in
deployment than in development.

Alternatively to using a _PageStart.cshtml, you can have each page in your site set the
Layout variable directly in a Razor code block at the top of the file. This lets you have a
TIP
different layout for each page if you want it — but usually it’s best to have one layout
shared among the files in your site, for a consistent experience.

2.4.2. Identifying a section

You identify a section named help within your .cshtml file like so:

@section ①
  help ②
{
  <p>If you are looking for assistance with this web site, please contact
admin@website.com.</p> ③
}

① @section is the Razor marker to make this portion of your file a section; it will only be rendered
if there is a matching @RenderSection call in the layout file.

② This is the name of the section; you can give your sections any valid identifier.

③ The section begins and ends with curly braces; within you place HTML and potentially
embedded Razor blocks.

2.5. Making Layout Setting DRY


You have seen that you can apply different layouts to different pages in your website by setting the
Layout property at the start of each page. However, what if you forget one page?

This is handled at a directory-wide level with a _PageStart.cshtml file. When a target page is

29
identified, a _PageStart.chtml file in the same directory is read and rendered before the file for the
page itself. So you can ensure that all the files in a given directory use the same layout file by
creating a _PageStart.cshtml file that sets the Layout property like so:

Listing 1. _PageStart.cshtml

@{
  Layout = "~/SiteLayout.cshtml";
}

You can put any other common processing in that file as well.

If you need to override the Layout property for a single file in the same directory, you can reset it at
the start of your individual .cshtml file — it will change the property’s value onces _PageStart
completes and your actual page begins rendering.

If you create a subdirectory, you would create a _PageStart.cshtml file in it to have each page in the
new subdirectory use the same Layout.

2.5.1. Other uses for _PageStart

_PageStart can be used for more than just selecting a common layout: it lets you specify any
common action you desire. This might include

• initializing Page properties

• specialized error handling

• restricting folder access

See http://www.asp.net/web-pages/overview/ui-layouts-and-themes/18-customizing-site-wide-
behavior for examples of those uses.

2.5.2. Subdirectories?

I mentioned earlier that subdirectories are often used to separate different sections of a website. In
the template provided, we see the Accounts directory contains all of the code for user accounts,
login and registration, separate from the rest of the web site.

Within a directory, ASP.NET will look for a _PageStart file to use prior to rendering the file within
the directory that you have requested.

2.6. Web Design


Layouts are simply a tool; the key task behind them is designing your web application. We are
looking at web applications that would have several pages, would be accessed by a variety of
people (this is the internet, after all), and involve persistent data kept on the server.

30
2.6.1. Learn from the Internet

You probably already have favorite places on the internet — consider what you like about them,
and how they are organized. You can always take a peek at how they did their HTML with a simple
right-click and View Source… on the pop-up menu that appears. You won’t see their client-side code,
but you will see their HTML, and any links to additional CSS and JavaScript files there can be
clicked on to bring those up as well.

When you do this, remember: there is an implicit copyright on anything you see on the internet,
unless they have released it with an explicit statement or license such as Creative Commons (for
content) or Open Source (for code). You can’t simply copy and paste what is there, you need to learn
from it, internalize it, and then put it aside when you work on your own web applications. Copying
code is a copyright violation, and in the workplace can be grounds for losing your job or legal
prosecution.

2.6.2. Responsive Web Design

A current theme in web design is to have your site be responsive; in fact, this replaced the prior
theme of "mobile-ready" web sites. Razor provides some capabilities for "mobile-ready" — we will
not be discussing them in this text. To make your web site responsive regardless of its target client,
use the CSS/Javascript framework called Bootstrap. This framework is included in ASP.NET MVC
projects due to its rich capabilities.

Bootstrap is outside the scope of this text; for more information, I recommend: the official bootstrap
resources and the Tutorials Point Bootstrap Tutorial.

2.6.3. Basic Design Principles

Good design starts and ends with the user: is your website usable. Yes, it has a purpose; it is your
job as its designer to mold that purpose into a positive user experience. As developers, we often
forget to look at the user and get lost in the purpose. So, design focuses on the user perspective, as
you see in the list below.

Design is a plan for arranging elements in such a way as best to accomplish


a particular purpose.

— Charles Eames

1. Don’t make users think

Make it easy for users to "do the right thing" — you want them to stay on your site and enjoy it. This
means inviting them to push the right button, not making them click several times where one click
will do.

There are a few things to know about users that can help you with this:

• users know quality when they see it; if they hit typos or things that don’t work, you’ve lost them.

• users scan: don’t overload them with text; you are making a website, not a book.

31
• users are impatient, and that means they will choose early rather than look at all the options.

2. Don’t waste users' time

This can be anything from slow load times to requiring several clicks where one would do. Right-
size your images for the web, and consider mobile load times; you can tailor images to several
platforms with CSS media rules.

Also consider not having them register at first — get them interested in your site so that they want
to register. When you do make them register, don’t ask them for more information than you need.
Privacy is important to users, and they may leave your site if you ask for irrelevant information.

Consider how you want your website to flow; different parts may need different flows — think
about the user experience and what they will expect, to make them as intuitive as possible.

Two typical flows are hierarchical, where you drill down to more detail on a particular item; and
sequential, where you step through a series of equal items. E-books are often a collection of both;
the book opens to a table of contents that lets you drill down to particular chapters, and chapters
drill down to sections. Once you are on text, you can move sequentially from page to page.

Figure 7. Hierarchical flow

Figure 8. Sequential flow

Website layout is often done with a "wire diagram" showing how the pages are interconnected.
Cloud tools such as Cacoo and freeware such as Pencil are great tools for layout out your website

32
before you commit to HTML.

3. Keep it simple

Choose simple words, keep phrases and text short and focused. Technical writing is an art in itself.
Remember to focus on avoiding spelling errors and also on using active voice.

What is active voice? Write as if you were talking to your user, and use direct
language. For example, instead of saying "at this point in the installation one may see
TIP
that the icon is changing colors", say "now you see the icon change color". Active voice
is tight, crisp, and direct.

Your layout should also be simple; don’t overload the user with flashing icons, lots of fonts, and
random color changes. Keep it clean and crisp — keep it simple. In this regard, white space is your
friend. Look at websites you like — see where they put gaps, around headers, around images,
between sections on their pages. Strive to use whitespace to add organization and direction to your
site.

4. Make the right choice obvious

Each page should have one goal; and users should be able to figure that out and satisfy that goal
quickly. Focus the user’s attention on the key activity the page wants them to do.

Guide the user — you may feel like you are oversimplifying things, but remember, they will decide
to stay on your site or not in three seconds.

There is some great advice on this here: ttp://conversionxl.com/8-universal-web-design-principles-


you-should-to-know/

5. Use layout carefully

There should be a consistent look to all of the pages in your application. That layout needs to
consider that it is on all of your pages. Keep common features such as links to a privacy policy, out
of the way but available. Navigation is usually at the top of a page, links to common pages at the
bottom.

HTML provides you with the ability to change font sizes and font families easily. Do this with care.
Use the semantic tags appropriately, so <h1> is your largest, most important heading and <h6> is
your smallest, least important heading. It’s seldom appropriate to have more than 2 levels of
headers, actually, as users won’t stay engaged long enough if they need to keep the upper levels in
mind to know where they are.

Step away from your monitor to view the page from a distance — is there a visual clue there that
aids the user in finding out what to do, without being able to read the text? There should be.

6. Don’t be unconventional

Sure, it’s fine to work on being a break-out designer with the newest look. But when you are
creating something that is new-but-not-new, such as a website to sell shoes, consider what the
biggest in the business do: zappos.com has this down. Now, you can’t copy their site, but you can

33
learn from it: where do they put their privacy policy? what order are their shopping cart check-out
steps in? You will soon find that websites that sell things (even non-shoe things) have a pretty
standard order for cart check-out. It would be to your benefit to use the same order. That way users
won’t get lost, and you will get the sale.

Even a game website has some conventions: there will be help links, inventory pages, pages to shop
for extra goodies, and the basic game play page.

There are conventions for web pages that are there for very good reasons, such as WebAIM's
guidelines for accessibility. When you learn about conventions such as those, use them. It will help
your web site if more people can use it. Some conventions may actually be a legal requirement for
your website: accessibility, copyright, terms of service, and privacy policies are becoming more
mandatory, with legal requirements in some fields such as education and government web sites.

2.7. Further Reading


• Creating a Consistent Layout in ASP.NET Web Pages (Razor) Sites @ asp.net

• Customizing Site-Wide Behavior for ASP.NET Web Pages (Razor) Sites @ asp.net

• ASP.NET Web Pages - Tutorial @ w3schools.com

• 10 Principles Of Effective Web Design @ smashingmagazine.com

• https://www.smashingmagazine.com/2012/01/stop-designing-pages-start-designing-flows/

• Stop Designing Pages And Start Designing Flows @smashingmagazine.com

• 8 Effective Web Design Principles You Should Know @ conversionxl.com

• Buld it With the User in Mind @ conversionxl.com

• The Principles of Design @ digital-web.com

• WebAIM: Web Accessibility In Mind @webaim.org

• Exercise 1 - Creating the Base Application from a Template @ msdn.microsoft.com builds a


sample website in WebMatrix using layouts

2.8. Exercises
1. Design a layout that mimics craigslist.org: a home page with links to sections, section pages with
links to individual items, and individual item pages. Develop a wire-frame and then implement
your layout in Web Pages. Include at least 3 sections and 6 items (it is fine to cross-list items in
multiple sections). Have a common look-and-feel, and capture it in _SiteLayout.cshtml. Use
_AppStart.cshtml and _PageStart.cshtml. Use the Web Pages convention of ~ as the location of
the root directory of your website, not an absolute path.

This will be a hierarchical layout (with a little spaghetti at the lowest level if you reuse item
pages).

2. Design a layout that mimics a shopping cart purchase process: a cart page showing contents,
and includes at least three steps in the process.

34
Consider what you want displayed on each page, and why you chose the steps and the order in
which you present the steps (was it modeled after a well-known website? what reasoning did
you use in putting the pages in the order you chose?)

Design a wire-frame and then implement your layout in Web Pages. Have a common look-and-
feel, and capture it in _SiteLayout.cshtml. Use _AppStart.cshtml and _PageStart.cshtml. Use the
Web Pages convention of ~ as the location of the root directory of your website, not an absolute
path.

This will be a sequential layout.

2.9. Project
Design a layout for your application. Use the Layouts and Render, and start with the default Razor 3
application so that user logins are a part of your website. Rewrite the About and Contact pages.
Make the contact information reflect how you would like to be contacted - only include information
for the methods of contact you want to respond to. Use a _PageLayout.cshtml file so that you do not
repeat the code to set the Layout property in every page.

Start looking into Geolocation in HTML, using this: http://apress.jensimmons.com/v5/pro-html5-


programming/ch5.html

and this: https://developers.google.com/maps/

Make a You Are Here webpage that shows the user’s current location by latitude and longitude. Or
go for it, and show it on a map. Be sure to include a citation of sources used in your HTML. To
display a map you will have to have a google account so that you can get a Google Maps key. This is
available at no charge at the google link above. (Bing also has a map service, if you prefer using a
Microsoft account; theirs also requires a key.)

35
Chapter 3. Razor
Believe it or not, you’ve already seen almost enough Razor to infer how it is used to embed C#
within a web page.

Let’s take a step back and review what’s going on:

Figure 9. Where Razor fits in the web request processing

When a client requests a particular page, the web server determines how to "source" it — it may be
a file (as ours are) or it may be an interface to another system. It locates the file, and then
determines if it needs further processing before it is returned.

A web browser (in the client) can only handle HTML, CSS, and JavaScript, so anything beyond that
needs to be turned into one of those three on the server. So, when the web server realized the page
has Razor in it, it hands it to the Razor engine. That engine will execute the code within the Razor
markers, which may impact the server-side state and may also cause HTML to be generated within
the page. Once the processing completes, the final HTML page is returned to the client for
rendering in the web browser.

Razor is a templating "language": it defines how to note that you are now in C#, which needs to be
executed on the server side. Razor is used for two reasons:

1. to impact server-side state

2. to generate in-place HTML within the page

Its rules are fairly basic and intuitive, and just like we can use parentheses to clarify order of
operations, Razor gives us several ways to make very clear when we are specifying client-side code
(HTML, JavaScript, and CSS) and when we are specifying server-side code (C#).

36
Yes, Razor can also be used to embed Visual Basic. We won’t go there. To see those
NOTE rules: http://www.asp.net/web-pages/overview/getting-started/introducing-razor-
syntax-vb

3.1. Razor’s Rules


1. Use the file extension .cshtml
To tell the web server that your page has Razor and C# in it, you give the file the extension .cshtml.
That’s all.

If your page in fact has no Razor/C# in it, it works fine. The processsor won’t find anything to
process, and simply returns the file unchanged.

2. @{ … } marks a code block.


To put a block of C# code in your file at the point you want it executed, you open the block with @{
and close the block with }. Everything within is considered to be C# and is interpretted as such. The
contents must follow the rules of C# (but note #4 below).

<!- - Multi-statement block - - >


@{
var weekDay = DateTime.Now.DayOfWeek; ①
var weekDayMessage = "Thank goodness it's " + weekDay;
}

① the variable weekDay is looking into an ASP.NET object named DateTime. The "." operator on
DateTime accesses a property called Now, which is then accessed with another . operator to get
its DayOfWeek property. That holds a string value which is, you guessed it, the day of the week
when the code is executed.

3. @ marks an inline expression.


If you want a simple value in your HTML, you can slip into C# mode with a simple @ symbol. The
expression is evaluated by the Razor engine and its value put into the resulting output HTML file.

Typically the @ is used with a variable previously declared in a code block, or with a function call.
It can also be an arbitrary expression, wrapped in parentheses.

ASP.NET provides many useful functions; you saw this with the @RendorBody() method used in
Layouts.

<p>Hello. @weekDayMessage</p> ①
<p>Did you know that 1 + 1 is @(1+1)?</p> ②

① Assuming the code block above occurs first, this will substitute the string in place of the variable
when the page is processed in the web server, so on a Monday, the resulting HTML will be the
code shown below.

② And yes, @(1+1) is a bit silly but shows the use of parentheses around an expression.

37
<p>Hello. Thank goodness it's Monday</p>
<p>Did you know that 1 + 1 is 2?</p>

HTML Encoding
The @ marker has a very interesting and valuable side-effect. The content that is
put is is "HTML encoded". ASP.NET replaces reserved HTML characters with
codes that will display the character in the web page rather than let them be
interpretted as HTML. This is valuable because it prevents a security hole with
user data called an "injection attack", where user data causes execution on the
web page.
CAUTION

So, characters such as <, >, and & will be replaced with numeric entity references
and will be displayed as text, rather than coming through unchanged in a string
value.

If you want to have the string value appear as raw HTML, un-encoded, you will
need to wrap the value in an ASP.NET function such as Html.Raw().

4. Declare variables with the var keyword.


This is one slight difference from C# general use, where variables are usually given types. Razor
expects a more dynamic environment, so variables are declared simply with var and their type is
inferred from their initialization.

C# does require the variables be declared, unlike PHP and other weak-typing languages.

@{ var total = 7; } ①

<p>The value of your account is: @total </p> ②

① total takes an integer value

② the value in the variable is put in its place in the resulting HTML.

The variable must be both declared and initialized, so that its type can be inferred from the initial
value.

5. C# is case sensitive.
This is true in C# in general, and applies here as well. C# keywords and names are always case
sensitive. The name you access a variable with must match the case of how it was declared.
lastName and LastName do not match.

6. Statements end with semicolons.


If you use @ to start a statement, end it with a semicolon. (We won’t see an example of this until we
get to more complex features requiring @using.)

Within code blocks, the normal rules of C# apply, where statements usually end with ; and
compound statements are surrounded with { }.

38
7. To put @ in your HTML, use @@.
How do you put an email in a HTML file? like so: me@@gmail.com. @@ is replaced with @ by the
Razor engine.

8. String values use quotation marks


Strings use the double-quote, or " mark, in Razor blocks and expressions.

We look to C# to see how to handle all the lovely corner cases with strings that always occur in a
language:

C# requires \ (backslash) and " (the double quote) be handled with special string literals.

To put a \ in a string, you have to prefix the string literal with a @ marker. This is a C# @, not a
Razor @. C# calls this a verbatim string literal. This is because the \ marker is used to include
character encodings in string literals.

<!-- Embedding a backslash in a string -->


@{ var filePath = @"C:\MyFolder\"; }
<p>The path is: @filePath</p>

To put a double quote within a string, you use the verbatim string literal and double up the double
quote, like so:

<!-- Embedding double quotation marks in a string -->


@{ var quote = @"Then she said, ""Hello, how are you?"""; }
<p>@quote</p>

This renders as:

<p>Then she said, "Hello, how are you?"</p>

To continue a long string value across multiple lines, start with a verbatim string literal opening (
@") and then wherever you have newlines they will be ignored. Close the string with ".

9. ASP.NET Objects are available to you in code blocks and inline expressions.
Even before we start declaring our own objects in C#, you will be working with many ASP.NET
objects. You have already done this with layouts: the RenderBody, RenderSection, and other
functions are actually methods on the Page object available by default in a page.

Objects have properties that describe their characteristices and methods that define actions on the
object. You can read or change an object’s properties and call its methods.

Besides the Page, you will have access to the Request that came in for the page, and many other
system objects such as the DateTime object we’ve used already in our examples.

The Request object is an interesting one to explore:

39
<table border="1">
<tr>
  <td>Requested URL</td>
  <td>Relative Path</td>
  <td>Full Path</td>
  <td>HTTP Request Type</td>
</tr>
<tr>
  <td>@Request.Url</td> ①
  <td>@Request.FilePath</td> ②
  <td>@Request.MapPath(Request.FilePath)</td> ③
  <td>@Request.RequestType</td> ④
</tr>
</table>

① The Url property gives you the URL of the page

② FilePath gives you the path on the URL (after the domain name)

③ MapPath is a method on Request that gives you the absolute path of the page on the server

④ RequestType tells you if it was a GET or POST request.

10. Everything outside the Razor markers is HTML.


So, HTML comments are used in HTML, and C# comments are used within Razor blocks.

11. Put HTML inside Razor blocks with @: or <text>


You can actually include HTML within a Razor block by using any matching tags; the <text> tag is
specific to Razor, but HTML tags such as <p> and <em> can also be used.

A single line of HTML can be included with @: at the start of the line.

You can also use inline expressions within those "HTML-inside-Razor" blocks - this can get
confusing fast, so use this type of embedding carefully.

@{
  var minTemp = 75;

  <text>It is the month of @DateTime.Now.ToString("MMMM"), and


  it's a <em>great</em> day! <br /><p>You can go swimming if it's at
  least @minTemp degrees. </p></text>

  @: It is @DateTime.Now.DayOfWeek. ①

  <p>We can just use the HTML markers too. And inline a value: @minTemp.</p>
}

① You might notice the closing . here — why doesn’t Razor consider it to be a dot operator?
because there isn’t a valid name following it. Razor keeps following dot operators as long as they
are followed by names, but when they aren’t, it stops and assumes the . is part of the HTML, not

40
part of the inline expression. Razor’s really clever that way.

12. You can embed the C# if statement directly.


The C# if can be directly embedded with the @ operator rather than inside a code block. This may
remind you of PHP, which does something similar:

@if(IsPost) { ①
  <p>Hello, the time is @DateTime.Now and this page is a postback!</p> ②
} else { ③
  // All content between matched tags, followed by server code. ④
  <p>Hello <em>stranger</em>, today is: <br /> </p> @DateTime.Now
}

① IsPost is a property on the page which is true if the request was a POST of a form.

② This is HTML within the code block.

③ Notice that the else uses curly braces but no additional @ symbols.

④ The // is used to make a C# comment within the block.

13. Razor comments use @* *@


Yes, you have HTML comments in your HTML. Yes, you have C# comments in your code blocks.

You also have a third choice, which can be used in both places: Razor comments.

Razor comments are removed by the Razor processor, so they will not be seen on the client. HTML
comments are seen on the client.

3.1.1. Is that it?

There are a few more uses of Razor that we will see, such as @using, but we will explain them
when we have enough context to make them useful.

Razor itself is a small set of conventions that allow you to embed C# within HTML. So alot of our
"Razor" rules above are actually C# rules (verbatim string literals, variables, and case sensitivity, for
example). Helpers are also considered to be part of Razor; we saw some in Layout with the various
Render calls that pull pages together from layout templates.

Razor also is used as a base in ASP.NET MVC, the next level of Web Development technology in the
Microsoft stack.

I know Stack Overflow is a favorite landing pad when there are questions, but Microsoft
Developer’s Network maintains forums that you may find useful, specifically the * ASP.NET Web
Pages forum.

3.2. An example: a simple calculator


Based on Introduction to ASP.NET Web Programming Using the Razor Syntax (C#)

41
Listing 2. SimpleCalculator.cshtml

@{
  var result = 0;
  var message = "";
  if (IsPost) {
  // Retrieve the numbers the user entered.
  var num1 = Request["num1"].AsInt(); ①
  var num2 = Request["num2"].AsInt();

  // Add the numbers and provide the result message


  result = num1 + num2;
  message = "Total = " + result;
  }
}

<!DOCTYPE html>
<html>
  <head>
  <title>Simple Calculator</title>

  <style type="text/css">
  body {font-family: Verdana, Arial; margin: 50px;}
  form {padding: 10px; border-style: solid; width: 250px;}
  </style>
  </head>

  <body>
  <p>Enter two integers and then click <strong>Add</strong>.</p>
  <form action="" method="post"> ②
  <p><label for="num1">First Number:</label>
  <input type="text" name="num1" />
  </p>
  <p><label for="num2">Second Number:</label>
  <input type="text" name="num2" />
  </p>
  <p><input type="submit" value="Add" /></p>
  </form>

  <p>@message</p> ③
  </body>
</html>

① The Request object is used to access a form’s fields. Since field names are dynamic, the […]
syntax is used with the field name to get to the form field value, rather than dot notation. The
values are available as strings, so the .AsInt() method is called on the string value to conver it to
an integer.

② Notice post here — that ensures when submit is clicked, the request is a post request, so IsPost is
true in the C# code when the form is submitted. The original page request will be a get request.
<3>The result message is completely filled out in the message variable so that no text is output if

42
the user has not yet submitted the form. An empty paragraph will be output before the form is
submitted.

GET and POST in HTTP


HTTP requests are usually GET requests; forms can be submitted with either GET or
POST. We use POST here so that we can use IsPost to determine that the form has
been submitted (it keeps our code simple). POST is also used for long forms, to put
NOTE the form values in the HTTP request rather than within the URL. A GET submission
causes the values to be placed within the URL itself Google does this - check out the
search URL next time you do a search.They use GET so the search result can be
bookmarked. Since you set up the form, you get to decide how it will be submitted.
This lets you handle form processing appropriately.

One thing our page lacks is error handling; we will see that there are calls we can make to check the
input values and ensure they are valid integers prior to converting them to integers. There are
several checks we may want to make, if our code is going to be used to control peoples' bank
balances or fly shuttles to Mars. (Don’t believe me? see
http://www.hq.nasa.gov/office/pao/History/alsj/a11/a11.1201-pa.html)

3.3. Further Reading


• http://www.w3schools.com/aspnet/razor_syntax.asp

• http://www.asp.net/web-pages/overview/getting-started/introducing-razor-syntax-c

• http://www.asp.net/web-pages/overview/getting-started/introducing-aspnet-web-pages-2/getting-
started

• http://www.asp.net/web-pages/overview/getting-started/introducing-aspnet-web-pages-2/intro-
to-web-pages-programming

• http://www.asp.net/web-pages/overview/testing-and-debugging/aspnet-web-pages-razor-
troubleshooting-guide

• http://www.asp.net/web-pages/overview/getting-started/aspnet-web-pages-razor-faq

• http://forums.asp.net/1224.aspx/1?ASP+NET+Web+Pages

• https://msdn.microsoft.com/en-us/library/gg606533(v=vs.100).aspx
http://blog.slaks.net/2011/01/dissecting-razor-part-1-pieces-of.html and Slak’s other posts on
Razor - very informative, something to return to once you’ve had some time with Razor.

3.4. Exercises
1. The Introducing ASP.NET Web Pages - Getting Started tutorial steps you through a "hello, world"
style razor page. Complete this walkthrough in Visual Studio (just this page’s information, not
the pages that follow).

2. The Microsoft Introduction to Razor page steps through several code examples. Take the one
called "Add Numbers" and get it working in Visual Studio.

3. The Walkthrough: Creating a Web Site using Razor Syntax in Visual Studio walks through one

43
example, adding to it as it goes. Do the walkthrough starting after the VS update (with VS 2015
you already have Razor), and get the final page working in Visual Studio.

3.5. Project
1. Forms are a big deal — they bring a website to life, getting input from the user for a tailored
experience in the app. In this chapter you were given a simple example that processes form
results on the same page as the form. Build a form that collects interesting data from the user,
and have it route its results to a different page that then processes and displays the data entered.
You can use either GET or POST as the action, since the target page is only used to process form
results. It will not need to check IsPost, it can assume there is a Request with the values
available. Make your form be something you might want to collect data about, such as movies, a
bucket list, songs, goals, magic cards, pokemon, flowers, birds, yarns, or beers. You can use this
later in your project when you have a backing database.

44
Chapter 4. C# Variables and Expressions
Based on Think Java Chapter 2

You have already seen a little bit of C#. Now we are going to take a step back and cover the core
features a bit more thoroughly.

This chapter describes how to write statements using variables, which store values like numbers
and words, and operators, which are symbols that perform a computation. We also explain three
kinds of programming errors and offer additional debugging advice building on that in Chapter 1.

This chapter will cover primitive types, variables, literals, expressions, assignment statements and
method calls.

Later chapters will look into control flow statements, arrays, exception handling, object classes,
properties, and methods.

4.1. Declaring variables


One of the most powerful features of a programming language is the ability to define and
manipulate variables. A variable is a named location that stores a value. Values may be numbers,
strings, booleans, objects, and other types of data. To store a value, you first have to declare a
variable.

string message;

This statement is a declaration, because it declares that the variable named message has the type
string. Each variable has a type that determines what kind of values it can store. For example, the
int type can store integers, and the char type can store characters.

Some types begin with a capital letter and some with lowercase. We will learn the significance of
this distinction later, but for now you should take care to get it right. There is no such type as Int;
there is actually a String type in C#; it is the system class defined to support the string primitive
type. Tere is also an Int32 class behind the int type.

To declare an integer variable, the variable declaration statement is:

int x;

Note that x is an arbitrary name for the variable. In general, you should use names that indicate
what the variables mean. For example, if you saw these declarations, you could probably guess
what values would be stored:

45
string firstName;
string lastName;
int hour, minute;

This example declares two variables with type string and two with type int. When a variable name
contains more than one word, like firstName, it is conventional to capitalize the first letter of each
word except the first. Variable names are case-sensitive, so firstName is not the same as firstname or
FirstName.

variable names can contain underscores and numbers as well as letters. By convention, start with a
lowercase letter, start inner words with an uppercase letter, even when they are acronyms such as
HTML (use Html within a name or html at the start of a name).

This example also demonstrates the syntax for declaring multiple variables with the same type on
one line: hour and minute are both integers. Note that each declaration statement ends with a
semicolon.

You can use any name you want for a variable. But there are about 50 reserved words, called
keywords, that you are not allowed to use as variable names. These words include public, class,
static, void, and int, which are used by the compiler to analyze the structure of the program.

You can find the complete list of keywords at https://msdn.microsoft.com/en-


us/library/x53a06bb.aspx, but you don’t have to memorize them. Most programming editors
provide “syntax highlighting”, which makes different parts of the program appear in different
colors.

A variable, once defined, has a visible scope. In Razor, a variable can be used anywhere on the
page once it is declared in a Razor code block, including in a later Razor code block.

C# also allows another form of variable declaration:

var message = "Hello World";


var age = 23;

The keyword var can be used in C# to declare a variable if there is an initialization in the same
statement — the = is used to assign an initial value to the variable. The C# compiler uses this to
determine the type of the variable.

The type is fixed at compile time by the type of the initialization value.

In our example, message will be a string variable, and age will be an int variable.

The initializer on a var declaration cannot be null (which is a special, untyped value).

4.2. Assignment
Now that we have declared variables, we want to use them to store values. We do that with an
assignment statement.

46
message = "Hello!"; // give message the value "Hello!"
hour = 11; // assign the value 11 to hour
minute = 59; // set minute to 59

This example shows three assignments, and the comments illustrate different ways people
sometimes talk about assignment statements. The vocabulary can be confusing here, but the idea is
straightforward:

• When you declare a variable, you create a named storage location.

• When you make an assignment to a variable, you update its value. As a general rule, a variable
has to have the same type as the value you assign to it. For example, you cannot store a string in
minute or an integer in message. We will see some examples that seem to break this rule, but we’ll
get to that later.

A common source of confusion is that some strings look like integers, but they are not. For example,
message can contain the string "123", which is made up of the characters '1', '2', and '3'. But that is
not the same thing as the integer 123.

message = "123"; // legal


message = 123; // not legal

Assignment statements are actually expressions; if you use an assignment statement


without a semicolon, then it is an expression, and it can be placed inside a larger
NOTE expression. The value of an assignment expression is the value placed into the
storage location (variables, so far, are our only storage locations; later we will see
array indexes and properties used this way also).

Variables must be initialized (assigned for the first time) before they can be used. You can declare a
variable and then assign a value later, as in the previous example. You can also declare and
initialize on the same line:

string message = "Hello!";


int hour = 11;
int minute = 59;

This is the same syntax we saw with the var declarations above.

4.3. State diagrams


Because C# uses the = symbol for assignment, it is tempting to interpret the statement a = b as a
statement of equality. It is not!

Equality is commutative, and assignment is not. For example, in mathematics if a = 7 then 7 = a. In


C# a = 7; is a legal assignment statement, but 7 = a; is not. The left side of an assignment statement
has to be a storage location (so far the only storage locations we have covered are local variables;

47
we will see others in later sections).

Also, in mathematics, a statement of equality is true for all time. If a = b now, a is always equal to b.
In C#, an assignment statement can make two variables equal, but they don’t have to stay that way.

int a = 5;
int b = a; // a and b are now equal
a = 3; // a and b are no longer equal

The third line changes the value of a, but it does not change the value of b, so they are no longer
equal. When you store a value in a variable with an assignment statement, it replaces the value that
was in that location earlier.

Taken together, the variables in a program and their current values make up the program’s state.
This figure shows the state of the program after these assignment statements run:

Figure 10. State diagram of the variables a and b

Diagrams like this one that show the state of the program are called state diagrams. Each variable is
represented with a box showing the name of the variable on the outside and the value inside. As
the program runs, the state changes, so you should think of a state diagram as a snapshot of a
particular point in the execution.

4.4. Constants
Sometimes we want names for values even though they don’t change. This cuts down on comments
in the code, if the names are well-chosen. However, variable contents can be changed with a simple
assignment statement. C# comes to the rescue with constants: add the keyword const before the
variable declaration like so:

const int meaning = 42;

The constant must be initialized when it is declared, and its value cannot be changed once it is
declared.

C# conventions say that local constants should be named just like local variables, with camel case
(not all upper case as we see in other languages).

4.5. Displaying values


You can put the value of the variable on your web page with an inline expression.

The following statements declare a variable named firstLine, assign it the value "Hello, again!",

48
and display that value.

@{ string firstLine = "Hello, again!"; }


<p>@firstLine</p>

When we talk about displaying a variable, we generally mean the value of the variable. To display
the name of a variable, you have to put it in the HTML directly.

<p> The value of firstLine is @firstLine</p>

For this example, the resulting HTML is:

<p>The value of firstLine is Hello, again!</p>

Conveniently, the syntax for displaying a variable is the same regardless of its type. For example:

@{
int hour = 11;
int minute = 59;
}

<p>The current time is @hour:@minute.</p>

For this example, the resulting HTML is:

<p>The current time is 11:59.</p>

Note that the HTML formatting is required. Without the <p> tags, the text will run together even if
you put whitespace between your un-tagged 'paragraphs'.

4.6. Data types in C#


Variables, constants, and literals all have a data type — the type of the data. So far, you’ve seen int
and char. C# has a rich set of built-in primitive types, as shown in the table below.

type description range of values literal

byte 8-bit unsigned integer 0 - 255 whole number in range

sbyte 8-bit signed integer -128 - 127 whole number in range

short 16-bit signed integer -32,768 - 32,767 whole number in range

ushort 16-bit unsigned integer 0 - 65,535 whole number in range

49
int 32-bit signed integer - 2,147,483,648 - whole number i.e. 452
2,147,483,647

uint 32-bit unsigned integer 0 - 4,294,967,295 whole number in range

long 64-bit signed integer -9,223,372,036,854,775,8 whole number with l


08 .. sufficx, i.e. 452l
9,223,372,036,854,775,8
07

ulong 64-bit unsigned integer 0 .. ul suffix


18,446,744,073,709,551,
615

float 32-bit floating point (7 ±1.5e−45 to ±3.4e38 decimal number with f


digits) suffix

double 64-bit floating point (15 ±5.0e−324 to ±1.7e308 decimal number with
digits) optional d suffix

decimal 128-bit, 28 digits of -7922816251426433759 decimal number with


precision 3543950335 .. m suffix
79228162514264337593
543950335

char 16-bit Unicode U+0000 - U+FFFF single quotes around


character one character

string sequence of Unicode double quotes around 0


characters or more characters or
null (a special value
meaning there is no
value)

bool Boolean value true or false true or false

object An object new creates one; null


(more on this later)

As you will see later, C# also allows you to define classes, which are object-oriented types you can
then use in your programs. ASP.NET actually defines its own classes, which C# maps to these
primitive types. So, int maps to ASP.NET’s Int32 and string maps to String. It is C#'s convention to
capitalize class names, property names, and method names while the primitive types and local
variables and local constants are initial lower case. Both use camel case.

It is best to stick with the data type that will fit the values you need; however, if you are using a
library of previously written methods, such as ASP.NET, you may use types larger than you need, to
avoid conversion between types when you make calls to methods in that library.

4.6.1. String.Format

ASP.NET provides a helper method for formatting values. This is useful to truncate double values
and also to display date time values. This helper is String.Format: the Format method on the system
object String.

50
Here is a first example of how String.Format works. Its first parameter is a format string, and the
remaining parameters are expressions that are plugged into the format string.

@String.Format("Hello, {0}.",name)

If the value in the variable name is "Dave", then the String.Format result is the string "Hello, Dave.".
name is the first expression in the list after the format string, and so it is put in place of the {0},
which is a specification for the first expression (Format uses 0-based counting).

Here are some additional examples showing formatting and what it produces. Notice that the
arguments do not need to be variables — they can be any expression, a literal, a method call, or
operations on them:

String.Format("{0:C}",23.456) "$23.45" // C is for currency

String.Format("{0:0.00}", Math.PI) "3.14" // the result is always a string

String.Format("{0:#,##0.00}", 123456789) "123,456,789.00" // notice the .00

String.Format("{0,-6}{1,10},"Name","Phone") "Name Phone" // field widths: -6 left aligns; 10


right aligns

String.Format("It is now {0:d} at {0:t}", "It is now 4/10/2015 at 10:04 AM"


DateTime.Now) //notice the value is used in two places

For more information on String.Format formats, see https://msdn.microsoft.com/en-


us/library/system.string.format(v=vs.110).aspx and the links at the end of that page to numeric,
date/time, and additional formatting options.

4.7. Arithmetic operators


Operators are symbols that represent simple computations. In C#, the arithmetic operators include
the addition operator is +, subtraction is -, multiplication is *, division is /, and remainder of
division (modulus) is %.

The following code converts a time of day to minutes:

@{
  int hour = 11;
  int minute = 59;
 }

<p>Number of minutes since midnight:


  @(hour * 60 + minute)</p>

In this program, hour * 60 + minute is an expression, which represents a single value to be


computed. When the program runs, each variable is replaced by its current value, and then the
operators are applied. The values operators work with are called operands.

51
The result of the previous example is:

<p>Number of minutes since midnight: 719</p>

Expressions are generally a combination of numbers, variables, and operators. When complied and
executed, they become a single value.

For example, the expression 1 + 1 has the value 2. In the expression hour - 1, C# replaces the
variable with its value, yielding 11 - 1, which has the value 10. In the expression hour * 60 +
minute, both variables get replaced, yielding 11 * 60 + 59. The multiplication happens first, yielding
660 + 59. Then the addition yields 719.

Addition, subtraction, and multiplication all do what you expect, but you might be surprised by
division. For example, the following fragment tries to compute the fraction of an hour that has
elapsed:

<p>Fraction of the hour that has passed:


@(minute / 60)</p>

The output is:

<p>Fraction of the hour that has passed: 0</p>

This result often confuses people. The value of minute is 59, and 59 divided by 60 should be 0.98333,
not 0. The problem is that C# performs “integer division” when the operands are integers. By
design, integer division always rounds toward zero, even in cases like this one where the next
integer is close.

As an alternative, we can calculate a percentage rather than a fraction:

<p>Percent of the hour that has passed:


@(minute * 100 / 60)</p>

The new output is:

<p>Percent of the hour that has passed: 98</p>

Again the result is rounded down, but at least now it’s approximately correct.

4.7.1. Assignment and arithmetic

C# defines several short-hand operators that combine arithmetic and assignment: +=, -=, *=, /=, and
%=.

These work like so:

52
x += 2;

means

x = x + 2;

The other operators work in the same manner.

There is an even shorter form for +1 and -1, the post-fix (after) and-- and pre-fix (before)
and — operators.

These have subtle impacts when embedded within other expressions.

x++ and ++x both add one to x, changing the value in the variable x. However, the value of x++ is x
before it is updated, while the value of ++x is the value of x after it is updated.

int x = 3;
int y, z;

y = x++; // y is now 3 and x is now 4


z = ++x; // z is now 5 and x is now 5

4.8. Floating-point numbers


A more general solution is to use floating-point numbers, which can represent fractions as well as
integers. In C#, the default floating-point type is called double, which is short for double-precision.
You can create double variables and assign values to them using the same syntax we used for the
other types:

double pi;
pi = 3.14159;

C# performs “floating-point division” when one or more operands are double values. So we can
solve the problem we saw in the previous section:

double minute = 59.0;


<p>Fraction of the hour that has passed:
@(minute / 60.0)</p>

The output is:

<p>Fraction of the hour that has passed: 0.9833333333333333</p>

53
Although floating-point numbers are useful, they can be a source of confusion. For example, C#
distinguishes the integer value 1 from the floating-point value 1.0, even though they seem to be the
same number. They belong to different data types, and strictly speaking, you are not allowed to
make assignments between types.

The following is illegal because the variable on the left is an int and the value on the right is a
double:

int x = 1.1; // compiler error

It is easy to forget this rule because in many cases C# automatically converts from one type to
another:

double y = 1; // legal, but bad style

The preceding example should be illegal, but C# allows it by converting the int value 1 to the double
value 1.0 automatically. This leniency is convenient, but it often causes problems for beginners. For
example:

double y = 1 / 3; // common mistake

You might expect the variable y to get the value 0.333333, which is a legal floating-point value. But
instead it gets the value 0.0. The expression on the right divides two integers, so C# does integer
division, which yields the int value 0. Converted to double, the value assigned to y is 0.0.

One way to solve this problem (once you figure out the bug) is to make the right-hand side a
floating-point expression. The following sets y to 0.333333, as expected:

double y = 1.0 / 3.0; // correct

As a matter of style, you should always assign floating-point values to floating-point variables. The
compiler won’t make you do it, but you never know when a simple mistake will come back and
haunt you.

4.8.1. Rounding errors

Most floating-point numbers are only approximately correct. Some numbers, like reasonably-sized
integers, can be represented exactly. But repeating fractions, like 1/3, and irrational numbers, like π,
cannot. To represent these numbers, computers have to round off to the nearest floating-point
number.

The difference between the number we want and the floating-point number we get is called
rounding error. For example, the following two statements should be equivalent:

54
<p>@(0.1 * 10)</p>
<p>@(0.1 + 0.1 + 0.1 + 0.1 + 0.1
  + 0.1 + 0.1 + 0.1 + 0.1 + 0.1)</p>

But on many machines, the output is:

<p>1.0</p>
<p>0.9999999999999999</p>

The problem is that 0.1, which is a terminating fraction in base 10, is a repeating fraction in base 2.

In base 2, 0.1 is 0.000110011… The … means that it keeps repepating 0011 over and
NOTE over again; the computer has to cut it off, so cannot represent this value precisely.
That is why they are called "floating point" or approximate numeric values.

So its floating-point representation is only approximate. When we add up the approximations, the
rounding errors accumulate.

For many applications, like computer graphics, encryption, statistical analysis, and multimedia
rendering, floating-point arithmetic has benefits that outweigh the costs. But if you need absolute
precision, use integers instead. For example, consider a bank account with a balance of $123.45:

double balance = 123.45; // potential rounding error

In this example, balances will become inaccurate over time as the variable is used in arithmetic
operations like deposits and withdrawals. The result would be angry customers and potential
lawsuits. You can avoid the problem by representing the balance as a decimal:

decimal balance = 123.45m; // decimal literal, 28 digits of precision

This solution works as long as the value does not exceed 28 digits.

Note that there is an m after the value — this tells the compiler the literal is a decimal literal, not a
double literal.

4.9. String operators


In general, you cannot perform mathematical operations on strings, even if the strings look like
numbers. The following expressions are illegal:

"Hello" - 1 "World" / 123 "Hello" * "World"

The + operator works with strings, but it might not do what you expect. For strings, the + operator

55
performs concatenation, which means joining end-to-end. So "Hello, " + "World!" yields the string
"Hello, World!".

Or if you have a variable called name that has type string, the expression "Hello, " + name appends
the value of name to the hello string, which creates a personalized greeting.

Since addition is defined for both numbers and strings, C# performs automatic conversions you
may not expect:

@(1 + 2 + "Hello") @* the value is 3Hello *@

@("Hello" + 1 + 2) @* the value is Hello12 *@

C# executes these operations from left to right. In the first line, 1 + 2 is 3, and 3 + "Hello" is
"3Hello". But in the second line, "Hello" + 1 is "Hello1", and "Hello1" + 2 is "Hello12".

4.9.1. string methods

In C#, even the primitive types are seen as objects. So, you can dot off of a string variable to invoke
any of the methods defined on the string type. Many useful methods are defined, including:

CompareTo compares the string to another string

Contains determines if the string contains another string


or character

EndsWith determines if the string ends with another string

Equals determines if the string is equal to another


string

IndexOf returns the first index of the provided char or


string within the string

IsNullOrEmpty returns true if the string is null or has no


characters

IsNullOrWhitespace returns true if the string is null or is a valid


whitespace character (such as a space, tab, or
other non-printing character)

LastIndexOf returns the last index of the provided char or


string within the string

PadLeft pads the string on the left with the provided


string or char

PadRight pads the string on the right with the provided


string or char

Remove removes the provided char or string from the


string

56
Replace replaces a given char or string within the string
with a new one

Split splits the string on the given char (returns an


array of strings)

StartsWith returns true if the string starts with the specified


char or string

ToLower converts the string to lower case

ToUpper converts the string to upper case

For the full list of string operators and their behavior, see https://msdn.microsoft.com/en-
us/library/system.string(v=vs.110).aspx

These methods do not actually change the current string — those that return strings create a new
string that holds the value described above. So to affect a variable, you would need to say, for
example:

string message = "Welcome to my Page";


string thanks = "Thanks for Shopping";
message = message.ToLower(); // message holds "welcome to my page"
thanks.ToLower(); // thanks holds "Thanks for Shopping"

The second call to ToLower returns the new string, but since it isn’t stored with an assignment
statement, it isn’t captured anywhere.

4.9.2. string extensions in Razor

In the Razor environment, string extensions provide a collection of conversion and test methods as
well:

AsBool, AsDateTime, AsDecimal, AsFloat, AsInt converts the string value to the specified type,
returns a 0/false if it was not the type

IsBool, IsDateTime, IsDecimal, IsFloat, IsInt returns true if the string value can be converted
to a value of the specified type

Any operators that would alter the string contents return a new string value, they do not modify the
underlying string value.

4.9.3. string properties

In addition there are two properties available on string variables:

Name Description

[x] Gets the char at position x in the string (there is


no dot operator before this)

57
Length Gets the number of characters in the string

4.9.4. ToString()

All types in C# define a method ToString() that converts the value of the type to a string value. This
is useful when you want to get a printable version of a value, or compare the value to that stored in
a string.

4.10. Comparison and Boolean Operators


C# has a primitive boolean type. These are very handy for storing simple states, testing conditions,
and other operations. We will see they are heavily used in the C# flow-of-control statements. They
take on only two values: true or false.

Having a boolean type means that we can discuss comparisons as expressions, since they take two
values and compare them, resulting in a true or a false.

Comparison operators are supplied on all of the primitive types that result in boolean values: <, >,
<=, >=, ==, !=, is. Note that == tests equality, not =, which is for assignment statements. is tests the
type of a value and is true if the value has the type specified. These operators are defined to work in
the logical way: numbers compare numerically, characters and strings compare from left to right
based on character values, and false < true for booleans. Classes can override these operators to
define them for a class as well.

We have to peek ahead just a little at objects to fully explain ==. == tests values for the built-in types,
but for objects it tests object identity. So == on two objects returns true if and only if they reference
the same object (or if they override the == operator, another possibility).

C# diverges from Java in how it tests string equality; string values are fully
fledged objects in Java, where they are built-in types in C#. One particular result
CAUTION
of this is that the C# == comparison on strings is a value comparison, while in
Java it is an identity comparison.

The operators that take booleans include

&& logical and both sides must be true for true


result

^^ logical exclusive or only one side can be true for


true result

! logical not (unary operator) reverses the value

4.11. Precedence of operators


When more than one operator appears in an expression, they are evaluated according to order of
operations. Generally speaking, C# evaluates operators from left to right (as we saw in the previous
section). But for numeric operators, C# follows mathematical conventions:

58
• Multiplication and division take “precedence” over addition and subtraction, which means they
happen first. So 1 + 2 * 3 yields 7, not 9, and 2 + 4 / 2 yields 4, not 3.

• If the operators have the same precedence, they are evaluated from left to right. So in the
expression minute * 100 / 60, the multiplication happens first; if the value of minute is 59, we
get 5900 / 60, which yields 98. If these same operations had gone from right to left, the result
would have been 59 * 1, which is incorrect.

• Any time you want to override the order of operations (or you are not sure what it is) you can
use parentheses. Expressions in parentheses are evaluated first, so (1 + 2) * 3 is 9. You can also
use parentheses to make an expression easier to read, as in (minute * 100) / 60, even though it
doesn’t change the result. Don’t work too hard to remember the order of operations, especially
for other operators. If it’s not obvious by looking at the expression, use parentheses to make it
clear.

There are many operators defined in C#, similar to those found in Java, C, and other languages. This
table provides the order of precedence of the operators from highest (first to evaluate) to lowest
(last to evaluate). When the order of precedence is the same, expressions are evaluated from left to
right.

Table 2. Precedence and Associativity of C# Operators

Symbol Type of Operation Associativity

() parentheses left to right

. ?. f(x) a[x] a?[x] x++ x-- new Primary: member access, null left to right
typeof sizeof conditional member access,
function invocation, aggregate
object indexing, null
conditional indexing, postfix
increment, postfix decrement,
type instantiation, type object,
size

+x -x !x ~x (T)x Unary positive, negative, Right to left


negation, bitwise negation, type
cast

*/% Multiplicative Left to right

+– Additive Left to right

<< >> Bitwise shift Left to right

< > <= >= Is As Relational and conversion Left to right

== != Equality Left to right

& Bitwise-AND Left to right

^ Bitwise-exclusive-OR Left to right

| Bitwise-inclusive-OR Left to right

&& Logical-AND Left to right

59
|| Logical-OR Left to right

?? Null coalesce Left to right

?: Conditional-expression Right to left

= *= /= %= assignments and lambda Right to left


+= –= <<= >>=
&= ^= |=
=>

There are additional operators not included here, see MSDN C# Operators.

Notice the Associativity column; English readers expect left-to-right associativity, which means the
operators are evaluated from left to right (1 + 2 + 3 is 3 + 3 is 6). However, the conditional
expression and the assignment statements have right-to-left associativity. This means their right
side is evaluated before their left side. For assignments this makes sense: the value to be assigned
has to be evaluated before it can be stored in the storage location, so x = y = 2 first assigns 2 to y
and then takes the value of that assignment expression, 2, and stores that in x.

4.12. Composition
So far we have looked at the elements of a programming language – variables, expressions, and
statements – in isolation, without talking about how to put them together.

One of the most useful features of programming languages is their ability to take small building
blocks and compose them. For example, we know how to multiply numbers and we know how to
display values. We can combine these operations into a single statement:

@(17 * 3)

Any arithmetic expression can be used inside an inline expression. We’ve already seen one
example:

@(hour * 60 + minute)

You can also put arbitrary expressions on the right side of an assignment:

@{
  int percentage;
  percentage = (minute * 100) / 60;
 }

The left side of an assignment must be a variable name, not an expression. That’s because the left
side indicates where the result will be stored, and expressions do not represent storage locations.

60
hour = minute + 1; // correct
minute + 1 = hour; // compiler error

The ability to compose operations may not seem impressive now, but we will see examples later on
that allow us to write complex computations neatly and concisely. But don’t get too carried away.
Large, complex expressions can be hard to read and debug.

Composition is used extensively with boolean expressions. For example, we might say

// can I sell a movie ticket?


bool okToSell = ((movie < 17) || (age >= 17)) && (cash > total);

In this code we are testing to see if we can sell a movie ticket: if the movie requires the person be
over 17, then we check their age; and they have to have the money to buy the ticket. Notice the use
of parentheses; the expression would not evaluate correctly without the outer pair on the left, since
&& is evaluated before || (but luckily () is evaluated before &&).

4.13. General operators


These operators work on a variety of types and return either the same type or another one

?? null coalescing x??y is y if x is null, otherwise it


is x

?: conditional operator x?y:z is y if x is true, otherwise


it is z

x++ postfix addition result is x before changing, but


x is incremented after that

++x prefix addition x is incremented and that new


value is the result

sizeof(x) size of gives the size in bytes of the


storage location or type

type(x) type of returns the object representing


the type of the storage location

4.14. Method calls


We have already shown you method calls, as we are making use of ASP.NET throughout our code.
When a method is called, it is called on an object (there is an implicit object for RenderBody, the
current page). We call this "dotting off" of the object. The function name is given, and then values
are specified to be passed to the method for it to use. These are called the method’s argument
values. Argument values can be literals, variables, expressions, and even other function calls. They
are evaluated and their value is copied and passed to the method. Any connection to a variable is
broken at that point, as in C# "pass by copy" is used, with a copy of the value going into the

61
method’s parameters for use in the method.

Methods can change the object they are invoked on, and can invoke methods on objects they are
passed to change their state as well. It is important ot understand that it is not the original variable
that changes, but only object state.

4.15. Classes and Objects


While we will not study objects in detail until a later chapter, it will be useful for you to know a
little about them and about a closely related topic: classes. ASP.NET’s functionality is provided as a
library of classes with properties and methods, and to understand what they are doing we need to
explain just a bit about objects and classes up front.

4.15.1. Built-in methods and properties

A method is a set of program instructions that have been chunked together and given a name. A
method is designed to perform some task. To get that task performed in a program, you can "call"
the method by dotting off of the object that it acts on. Later on you will learn how to write your own
classes and methods, but you can get a lot done in a program just by calling methods that have
already been written for you. In C#, every method is contained either in a class or in an object.
Some classes that are standard parts of the C# language contain predefined methods that you can
use. Even the primitive types are viewed as objects, and have methods that can be used to
manipulate them. These methods are "built into" the C# language, as part of ASP.NET. You can call
all these methods without understanding how they were written or how they work. Indeed, that’s
the whole point of methods: A method is a "black box" which can be used without knowing what
goes on inside.

Let’s first consider methods that are part of a class. One of the purposes of a class is to group
together some properties and methods, which are contained in that class. These properties and
methods are called static members of the class. You’ve seen one example: Math is actually a class,
and has a static member called Pi, a static property on the class. The parts of a class definition that
define static members are marked with the reserved word "static", as you will see when we cover
class definition.

When a class contains a static property or method, the name of the class is part of the full name of
the property or method. For example, the standard class named Math contains a method named
Abs. To use that method in your program, you must refer to it as Math.Abs. This full name consists
of the name of the class that contains the method, followed by a period, followed by the name of the
method. This method requires a number as parameter, and returns a new number that is the
absolute value, so you would actually use it with a method call expression such as

absVal = Math.Abs(val);

Calling Math.Abs will invoke a system utility provided in ASP.NET. That utility is provided in
compiled form, and in fact may not even have been written in C# — it doesn’t matter.

The Math class gives us an example of a class that contains static properties: Math.Pi and Math.E
whose values are the mathematical constants π and e. Math also contains a large number of

62
mathematical "functions." Every method performs some specific task. For some methods, that task
is to compute or retrieve some data value. Methods of this type are called functions. We say that a
function returns a value. Generally, the returned value is meant to be used somehow in the
program that calls the function.

You are familiar with the mathematical function that computes the square root of a number. The
corresponding function in C# is called Math.Sqrt. This function is a static method in the class named
Math. If x is any numerical value, then Math.Sqrt(x) computes and returns the square root of that
value. Since Math.Sqrt(x) represents a value, it doesn’t make sense to put it on a line by itself in a
call statement such as

Math.Sqrt(x); // This doesn't make sense!

What, after all, would the computer do with the value computed by the function in this case? You
have to tell the computer to do something with the value. You might tell the computer to display it:

<p>@Math.Sqrt(x)</p>

or you might use an assignment statement to tell the computer to store that value in a variable:

lengthOfSide = Math.Sqrt(x);

The function call Math.Sqrt(x) represents a value of type double, and it can be used anyplace where
a numeric literal of type double could be used.

The Math class contains many static member functions. Here is a list of some of the more important
of them:

• Math.Abs(x), which computes the absolute value of x.

• The usual trigonometric functions, Math.Sin(x), Math.Cos(x), and Math.Tan(x). (For all the
trigonometric functions, angles are measured in radians, not degrees.)

• The inverse trigonometric functions arcsin, arccos, and arctan, which are written as:
Math.Asin(x), Math.Acos(x), and Math.Atan(x). The return value is expressed in radians, not
degrees.

• The exponential function Math.Exp(x) for computing the number e raised to the power x, and
the natural logarithm function Math.Log(x) for computing the logarithm of x in the base e.

• Math.Pow(x,y) for computing x raised to the power y.

• Math.Floor(x), which rounds x down to the nearest integer value that is less than or equal to x.
Even though the return value is mathematically an integer, it is returned as a value of type
double, rather than of type int as you might expect. For example, Math.Floor(3.76) is 3.0. The
function Math.Round(x) returns the integer that is closest to x, and Math.Ceil(x) rounds x up to
an integer. ("Ceil" is short for "ceiling", the opposite of "floor.")

For these functions, the type of the parameter — the x or y inside the parentheses — can be any

63
value of any numeric type. For most of the functions, the value returned by the function is of type
double no matter what the type of the parameter. However, for Math.Abs(x), the value returned
will be the same type as x; if x is of type int, then so is Math.Abs(x). So, for example, while
Math.Sqrt(9) is the double value 3.0, Math.Abs(9) is the int value 9.

You also saw the useful class DateTime, which has the very useful static property Now. Now is itself
an object of type DateTime, representing the current system time. Because it is an object, not a
class, you can call the instance methods and access the instance properties defined on the DateTime
class. ("Instance" is the opposite of "static".) Instance properties and methods are defined for
objects, not classes; you have to have an object instance to access them.

It is useful to look at how long processing takes; to do that, you will need to access the Ticks
instance property on Now; this is the number of 100-nanosecond intervals since 12:00:00 midnight,
January 1, 0001. This is a long value. Recording this value at the start and after completion of a
section of code, lets you measure the time that it takes the computer to perform a task. Remember
that C# is executed on the web server, so the performance you are measuring is the web server’s
performance, not the client machine’s.

Here is a sample program that performs a few mathematical tasks and reports the time that it takes
for the program to run. On some computers, the time reported might be zero, because it is too small
to measure in ticks. Even if it’s not zero, you can be sure that most of the time reported by the
computer was spent doing output or working on tasks other than the program, since the
calculations performed in this program occupy only a tiny fraction of a 100-nanosecond interval of
a computer’s time.

64
Listing 3. TimedComputation.cshtml

<!DOCTYPE html>
<html>
<head><title>Timed Computation</title></head>
<body>

<p>We performed some mathematical computations on the server;


here are the results, and how long it took to perform them.</p>

@{
  // capture the start time
  DateTime startTime = DateTime.Now;

  <p>Time at the start is @startTime.</p>

  // Compute the hypotenuse of a fixed triangle:


  double width, height, hypotenuse; // sides of a triangle
  width = 42.0;
  height = 17.0;
  hypotenuse = Math.Sqrt( width*width + height*height );
  <p>A triangle with sides @width and @height
  has hypotenuse @hypotenuse.</p>

  // Compute a known mathematical value, see if double can handle it


  <p>Mathematically, <code>sin(x)*sin(x) + cos(x)*cos(x) - 1</code>
  should be 0.</p>
  <p>Let's check this for x = 1:<br/>
  <code>sin(1)*sin(1) + cos(1)*cos(1) - 1 =
  @(Math.Sin(1)*Math.Sin(1) + Math.Cos(1)*Math.Cos(1) - 1)
  </code></p>
  <p>(There can be round-off errors when computing with real numbers.)</p>

  // print a few random things...


  Random rand = new Random();
  <p>Here is a random number: @rand.NextDouble()</p>

  <p>The value of &pi; is @System.Math.PI</p>

  // figure out if time has passed ... how fast is your server?
  DateTime stopTime = DateTime.Now;
  TimeSpan elapsedTime = stopTime - startTime;

  <p>Time at the end is @stopTime.</p>


  <p>Run time was @(elapsedTime.TotalMilliseconds) milliseconds.</p>
}
</body>
</html>

65
If you get 0 time elapsed, that’s due to either the speed of your machine and the
inaccuracy of DateTime.Now. See
TIP
https://blogs.msdn.microsoft.com/ericlippert/2010/04/08/precision-and-accuracy-of-
datetime/ for an interesting writeup on this topic.

4.15.2. Classes and Objects

Classes can be containers for static properties and methods. However classes also have another
purpose. They are used to describe objects. In this role, the class is a type, in the same way that int
and double are types. That is, the class name can be used to declare variables. Such variables can
only hold one type of value. The values in this case are objects. An object is a collection of
properties and methods. Every object has an associated class that tells what "type" of object it is.
The class of an object specifies what properties and methods that object contains. All objects
defined by the same class are similar in that they contain similar collections of properties and
methods. For example, an object might represent a point in the plane, and it might contain
properties named x and y to represent the coordinates of that point. Every point object would have
an x and a y, but different points would have different values for these properties. A class, named
Point, for example, could exist to define the common structure of all point objects, and all such
objects would then be values of type Point.

As another example, let’s look at DateTime.Now.Time. DateTime is a class, and Now is a static
property within that class. However, the value of Date.Now is an object, and DateTime.Now.Time is
actually the full name of a property that is contained in the object DateTime.Now. You don’t need to
understand it at this point, but the object referred to by DateTime.Now is an object of the class
DateTime. Any object of type DateTime has a Time property that can be used to get the time value
from the object. The object in DateTime.Now is just one possible object, and DateTime.Now.Time is
a property of that value. Other objects of type DateTime will have a Time property that holds their
time value. This is object-oriented programming: Many different things which have something in
common — they can all be used to hold specific datetime values — can all be used in the same
way — through accessing a Time property. The DateTime class expresses the commonalities among
all these objects.

The dual role of classes can be confusing, and in practice most classes are designed to perform
primarily or exclusively in only one of the two possible roles. Fortunately, you will not need to
worry too much about it until we start working with objects in a more serious way, in a later
chapter.

By the way, since class names and variable names are used in similar ways, it might be hard to tell
which is which. Remember that all the built-in, predefined names in C# follow the rule that class
names begin with an upper case letter while variable names begin with a lower case letter. While
this is not a formal syntax rule, I strongly recommend that you follow it in your own programming.
Method and Property names should also begin with upper case letters. This way there is no
possibility of confusing a variable with a property, since a variables start with lower case and
properties with uppercase.

In other languages, you may run across the terms function and procedure — in non-OO languages,
there are no methods, but stand-alone named routines that are called directly, not dotted off of

66
classes or objects. A function returns a value, and a procedure does not. In C#, we call them both
methods, and put those that do not return values in statements and those that do return values in
expressions. If you put a function or method returning a value alone in a statement, then the value
that is returned is lost, not captured anywhere.

Java refers to properties as variables; however as we will see when we define classes, C# diverges
quite a bit from Java in how it defines properties, making them unique and more powerful than the
static and instance variables defined in Java classes.

4.15.3. The Random class

Some classes are very useful, but do not provide static properties. These require that you generate
instances usually for security or multi-processing thread safety. Random gives you the ability to
generate random numbers, very useful to simulate behavior in programs, as we will see throughout
this text.

However, when you generate a random number, you change the state of the Random object; if you
have methods that may run at the same time, you have to be careful that those methods do not
attempt to update the same object at the same time. This is referred to as thread safety. C# contains
syntax and operations to provide the ability to control object updates, however that is advanced C#
programming. We will rely on the fact that our code runs in a single thread, so we can safely create
a Random object instance and request numbers from it without being concerned about thread
safety.

How do you create an instance of a class? You use the special new expression and invoke a special
method on a class called a constructor. You will store this new object in a variable, like so:

Random rand = new Random();

Once you have a Random object instance, you have a variety of methods available to you:

Method Description

Next()] Returns a non-negative random integer.

Next(i)] Returns a non-negative random integer that is


less than the specified maximum integer i.

Next(low, high)] Returns a random integer that is within a


specified range of low..high.

NextBytes(Byte[])] Fills the elements of a specified array of bytes


with random numbers.

NextDouble()] Returns a random floating-point number that is


greater than or equal to 0.0, and less than 1.0.

Sample()] Returns a random floating-point number


between 0.0 and 1.0.

You would not create a new Random object for each random number you need — rather, you

67
should create a Random object and reuse it as much as possible within your code.

How random is Random? According to Microsoft, "The chosen numbers are not completely random
because a mathematical algorithm is used to select them, but they are sufficiently random for
practical purposes." Microsoft supplies cryptography classes that are more random, but have
slower performance. Read more about them here https://msdn.microsoft.com/en-
us/library/system.random(v=vs.110).aspx

4.15.4. Enums

C# has a very rich type system; it contains not only a significant set of primitive types and object-
oriented classes but also the ability to define structs — simple types that contain only fields; and
enums — simple types that have a limited number of values. As they cannot be directly defined in
Web Pages, we will save discussing them until we cover defining classes in C#.

4.16. Types of errors


Three kinds of errors can occur in a program: compile-time errors, run-time errors, and logic
errors. It is useful to distinguish among them in order to track them down more quickly.

Compile-time errors occur when you violate the syntax rules of the C# language. For example,
parentheses and braces have to come in matching pairs. So (1 + 2) is legal, but 8) is not. In the
latter case, the program cannot be compiled, and the compiler displays an error.

Error messages from the compiler usually indicate where in the program the error occurred, and
sometimes they can tell you exactly what the error is. As an example, let’s take a simple web page
body named Hello.cshtml:

Listing 4. Hello.cshtml

@{
  var message = "Hello, World";
  }

<p>@message</p>

If you forget the semicolon at the end of the variable declaration, you might get an error message
like this:

Hello.cshtml(7,33): error CS1002: ; expected

That’s pretty good: the location of the error is correct, and the error message tells you what’s
wrong.

But error messages are not always easy to understand. Sometimes the compiler reports the place in
the program where the error was detected, not where it actually occurred. And sometimes the
description of the problem is more confusing than helpful.

68
For example, if you leave out the closing brace at the end of the Razor block, you may get an error
like this:

Hello.cshtml(6): Build (web): The code block is missing a closing "}" character. Make
sure you have a matching "}" character for all the "{" characters within this block,
and that none of the "}" characters are being interpreted as markup.

There are two problems here. First, the error message is written from the compiler’s point of view,
not yours. Parsing is the process of reading a program before translating; if the compiler gets to the
end of the file while still parsing, that means something was omitted. But the compiler doesn’t
know what. It also doesn’t know where. The compiler discovers the error at the end of the program
(line 6), but the missing brace should be 2 lines above that.

Error messages contain useful information, so you should make an effort to read and understand
them. But don’t take them too literally.

During the first few weeks of your programming career, you will probably spend a lot of time
tracking down compile-time errors. But as you gain experience, you will make fewer mistakes and
find them more quickly.

The second type of error is a run-time error, so-called because it does not appear until after the
program has started running. In C#, these errors occur while the interpreter is executing byte code
and something goes wrong. These errors are also called “exceptions” because they usually indicate
that something exceptional (and bad) has happened.

Run-time errors are rare in the simple programs you will see in the first few chapters, so it might be
a while before you encounter one. When a run-time error occurs, the interpreter displays an error
message that explains what happened and where.

For example, if you accidentally divide by zero you will get a message like this in Visual Studio:

An exception of type 'System.DivideByZeroException' occurred in App_Web_zst0xju3.dll


but was not handled in user code

Additional information: Attempted to divide by zero.

Some parts of this output are useful for debugging. The first line includes the name of the
exception, System.DivideByZeroException', and a message that indicates more specifically what
happened, Attempted to divide by zero. If you look into the detail of the error (click View Detail…),
and then open the exception up, you will see the file where the error occurred in the Stack Trace:

69
  at ASP._Page_Hello_cshtml.Execute() in Hello.cshtml:line 13
  at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()
  at System.Web.WebPages.WebPage.ExecutePageHierarchy(IEnumerable`1 executors)
  at System.Web.WebPages.WebPage.ExecutePageHierarchy()
  at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext,
TextWriter writer, WebPageRenderingBase startPage)
  at System.Web.WebPages.WebPageHttpHandler.ProcessRequestInternal(HttpContextBase
httpContext)

It also reports the line number where the error occurred, 13. The other items listed in the stack
trace show the internal handling of your web page by the web server, and are unlikely to have
caused the issue.

Error messages sometimes contain additional information that won’t make sense yet. So one of the
challenges is to figure out where to find the useful parts without being overwhelmed by extraneous
information. Also, keep in mind that the line where the page crashed may not be the line that needs
to be corrected.

The third type of error is the logic error. If your program has a logic error, it will compile and run
without generating error messages, but it will not do the right thing. Instead, it will do exactly what
you told it to do. For example, here is a version of the hello world program with a logic error:

@{ hours = 11;
  minutes = 30;
 }

<p>The portion of the hour taken up is @(minutes/60)</p>

This program compiles and runs just fine, but the output is:

<p>The portion of the hour taken up is 0</p>

Assuming that we wanted the value 0.5, this is not correct. The problem is that the math is integer
division, when double precision was desired.

Identifying logic errors can be hard because you have to work backwards, looking at the output of
the program, trying to figure out why it is doing the wrong thing, and how to make it do the right
thing. Usually the compiler and the interpreter can’t help you, since they don’t know what the right
thing is.

Remember to re-read Chapter 1, to review some of our favorite debugging advice. It refers to
language features we haven’t talked about yet, so you might want to re-read it from time to time.

4.17. Data types in C#

70
type description range of values literal

byte 8-bit unsigned integer 0 - 255 whole number in range

sbyte 8-bit signed integer -128 - 127 whole number in range

short 16-bit signed integer -32,768 - 32,767 whole number in range

ushort 16-bit unsigned integer 0 - 65,535 whole number in range

int 32-bit signed integer - 2,147,483,648 - whole number i.e. 452


2,147,483,647

uint 32-bit unsigned integer 0 - 4,294,967,295 whole number in range

long 64-bit signed integer -9,223,372,036,854,775,8 whole number with l


08 .. sufficx, i.e. 452l
9,223,372,036,854,775,8
07

ulong 64-bit unsigned integer 0 .. ul suffix


18,446,744,073,709,551,
615

float 32-bit floating point (7 ±1.5e−45 to ±3.4e38 decimal number with f


digits) suffix

double 64-bit floating point (15 ±5.0e−324 to ±1.7e308 decimal number with
digits) optional d suffix

decimal 128-bit, 28 digits of -7922816251426433759 decimal number with


precision 3543950335 .. m suffix
79228162514264337593
543950335

char 16-bit Unicode U+0000 - U+FFFF single quotes around


character one character

string sequence of Unicode double quotes around 0


characters or more characters

bool Boolean value true or false true or false

object An object new creates one; null


(more on this later)

Implicit type conversion will occur when a loss of significant digits will not occur. For example, a
byte will be implicitly converted to an int (exactly) and even to a double (though the exact value
may be lost on the conversion) since the range of the double will fit the range of the byte.

From To

sbyte short, int, long, float, double, or decimal

byte short, ushort, int, uint, long, ulong, float,


double, or decimal

short int, long, float, double, or decimal

71
From To

ushort int, uint, long, ulong, float, double, or decimal

int long, float, double, or decimal

uint long, ulong, float, double, or decimal

long float, double, or decimal

char ushort, int, uint, long, ulong, float, double, or


decimal

float double

ulong float, double, or decimal

• Precision but not magnitude might be lost in the conversions from int, uint, long, or ulong to
float and from long or ulong to double.

• There are no implicit conversions to the char type. But note that char is treated as a numeric
that can convert to many other types.

• There are no implicit conversions between floating-point types and the decimal type. This is
because decimal is an exact numeric but the floating-point types are approximate numeric
types.

• A constant expression of type int can be converted to sbyte, byte, short, ushort, uint, or ulong,
provided the value of the constant expression is within the range of the destination type.

• There are no implicit conversions with boolean.

Explicit converstion can be done with the cast operator, like so:

double val = (double)42;

The type of the cast is put in parentheses in front of the expression being converted.

Notes on explicit conversions from Microsoft:

• The explicit numeric conversion may cause loss of precision or result in throwing exceptions.

• When you convert a decimal value to an integral type, this value is rounded towards zero to the
nearest integral value. If the resulting integral value is outside therange of the destination type,
an OverflowException is thrown.

• When you convert from a double or float value to an integral type, the value is truncated. If the
resulting integral value is outside the range of the destination value, the result depends on the
overflow checking context. In a checked context, an OverflowException is thrown, while in an
unchecked context, the result is an unspecified value of the destination type.

• When you convert double to float, the double value is rounded to the nearest float value. If the
double value is too small or too large to fit into the destination type, the result will be zero or
infinity.

• When you convert float or double to decimal, the source value is converted to decimal

72
representation and rounded to the nearest number after the 28th decimal place if required.
Depending on the value of the source value, one of the following results may occur:

• If the source value is too small to be represented as a decimal, the result becomes zero.

• If the source value is NaN (not a number), infinity, or too large to be represented as a
decimal, an OverflowException is thrown.

• When you convert decimal to float or double, the decimal value is rounded to the nearest
double or float value.

There is another type of conversion, a user-defined conversion. An example of this are the .AsInt(),
AsBoolean(), and other methods supplied on the string type which are used to convert the string to
a value of the other type. The rules are defined in the method as to how the conversion is done.

4.18. Namespaces
Every class in C# is contained in something called a namespace. Classes that are not explicitly put
into a namespace are in the "default" namespace. Almost all the examples in this textbook are in
the default namespace; we will look at namespaces further when we look at classes and objects in a
later chapter. However, the classes we use from ASP.NET will come from a variety of namespaces,
so we will take a look at them now.

Namespaces are a way of grouping classes, identifying them as filling a common purpose and
keeping them separate from classes with a different purpose. They use the dot notation we are
already familiar with from accessing properties and methods. You can define a namespace as a top-
level namespace or within another namespace. ASP.NET defines a top-level System namespace; the
classes that we use from ASP.NET are actually in the System namespace, which is "always available"
no matter what your current namespace is.

To use classes from other namespaces, you have to make them visible to your web page with a
@using statement:

@using System.Collections;

This makes the classes in the namespace System.Collections visible. We will be using collections
quite a bit when we look at databases in a later chapter.

Our Web Pages (.cshtml files) reside in the default namespace. We can do the same with our C#
classes, or place them into namespaces to keep them apart and organize them in groups based on
their use. C# classes will also include using statements to make classes in other namespaces visible
to them.

73
There are two files in Visual Studio Web Sites that contain further information about
namespaces: packages.config and web.config. These configuration files identify
namespaces that are not automatically available, and make them available to your
web pages. This is why, even though the Razor classes are defined in
System.Web.WebPages, you do not need to put a @using System.Web.WebPages in
each of your .cshtml files.
TIP

packages.config is managed for you by Visual Studio; VS will update it when you install
a package using the NuGet package manager.

If you later find there is a namespace that you use often, you can add it to web.config
to have it automatically available to all of your pages.

4.19. Further Reading


• C# Succinctly Chapter 2 https://www.syncfusion.com/resources/techportal/ebooks/csharp
(requires account)

• https://msdn.microsoft.com/en-us/library/cs7y5x0x(v=vs.90).aspx Data types

• https://msdn.microsoft.com/en-us/library/wew5ytx4(v=vs.90).aspx Variables

• https://msdn.microsoft.com/en-us/library/x53a06bb.aspx Keyword List

• https://msdn.microsoft.com/en-us/library/bb384061.aspx var declarations

• https://msdn.microsoft.com/en-us/library/y5b434w4.aspx implicit conversion

• https://msdn.microsoft.com/en-us/library/yht2cx7b.aspx explicit conversion

• https://msdn.microsoft.com/en-us/library/ms173105.aspx casting and conversions

• https://msdn.microsoft.com/en-us/library/ff926074.aspx coding conventions

• https://msdn.microsoft.com/en-us/library/system.string_methods(v=vs.110).aspx string methods

• https://msdn.microsoft.com/en-us/library/system.web.webpages.stringextensions(v=vs.111).aspx
string extensions

• https://msdn.microsoft.com/en-us/library/sbbt4032.aspx enum reference


https://msdn.microsoft.com/en-us/library/cc138362.aspx enum programming guide

4.20. Exercises
1. Find a partner and play “Stump the Newbie”:

Start with a web page that compiles and displays correctly. One player looks away while the
other player adds an error to the program. Then the first player tries to find and fix the error.
You get two points if you find the error without compiling the program, one point if you find it
using the compiler, and your opponent gets a point if you don’t find it.

2. The point of this exercise is (1) to use string concatenation to display values with different types
(int and string), and (2) to practice developing applications gradually by adding a few
statements at a time.

74
a. Create a new page named Date.cshtml. Copy or type in something like the hello world
program and make sure you can compile and run it.

b. Following the example in the text, write a program that creates variables named day, date,
month, and year. The variable day will contain the day of the week (like Friday), and date will
contain the day of the month (like the 13th). What type is each variable? Assign values to
those variables that represent today’s date.

c. Display the value of each variable on a line by itself. This is an intermediate step that is
useful for checking that everything is working so far. Compile and run your page before
moving on.

d. Modify the program so that it displays the date in standard American format, for example:
Thursday, July 16, 2015.

e. Modify the program so it also displays the date in European format. The final output should
be:

American format: Thursday, July 16, 2015

European format: Thursday 16 July 2015

3. The point of this exercise is to (1) use some of the arithmetic operators, and (2) start thinking
about compound entities (like time of day) that are represented with multiple values.

a. Create a new page called Time.cshtml. From now on, we won’t remind you to start with a
small, working program, but you should.

b. Following the example program in this chapter, create variables named hour, minute, and
second. Assign values that are roughly the current time. Use a 24-hour clock so that at 2pm
the value of hour is 14.

c. Make the program calculate and display the number of seconds since midnight.

d. Calculate and display the number of seconds remaining in the day.

e. Calculate and display the percentage of the day that has passed. You might run into
problems when computing percentages with integers, so consider using floating-point.

f. Change the values of hour, minute, and second to reflect the current time using
DateTime.Now.Hour, DateTime.Now.Minute, and DateTime.Now.Second. Then write code to
compute the elapsed time since you started working on this exercise. Hint: You might want
to use additional variables to hold values during the computation. Variables that are used in
a computation but never displayed are sometimes called “intermediate” or “temporary”
variables.

4. Write a Web Page that simulates rolling a pair of dice. You can simulate rolling one die by
choosing one of the integers 1, 2, 3, 4, 5, or 6 at random. The number you pick represents the
number on the die after it is rolled. As pointed out in this chapter, the expression
rand.NextInt(6) + 1 does the computation to select a random integer between 1 and 6 if rand
holds an instance of the class Random. You can assign this value to a variable to represent one
of the dice that are being rolled. Do this twice and add the results together to get the total roll.
The content of the <body> should all be generated in a Razor code block. Your Web Page should

75
report the number showing on each die as well as the total roll. For example:

The first die comes up 3


The second die comes up 5
Your total roll is 8

5. Write a Web Page that asks the user’s name, and then takes them to a new page that greets the
user by name. Before outputting the user’s name, convert it to upper case letters. For example, if
the user’s name is Fred, then the program should respond "Hello, FRED, nice to meet you!". This
should be two pages, with the form on the first page and the output on a separate page.

6. Write a Web Page that helps the user count his change. The program should ask how many
quarters, dimes, nickels, and pennies the user has. Then the program should tell the user how
much money he has, expressed in dollars. Do this as a single page application, and show the
values in the fields when you display the result. This will require putting a Razor code block
before the form, and using an inline expression to output the answer after the form. HTML
forms will display values using the value attribute on the form field elements.

7. If you have N eggs, then you have N/12 dozen eggs, with N%12 eggs left over. (This is essentially
the definition of the / and % operators for integers.) Write a Web Page that asks the user how
many eggs she has and then tells the user how many dozen eggs she has and how many extra
eggs are left over.

A gross of eggs is equal to 144 eggs. Extend your Web Page so that it will tell the user how many
gross, how many dozen, and how many left over eggs she has. For example, if the user says that
she has 1342 eggs, then your program would respond with

Your number of eggs is 9 gross, 3 dozen, and 10

since 1342 is equal to 9*144 + 3*12 + 10.

Implement this as a single page web application, and provide the user with an appropriate
message if the input value is not an integer.

8. This exercise asks you to write a Web Page that tests some of the built-in subroutines for
working with strings. The program should ask the user to enter their first name and their last
name, separated by a space, in one form field. Break the input string up into two strings, one
containing the first name and one containing the last name. You can do that by using the
IndexOf() subroutine to find the position of the space, and then using Substring() to extract each
of the two names. Also output the number of characters in each name, and output the user’s
initials. (The initials are the first letter of the first name together with the first letter of the last
name.) A sample output with the input "Mary Smith" should look something like this:

Your first name is Mary, which has 4 characters


Your last name is Smith, which has 5 characters
Your initials are MS

76
4.21. Project
One feature you may be using in your project is Geolocation, which is available in browsers as
shown here http://www.w3schools.com/html/html5_geolocation.asp.

http://apress.jensimmons.com/v5/pro-html5-programming/ch5.html a very thorough overview of


HTML5 geolocation with the distance formula shown below (which was found on stack overflow).

It’s pretty easy to find distance-between calculations in JavaScript, however you will need to do the
computation on the server side as you work through a large (potentially) database of locations
relative to the user’s current location. You don’t want to copy all the data to the client, so you will
need to do it on the server.

Write a web page that takes the user’s current location in a form, and then computes (on the same
page, like we did in the simple calculator in Chapter 3) the distance between the user’s location and
a fixed location of your choosing. Put that fixed location into constants in your code, do not hard
code the numbers within the computation.

http://stackoverflow.com/questions/365826/calculate-distance-between-2-gps-coordinates proposes
this code, among others:

Number.prototype.toRad = function() { return this * (Math.PI / 180); }

var R = 6371.0; // Earth's radius in kilometers


var Rm = 6378137.0; // meters
var Rft = Rm * 100.0/2.54/12.0; // feet
var Rmi = Rft/5280.0; // miles

var dLat = (lat2-lat1).toRad();


var dLon = (lon2-lon1).toRad();
var lat1 = lat1.toRad();
var lat2 = lat2.toRad();

var a = Math.sin(dLat/2) * Math.sin(dLat/2) +


  Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c; // km results, use the other vars for their results

(why yes, your C# code will look quite similar…)

http://www.movable-type.co.uk/scripts/latlong.html a bit too nerdy but interesting explanation

https://msdn.microsoft.com/en-us/library/system.math_methods(v=vs.110).aspx C#'s Math class


contains the PI property and the methods needed. You will have to repeat the code to convert
values to radians many times as we have not yet discussion functions, and there is no toRad
function in ASP.NET. You will be able to make it a function after chapter 7, when methods are
introduced.

77
Chapter 5. C# Statements, Arrays, and
Objects
This material is derived from Chapter 3 in Introduction to Programming Using Java

The basic building blocks of programs — variables, expressions, assignment statements, and


subroutine call statements — were covered in the previous chapter. Starting with this chapter, we
look at how these building blocks can be put together to build complex programs with more
interesting behavior.

Since we are still working on the level of "programming in the small" in this chapter, we are
interested in the kind of complexity that can occur within a small block of code. On this level,
complexity is provided by control structures. The two types of control structures, loops and
branches, can be used to repeat a sequence of statements over and over or to choose among two or
more possible courses of action. C# includes several control structures of each type, and we will
look at each of them in some detail.

Program complexity can be seen not just in control structures but also in data structures. A data
structure is an organized collection of data, chunked together so that it can be treated as a unit. We
will end this chapter with an introduction to one of the most common data structures: arrays.

5.1. Blocks, Loops, and Branches


The ability of a computer to perform complex tasks is built on just a few ways of combining simple
commands into control structures. In Java, there are just six such structures that are used to
determine the normal flow of control in a program — and, in fact, just three of them would be
enough to write programs to perform any task. The six control structures are: the block, the while
loop, the do..while loop, the for loop, the if statement, and the switch statement. Each of these
structures is considered to be a single "statement," but a structured statement that can contain one
or more other statements inside itself.

5.1.1. Blocks

The block is the simplest type of structured statement. Its purpose is simply to group a sequence of
statements into a single statement. The format of a block is:

{
  statements
}

That is, it consists of a sequence of statements enclosed between a pair of braces, "{" and "}". In fact,
it is possible for a block to contain no statements at all; such a block is called an empty block, and
can actually be useful at times. An empty block consists of nothing but an empty pair of braces.
Block statements usually occur inside other statements, where their purpose is to group together
several statements into a unit. However, a block can be legally used wherever a statement can
occur. There is one place where a block is required: As you might have already noticed in the case

78
of the main subroutine of a program, the definition of a subroutine is a block, since it is a sequence
of statements enclosed inside a pair of braces.

I should probably note again at this point that C# is what is called a free-format language. There are
no syntax rules about how the language has to be arranged on a page. So, for example, you could
write an entire block on one line if you want. But as a matter of good programming style, you
should lay out your program on the page in a way that will make its structure as clear as possible.
In general, this means putting one statement per line and using indentation to indicate statements
that are contained inside control structures. This is the format that I will generally use in my
examples.

Here are two examples of blocks:

{
  intro="The answer is ";
  message=intro+ans;
}

{ // This block exchanges the values of x and y


  int temp; // A temporary variable for use in this block.
  temp = x; // Save a copy of the value of x in temp.
  x = y; // Copy the value of y into x.
  y = temp; // Copy the value of temp into y.
}

In the second example, a variable, temp, is declared inside the block. This is perfectly legal, and it is
good style to declare a variable inside a block if that variable is used nowhere else but inside the
block. A variable declared inside a block is completely inaccessible and invisible from outside that
block. When the computer executes the variable declaration statement, it allocates memory to hold
the value of the variable. When the block ends, that memory is discarded (that is, made available
for reuse). The variable is said to be local to the block. There is a general concept called the "scope"
of an identifier. The scope of an identifier is the part of the program in which that identifier is valid.
The scope of a variable defined inside a block is limited to that block, and more specifically to the
part of the block that comes after the declaration of the variable.

Block activation records

Every time a block is entered, if it has local parameters, an activation record is created on the
"activation stack", a portion of memory reserved for executing code. When the block completes, its
activation record is destroyed and removed from the stack. This means that a local variable defined
within a block does not keep its value with each subsequent trip to the same block - it is gone at the
end of the block, and created again anew when the block is re-entered.

5.1.2. The Basic While Loop

The block statement by itself really doesn’t affect the flow of control in a program. The five
remaining control structures do. They can be divided into two classes: loop statements and
branching statements. You really just need one control structure from each category in order to

79
have a completely general-purpose programming language. More than that is just convenience. In
this section, I’ll introduce the while loop and the if statement. I’ll give the full details of these
statements and of the other three control structures in later sections.

A while loop is used to repeat a given statement over and over. Of course, it’s not likely that you
would want to keep repeating it forever. That would be an infinite loop, which is generally a bad
thing. (There is an old story about computer pioneer Grace Murray Hopper, who read instructions
on a bottle of shampoo telling her to "lather, rinse, repeat." As the story goes, she claims that she
tried to follow the directions, but she ran out of shampoo. (In case you don’t get it, this is a joke
about the way that computers mindlessly follow instructions.))

To be more specific, a while loop will repeat a statement over and over, but only so long as a
specified condition remains true. A while loop has the form:

while (boolean-expression)
  statement

Since the statement can be, and usually is, a block, most while loops have the form:

while (boolean-expression) {
  statements
}

Some programmers think that the braces should always be included as a matter of style, even when
there is only one statement between them, but I don’t always follow that advice myself.

C# in Razor requires the braces on the body of the while statement — even


WARNING when it is a single statement. It also requires them on the body of an if
statement and the other looping statements of the language.

The semantics of the while statement go like this: When the computer comes to a while statement, it
evaluates the boolean-expression, which yields either true or false as its value. If the value is false,
the computer skips over the rest of the while loop and proceeds to the next command in the
program. If the value of the expression is true, the computer executes the statement or block of
statements inside the loop. Then it returns to the beginning of the while loop and repeats the
process. That is, it re-evaluates the boolean-expression, ends the loop if the value is false, and
continues it if the value is true. This will continue over and over until the value of the expression is
false when the computer evaluates it; if that never happens, then there will be an infinite loop.

Here is an example of a while loop that simply prints out the numbers 1, 2, 3, 4, 5:

80
string message = ""; // build up a message
int number; // The number to be tracked.
number = 1; // Start with 1.
while ( number < 6 ) { // Keep going as long as number is < 6.
  message= message+" "+number;
  number = number + 1; // Go on to the next number.
}
//value in message is "1 2 3 4 5".

The variable number is initialized with the value 1. So when the computer evaluates the expression
"number < 6" for the first time, it is asking whether 1 is less than 6, which is true. The computer
therefore proceeds to execute the two statements inside the loop. The first statement adds " 1" to
message. The second statement adds 1 to number and stores the result back into the variable
number; the value of number has been changed to 2. The computer has reached the end of the loop,
so it returns to the beginning and asks again whether number is less than 6. Once again this is true,
so the computer executes the loop again, this time adding " 2" to the message and then changing the
value of number to 3. It continues in this way until eventually number becomes equal to 6. At that
point, the expression "number < 6" evaluates to false. So, the computer jumps past the end of the
loop to the next statement after the loop. Note that when the loop ends, the value of number is 6,
but the last value that was put into message was 5.

By the way, you should remember that you’ll never see a while loop standing by itself in a real
program. It will always be inside a web page or C# method which is itself defined inside some class.
As an example of a while loop, here is a little program that computes the interest on an investment
over several years.

Listing 5. InvestmentValue.cshtml

@{
  double principal; // The value of the investment.
  double rate; // The annual interest rate.
  string message="";

  /* Get the initial investment and interest rate from the user. */
  if (IsPost) {
  principal = (double) Request["principal"].AsDecimal(); ①

  rate = (double) Request["rate"].AsDecimal();

  /* Simulate the investment for 5 years. */

  int years; // Counts the number of years that have passed.

  years = 0;
  while (years < 5) {
  double interest; // Interest for this year.
  interest = principal * rate;
  principal = principal + interest; // Add it to principal.
  years = years + 1; // Count the current year.

81
  message = "The value of the investment after "+years
  + " years is $" + String.Format("{0:0.00}",principal); ②
  } // end of while loop

  }
}

<!DOCTYPE html>
<html>
  <head>
  <title>Add Numbers</title>

  <style type="text/css">
  body {background-color: beige; font-family: Verdana, Arial;
  margin: 50px; }
  form {padding: 10px; border-style: solid; width: 250px;}
  </style>
  </head>

  <body>
  <p>Enter two numbers and then click <strong>Calculate</strong>.</p>
  <form action="" method="post">
  <p><label for="principal">Initial investment:</label>
  <input type="text" name="principal" />
  </p>
  <p><label for="rate">Interest rate (decimal, not percentage):</label>
  <input type="text" name="rate" />
  </p>
  <p><input type="submit" value="Calculate" /></p>
  </form>

  <p>@message</p>
  </body>
</html>

You should study this program, and make sure that you understand what the computer does step-
by-step as it executes the while loop.

① Note the use of .AsDecimal() and the typecast to (double) — this is required because there is no
.AsDouble() method available on strings. We could choose, instead, to keep all of our numbers as
decimals and avoid the typecast.

② The raw double value gives all the digits, but since we are dealing with money we want to
display it in a shorter form showing just the money-relevant digits. There is a system String
object (which is also a class — more on this later in this text) that provides a Format method for
creating the string representation of the double value. Format’s input is quite rich, this is just a
first example. See https://msdn.microsoft.com/en-us/library/system.string.format(v=vs.110).aspx
for details on using this.

82
Go ahead and modify our page to use just decimals and avoid the typecast to double.
TIP This may take some debugging — more than just principal and rate need to be
changed. Consider why all of the changes were necessary.

Modify the page so that the value is displayed in the form after the POST request, so
that the user can see their values when the results are displayed. Put the numbers in
TIP
the form fields directly. Consider why you can do this — and in future pages, consider
revisitng this and how the code on the page has to change to make it work.

5.1.3. The Basic If Statement

An if statement tells the computer to take one of two alternative courses of action, depending on
whether the value of a given boolean-valued expression is true or false. It is an example of a
"branching" or "decision" statement. An if statement has the form:

if ( boolean-expression )
  statement1
else
  statement2

Remember, Razor will require that the statements in the if and else always have
CAUTION
braces, even if there is just a single statement within it.

When the computer executes an if statement, it evaluates the boolean expression. If the value is
true, the computer executes the first statement and skips the statement that follows the "else". If the
value of the expression is false, then the computer skips the first statement and executes the second
one. Note that in any case, one and only one of the two statements inside the if statement is
executed. The two statements represent alternative courses of action; the computer decides
between these courses of action based on the value of the boolean expression.

In many cases, you want the computer to choose between doing something and not doing it. You
can do this with an if statement that omits the else part:

if ( boolean-expression )
  statement

To execute this statement, the computer evaluates the expression. If the value is true, the computer
executes the statement that is contained inside the if statement; if the value is false, the computer
skips over that statement. In either case, the computer then continues with whatever follows the if
statement in the program.

Sometimes, novice programmers confuse while statements with simple if statements (with no else
part), although their meanings are quite different. The statement in an if is executed at most once,
while the statement in a while can be executed any number of times. It can be helpful to look at
diagrams of the the flow of control for while and simple if statements:

83
In these diagrams, the arrows represent the flow of time as the statement is executed. Control
enters the diagram at the top and leaves at the bottom. Similarly, a flow control diagram for an
if..else statement makes it clear that exactly one of the two nested statements is executed:

Of course, either or both of the statements in an if statement can be a block, and again many
programmers prefer to add the braces even when they contain just a single statement. So an if
statement often looks like:

84
if ( boolean-expression ) {
  statements
}
else {
  statements
}

or:

if ( boolean-expression ) {
  statements
}

As an example, here is an if statement that exchanges the value of two variables, x and y, but only if
x is greater than y to begin with. After this if statement has been executed, we can be sure that the
value of x is definitely less than or equal to the value of y:

if ( x > y ) {
  int temp; // A temporary variable for use in this block.
  temp = x; // Save a copy of the value of x in temp.
  x = y; // Copy the value of y into x.
  y = temp; // Copy the value of temp into y.
}

Finally, here is an example of an if statement that includes an else part. See if you can figure out
what it does, and why it would be used:

if ( years > 1 ) { // handle case for 2 or more years


  message="The value of the investment after "
  + years + " years is $";
}
else { // handle case for 1 year
  message="The value of the investment after 1 year is $";
} // end of if statement
message += principal; // this is done in any case

I’ll have more to say about control structures later in this chapter. But you already know the
essentials. If you never learned anything more about control structures, you would already know
enough to perform any possible computing task. Simple looping and branching are all you really
need!

5.1.4. Definite Assignment

I will finish this introduction to control structures with a somewhat technical issue that you might
not fully understand the first time you encounter it. Consider the following two code segments,

85
which seem to be entirely equivalent:

int y; int y;
if (x < 0) { if (x < 0) {
  y = 1; y = 1;
} }
else { if (x >= 0) {
  y = 2; y = 2;
} }
message = "answer is "+y; message = "answer is "+y;

In the version on the left, y is assigned the value 1 if x < 0 and is assigned the value 2 otherwise, that
is, if x >= 0. Exactly the same is true of the version on the right. However, there is a subtle
difference. In fact, the Java compiler will report an error for the final statement in the code on the
right, while the code on the left is perfectly fine!

The problem is that in the code on the right, the computer can’t tell that the variable y has
definitely been assigned a value. When an if statement has no else part, the statement inside the if
might or might not be executed, depending on the value of the condition. The compiler can’t tell
whether it will be executed or not, since the condition will only be evaluated when the program is
running. For the code on the right above, as far as the compiler is concerned, it is possible that
neither statement, y = 1 or y = 2, will be evaluated, so it is possible that the output statement is
trying to print an undefined value. The compiler considers this to be an error. The value of a
variable can only be used if the compiler can verify that the variable will have been assigned a
value at that point when the program is running. This is called definite assignment. (It doesn’t
matter that you can tell that y will always be assigned a value in this example. The question is
whether the compiler can tell.)

Note that in the code on the left above, y is definitely assigned a value, since in an if..else statement,
one of the two alternatives will be executed no matter what the value of the condition in the if. It is
important that you understand that there is a difference between an if..else statement and a pair of
plain if statements. Here is another pair of code segments that might seem to do the same thing, but
don’t. What’s the value of x after each code segment is executed?

int x; int x;
x = -1; x = -1;
if (x < 0) if (x < 0)
  x = 1; x = 1;
else if (x >= 0)
  x = 2; x = 2;

After the code on the left is executed, x is 1; after the code on the right, x is 2.

86
5.2. Algorithm Development
Programming is difficult (like many activities that are useful and worthwhile — and like most of
those activities, it can also be rewarding and a lot of fun). When you write code, you have to tell the
computer every small detail of what to do. And you have to get everything exactly right, since the
computer will blindly follow your code exactly as written. How, then, do people write any but the
most simple programs? It’s not a big mystery, actually. It’s a matter of learning to think in the right
way.

A program is an expression of an idea. A programmer starts with a general idea of a task for the
computer to perform. Presumably, the programmer has some idea of how to perform the task by
hand, at least in general outline. The problem is to flesh out that outline into a complete,
unambiguous, step-by-step procedure for carrying out the task. Such a procedure is called an
"algorithm." (Technically, an algorithm is an unambiguous, step-by-step procedure that always
terminates after a finite number of steps. We don’t want to count procedures that might go on
forever.) An algorithm is not the same as a program. A program is written in some particular
programming language. An algorithm is more like the idea behind the program, but it’s the idea of
the steps the program will take to perform its task, not just the idea of the task itself. When
describing an algorithm, the steps don’t necessarily have to be specified in complete detail, as long
as the steps are unambiguous and it’s clear that carrying out the steps will accomplish the assigned
task. An algorithm can be expressed in any language, including English. Of course, an algorithm can
only be expressed as an actual program if all the details have been filled in.

So, where do algorithms come from? Usually, they have to be developed, often with a lot of thought
and hard work. Skill at algorithm development is something that comes with practice, but there are
techniques and guidelines that can help. I’ll talk here about some techniques and guidelines that
are relevant to "programming in the small," and I will return to the subject several times in later
chapters.

5.2.1. Pseudocode and Stepwise Refinement

When programming in the small, you have a few basics to work with: variables, assignment
statements, and input/output. You might also have some routines, objects, or other building blocks
that have already been written by you or someone else. (ASP.NET libraries and their routines fall
into this class.) You can build sequences of these basic instructions, and you can also combine them
into more complex control structures such as while loops and if statements.

Suppose you have a task in mind that you want the computer to perform. One way to proceed is to
write a description of the task, and take that description as an outline of the algorithm you want to
develop. Then you can refine and elaborate that description, gradually adding steps and detail,
until you have a complete algorithm that can be translated directly into programming language.
This method is called stepwise refinement, and it is a type of top-down design. As you proceed
through the stages of stepwise refinement, you can write out descriptions of your algorithm in
pseudocode — informal instructions that imitate the structure of programming languages without
the complete detail and perfect syntax of actual program code.

87
The informal description is not written in a programming language, but is expressed
in pseudocode, which can be a mix of simple English statements and some
TIP programming terminology as you will see in our examples here. There is no 'standard'
pseudocode language — simply write out the text in a way that is understandable to
you and should be understandable to a peer as well.

As an example, let’s see how one might develop the application from the previous section, which
computes the value of an investment over five years. The task that you want the application to
perform is: "Compute and display the value of an investment for each of the next five years, where
the initial investment and interest rate are to be specified by the user." You might then write — or
more likely just think — that this can be expanded as:

Get the user's input


Compute the value of the investment after 1 year
Display the value
Compute the value after 2 years
Display the value
Compute the value after 3 years
Display the value
Compute the value after 4 years
Display the value
Compute the value after 5 years
Display the value

This is correct, but rather repetitive. And seeing that repetition, you might notice an opportunity to
use a loop. A loop would take less typing. More important, it would be more general: Essentially the
same loop will work no matter how many years you want to process. So, you might rewrite the
above sequence of steps as:

Get the user's input


while there are more years to process:
  Compute the value after the next year
  Display the value

Following this algorithm would certainly solve the problem, but for a computer we’ll have to be
more explicit about how to "Get the user’s input," how to "Compute the value after the next year,"
and what it means to say "there are more years to process." We can expand the step, "Get the user’s
input" into

Ask the user for the initial investment


Read the user's response
Ask the user for the interest rate
Read the user's response

88
Remember, we are working with a web page, so we "ask" with a form and "read
TIP
response" with the POST request using the Response object available to us there.

To fill in the details of the step "Compute the value after the next year," you have to know how to do
the computation yourself. (Maybe you need to ask your boss or professor for clarification?) Let’s
say you know that the value is computed by adding some interest to the previous value. Then we
can refine the while loop to:

while there are more years to process:


  Compute the interest
  Add the interest to the value
  Display the value

As for testing whether there are more years to process, the only way that we can do that is by
counting the years ourselves. This displays a very common pattern, and you should expect to use
something similar in a lot of programs: We have to start with zero years, add one each time we
process a year, and stop when we reach the desired number of years. This is sometimes called a
counting loop. So the while loop becomes:

years = 0
while years < 5:
  years = years + 1
  Compute the interest
  Add the interest to the value
  Display the value

We still have to know how to compute the interest. Let’s say that the interest is to be computed by
multiplying the interest rate by the current value of the investment. Putting this together with the
part of the algorithm that gets the user’s inputs, we have the complete algorithm:

Ask the user for the initial investment ①


Read the user's response ②
Ask the user for the interest rate ①
Read the user's response ②
years = 0
while years < 5: ③
  years = years + 1
  Compute interest = value * interest rate
  Add the interest to the value
  Display the value ④

The numbers above correspond the the number markers in the finished code below.

Finally, we are at the point where we can translate pretty directly into proper programming-
language syntax. We still have to choose names for the variables, decide exactly what we want to
say to the user, and so forth. Having done this, we could express our algorithm in C# as:

89
Listing 6. InvestmentValue2.cshtml

<!DOCTYPE html>
<html>
  <head>
  <title>Compute Investment Value</title>

  <style type="text/css">
  body {background-color: beige; font-family: Verdana, Arial;
  margin: 50px; }
  form {padding: 10px; border-style: solid; width: 250px;}
  </style>
  </head>

  <body>
  <p>Enter two numbers and then click <strong>Calculate</strong>.</p>
  <form action="" method="post"> ①
  <p><label for="principal">Initial investment:</label>
  <input type="text" name="principal" />
  </p>
  <p><label for="rate">Interest rate (decimal, not percentage):</label>
  <input type="text" name="rate" />
  </p>
  <p><input type="submit" value="Calculate" /></p>
  </form>

  @{
  double principal; // The value of the investment.
  double rate; // The annual interest rate.
  string message="";

  /* Get the initial investment and interest rate from the user. */
  if (IsPost) {
  principal = Request["principal"].AsDouble(); ②

  rate = Request["rate"].AsDouble();

  /* Simulate the investment for 5 years. */

  int years; // Counts the number of years that have passed.

  years = 0;
  while (years < 5) { ③
  double interest; // Interest for this year.
  interest = principal * rate;
  principal = principal + interest; // Add it to principal.
  years = years + 1; // Count the current year.
  <p>@years : @principal</p> ④
  } // end of while loop

  }

90
  }
  </body>
</html>

This still needs to be wrapped inside a complete website, it still needs to be commented, and it
really needs to print out more information in a nicer format for the user. But it’s essentially the
same application as the one in the previous section. (Note that the pseudocode algorithm used
indentation to show which statements are inside the loop. In C#, indentation is completely ignored
by the computer, so you need a pair of braces to tell the computer which statements are in the loop.
If you leave out the braces, the only statement inside the loop would be "double interest;". The other
statements would only be executed once, after the loop ends. The nasty thing is that the computer
won’t notice this error for you, like it would if you left out the parentheses around "(years < 5)". The
parentheses are required by the syntax of the while statement. The braces are only required
semantically. The computer can recognize syntax errors but not semantic errors.)

One thing you should have noticed here is that my original specification of the
problem — "Compute and display the value of an investment for each of the next five years" — was
far from being complete. Before you start writing a program, you should make sure you have a
complete specification of exactly what the application is supposed to do. In particular, you need to
know what information the application is going to input and output and what computation it is
going to perform. Here is what a reasonably complete specification of the problem might look like
in this example:

"Write an application that will compute and display the value of an investment for each of the next
five years. Each year, interest is added to the value. The interest is computed by multiplying the
current value by a fixed interest rate. Assume that the initial value and the rate of interest are to be
input by the user when the program is run."

5.2.2. The 3N+1 Problem

Let’s do another example, working this time with a program that you haven’t already seen. The
assignment here is an abstract mathematical problem that is one of my favorite programming
exercises. This time, we’ll start with a more complete specification of the task to be performed:

"Given a positive integer, N, define the '3N+1' sequence starting from N as follows: If N is an even
number, then divide N by two; but if N is odd, then multiply N by 3 and add 1. Continue to generate
numbers in this way until N becomes equal to 1. For example, starting from N = 3, which is odd, we
multiply by 3 and add 1, giving N = 3*3+1 = 10. Then, since N is even, we divide by 2, giving N = 10/2
= 5. We continue in this way, stopping when we reach 1. The complete sequence is: 3, 10, 5, 16, 8, 4,
2, 1.

"Write a program that will read a positive integer from the user and will print out the 3N+1
sequence starting from that integer. The program should also count and print out the number of
terms in the sequence."

A general outline of the algorithm for the program we want is:

91
  Get a positive integer N from the user.
  Compute, print, and count each number in the sequence.
  Output the number of terms.

The bulk of the program is in the second step. We’ll need a loop, since we want to keep computing
numbers until we get 1. To put this in terms appropriate for a while loop, we need to know when to
continue the loop rather than when to stop it: We want to continue as long as the number is not 1.
So, we can expand our pseudocode algorithm to:

Get a positive integer N from the user;


while N is not 1:
  Compute N = next term;
  Output N;
  Count this term;
Output the number of terms;

In order to compute the next term, the computer must take different actions depending on whether
N is even or odd. We need an if statement to decide between the two cases:

Get a positive integer N from the user;


while N is not 1:
  if N is even:
  Compute N = N/2;
  else
  Compute N = 3 * N + 1;
  Output N;
  Count this term;
Output the number of terms;

We are almost there. The one problem that remains is counting. Counting means that you start with
zero, and every time you have something to count, you add one. We need a variable to do the
counting. The variable must be set to zero once, before the loop starts, and it must be incremented
within the loop. (Again, this is a common pattern that you should expect to see over and over.) With
the counter added, we get:

Get a positive integer N from the user;


Let counter = 0;
while N is not 1:
  if N is even:
  Compute N = N/2;
  else
  Compute N = 3 * N + 1;
  Output N;
  Add 1 to counter;
Output the counter;

92
We still have to worry about the very first step. How can we get a positive integer from the user? If
we just read in a number, it’s possible that the user might type in a negative number or zero. If you
follow what happens when the value of N is negative or zero, you’ll see that the program will go on
forever, since the value of N will never become equal to 1. This is bad. In this case, the problem is
probably no big deal, but in general you should try to write programs that are foolproof. One way
to fix this is to keep reading in numbers until the user types in a positive number:

Ask user to input a positive number;


Let N be the user's response;
while N is not positive:
  Print an error message;
  Read another value for N;
Let counter = 0;
while N is not 1:
  if N is even:
  Compute N = N/2;
  else
  Compute N = 3 * N + 1;
  Output N;
  Add 1 to counter;
Output the counter;

Getting input on a web page can be checked on the client-side in JavaScript to avoid sending the
value to the server until it is valid. However, the value would still need to be checked on the server
in case a user turned off JavaScript. So we need to think about how that works:

1. Give the user a form to fill out

2. Accept the submitted form

3. Check the values

4. If the values are not valid, return to step 1

In pseudocode, we can express this as a while, however in actual code we will be re-displaying the
form and requesting valid data without using an explicit loop; the web page does it for us.

So, the first loop will end only when N is a positive number, as required. (A common beginning
programmer’s error is to use an if statement instead of a while statement here: "If N is not positive,
ask the user to input another value." The problem arises if the second number input by the user is
also non-positive. The if statement is only executed once, so the second input number is never
tested, and the program proceeds into an infinite loop. With the loop, after the second number is
input, the computer jumps back to the beginning of the loop and tests whether the second number
is positive. If not, it asks the user for a third number, and it will continue asking for numbers until
the user enters an acceptable input. After the input loop ends, we can be absolutely sure that N is a
positive number.)

Here is the C# implementing this algorithm. It uses the operators <= to mean "is less than or equal
to" and != to mean "is not equal to." To test whether N is even, it uses "N % 2 == 0". All the operators
used here were discussed in the previous chapter.

93
Listing 7. ThreeNPlusOne.cshtml

<!DOCTYPE html>
<html>
  <head>
  <title>3N+1 sequence</title>

  <style type="text/css">
  body {background-color: beige; font-family: Verdana, Arial;
  margin: 50px; }
  form {padding: 10px; border-style: solid; width: 250px;}
  </style>
  </head>

  <body>
  <p>Enter a numbers and then click <strong>Show</strong>.</p>
  <form action="" method="post">
  <p><label for="principal">Number:</label>
  <input type="text" name="num" />
  </p>
  <p><input type="submit" value="Show" /></p>
  </form>

  @{
  int num; // The value of the investment.

  /* Get the initial number from the user. */


  if (IsPost) {
  num = Request["num"].AsInt();

  if (num <= 0) { ①
  <p>Number must be &gt; 0, try again.</p>
  } else {
  // At this point, we know that N > 0

  /**
  * This prints out a 3N+1 sequence starting from a positive
  * integer specified by the user. It also counts the number of
  * terms in the sequence, and prints out that number.
  */

  int counter = 0;
  while (num != 1) { ②
  if (num % 2 == 0) {
  num = num / 2;
  }
  else {
  num = 3 * num + 1;
  }
  <p>@num</p>
  counter = counter + 1;

94
  }

  <p>There were @counter terms in the sequence.</p>


  } // end num > 0

  } // end IsPost
  }
  </body>
</html>

① As you can see, this is written as a simple if statement; however it leaves us on the web page, so
the form is available and the user can re-enter data and try again. Notice that web pages give
users another, unspoken, option as well: they can choose not to continue and move on to
another page. This is actually quite powerful; in a stand-alone application, you would have to
explicitly give users a way to quit the program at any input step.

② The second loop remains a loop — it is generating output as it executes.

Two final notes on this program: First, you might have noticed that the first term of the
sequence — the value of N input by the user — is not printed or counted by this program. Is this an
error? It’s hard to say. Was the specification of the program careful enough to decide? This is the
type of thing that might send you back to the boss/professor for clarification. The problem (if it is
one!) can be fixed easily enough. Just add the following lines after int counter = 0; and before the
while loop:

<p>@num</p> @* print out initial term *@


counter = 1; // and count it

Second, there is the question of why this problem might be interesting. Well, it’s interesting to
mathematicians and computer scientists because of a simple question about the problem that they
haven’t been able to answer: Will the process of computing the 3N+1 sequence finish after a finite
number of steps for all possible starting values of N? Although individual sequences are easy to
compute, no one has been able to answer the general question. To put this another way, no one
knows whether the process of computing 3N+1 sequences can properly be called an algorithm,
since an algorithm is required to terminate after a finite number of steps! (Note: This discussion
really applies to integers, not to values of type int! That is, it assumes that the value of N can take on
arbitrarily large integer values, which is not true for a variable of type int in a C# program. When
the value of N in the program becomes too large to be represented as a 32-bit int, the values output
by the program are no longer mathematically correct. So the program does not compute the correct
3N+1 sequence if N becomes too large.

5.2.3. Coding, Testing, Debugging

It would be nice if, having developed an algorithm for your program, you could relax, press a
button, and get a perfectly working program. Unfortunately, the process of turning an algorithm
into Java source code doesn’t always go smoothly. And when you do get to the stage of a working
program, it’s often only working in the sense that it does something. Unfortunately not what you
want it to do.

95
After program design comes coding: translating the design into a program written in C# or some
other language. Usually, no matter how careful you are, a few syntax errors will creep in from
somewhere, and the C# compiler will reject your program with some kind of error message.
Unfortunately, while a compiler will always detect syntax errors, it’s not very good about telling
you exactly what’s wrong. Sometimes, it’s not even good about telling you where the real error is. A
spelling error or missing "{" on line 45 might cause the compiler to choke on line 105. You can avoid
lots of errors by making sure that you really understand the syntax rules of the language and by
following some basic programming guidelines. For example, I never type a "{" without typing the
matching "}". Then I go back and fill in the statements between the braces. A missing or extra brace
can be one of the hardest errors to find in a large program. Always, always indent your program
nicely. If you change the program, change the indentation to match. It’s worth the trouble. Use a
consistent naming scheme, so you don’t have to struggle to remember whether you called that
variable interestrate or interestRate. In general, when the compiler gives multiple error messages,
don’t try to fix the second error message from the compiler until you’ve fixed the first one. Once the
compiler hits an error in your program, it can get confused, and the rest of the error messages
might just be guesses. Maybe the best advice is: Take the time to understand the error before you
try to fix it. Programming is not an experimental science.

When your code compiles without error, you are still not done. You have to test the code to make
sure it works correctly. Remember that the goal is not to get the right output for the two sample
inputs that the professor gave in class. The goal is code that will work correctly for all reasonable
inputs. Ideally, when faced with an unreasonable input, it should respond by gently chiding the
user rather than by crashing. Test your program on a wide variety of inputs. Try to find a set of
inputs that will test the full range of functionality that you’ve coded into your program. As you
begin writing larger programs, write them in stages and test each stage along the way. You might
even have to write some extra code to do the testing — for example to call a routine that you’ve just
written. You don’t want to be faced, if you can avoid it, with 500 newly written lines of code that
have an error in there somewhere.

What is a reasonable input? Any value that the user could reasonably type in or
provide as input. On an HTML form, for example, any key (any key) on the
keyboard that produces a character can be used to put a value into a form field:
they are strings. So when you need a number, you need to consider how your
CAUTION
program will behave when the user types in "balloon" instead of "5".

Go ahead and see how your web page behaves with input like this; ask yourself
if it is reasonable, or if further checks and meaningful.

The point of testing is to find bugs — semantic errors that show up as incorrect behavior rather
than as compilation errors. And the sad fact is that you will probably find them. Again, you can
minimize bugs by careful design and careful coding, but no one has found a way to avoid them
altogether. Once you’ve detected a bug, it’s time for debugging. You have to track down the cause of
the bug in the program’s source code and eliminate it. Debugging is a skill that, like other aspects of
programming, requires practice to master. So don’t be afraid of bugs. Learn from them. One
essential debugging skill is the ability to read source code — the ability to put aside preconceptions
about what you think it does and to follow it the way the computer does — mechanically, step-by-
step — to see what it really does. This is hard. I can still remember the time I spent hours looking
for a bug only to find that a line of code that I had looked at ten times had a "1" where it should

96
have had an "i", or the time when I wrote a subroutine named WindowClosing which would have
done exactly what I wanted except that the computer was looking for windowClosing (with a lower
case "w"). Sometimes it can help to have someone who doesn’t share your preconceptions look at
your code.

Often, it’s a problem just to find the part of the program that contains the error. Most programming
environments come with a debugger, which is a program that can help you find bugs. Typically,
your program can be run under the control of the debugger. The debugger allows you to set
"breakpoints" in your program. A breakpoint is a point in the program where the debugger will
pause the program so you can look at the values of the program’s variables. The idea is to track
down exactly when things start to go wrong during the program’s execution. The debugger will also
let you execute your program one line at a time, so that you can watch what happens in detail once
you know the general area in the program where the bug is lurking.

I will confess that I only occasionally use debuggers myself. A more traditional approach to
debugging is to insert debugging statements into your program. These are output statements that
print out information about the state of the program. Typically, a debugging statement would say
something like

<p>At start of while loop, num = @num</p>

You need to be able to tell from the output where in your program the output is coming from, and
you want to know the value of important variables. Sometimes, you will find that the computer
isn’t even getting to a part of the program that you think it should be executing. Remember that the
goal is to find the first point in the program where the state is not what you expect it to be. That’s
where the bug is.

And finally, remember the golden rule of debugging: If you are absolutely sure that everything in
your program is right, and if it still doesn’t work, then one of the things that you are absolutely sure
of is wrong.

5.3. The while and do..while Statements


<big>S</big>tatements in Java can be either simple statements or compound statements. Simple
statements, such as assignment statements and subroutine call statements, are the basic building
blocks of a program. Compound statements, such as while loops and if statements, are used to
organize simple statements into complex structures, which are called control structures because
they control the order in which the statements are executed. The next five sections explore the
details of control structures that are available in Java, starting with the while statement and the
do..while statement in this section. At the same time, we’ll look at examples of programming with
each control structure and apply the techniques for designing algorithms that were introduced in
the previous section.

97
5.4. The while statement
The while statement was already introduced earlier in this chapter. A while loop has the form

while ( boolean-expression )
  statement

The statement can, of course, be a block statement consisting of several statements grouped
together between a pair of braces. This statement is called the body of the loop. The body of the
loop is repeated as long as the boolean-expression is true. This boolean expression is called the
continuation condition, or more simply the test, of the loop. There are a few points that might need
some clarification. What happens if the condition is false in the first place, before the body of the
loop is executed even once? In that case, the body of the loop is never executed at all. The body of a
while loop can be executed any number of times, including zero. What happens if the condition is
true, but it becomes false somewhere in the middle of the loop body? Does the loop end as soon as
this happens? It doesn’t, because the computer continues executing the body of the loop until it gets
to the end. Only then does it jump back to the beginning of the loop and test the condition, and only
then can the loop end.

this section from Think Java Chapter 7 Let’s look at a typical use of while loops in web pages:
generating a table. Our problem will be to display a number of bits and the maximum value it can
be used to store as an unsigned binary value. For example, with 2 bits, we can represent 0, 1, 2, 3,
x
and 4. For a given value x, the maximum binary value we can store in x bits is 2 . We want to
display this value for all x from 1 to 16.

Here is a pseudocode algorithm for the program:

Let start = 1 // our first value


start the table
while start <= 16
  compute 2^start
  display a table row
end the table

Notice we have a terminal value, 16. This is a "magic value". Good programming practice is to put
such magic values in constants so that the constant name documents the purpose of the value. We
will keep this in mind when we write the actual code.

Notice the <= there as well — if you checked only <, the loop would stop one step before you wanted
to. Such so-called off-by-one errors are very common. Counting turns out to be harder than it
looks!)

It is quite typical to just use a < comparison on loops like this, which means the terminal test needs
to compare the value to 17, not 16, in our example. So be careful to check both your terminal test
value and operator if you have an off-by-one error.

We can easily turn the algorithm into a complete program. Note that the code is going to integrate

98
HTML with Razor, since the table is an HTML construct.

Here is the full source code for the program:

Listing 8. BitMax.cshtml

<!DOCTYPE html>
<html>
  <head>
  <title>BitMax</title>
  </head>

  <body>
  <table>
  <tr><th># Bits</th><th>Maximum Value</th></tr>
  @{
  /*
  * print out the values 1-16 and the maximum binary value storable in the
  * corresponding number of bits.
  */
  int numBits = 1;
  const int maxBits = 16;

  while (numBits <= maxBits) {

  <tr><td>@numBits</td><td>@Math.Pow(2,numBits)</td></tr> ①

  numBits++; ②
  }
  }
  </table>
  </body>
</html>

numBits
① Notice that we use the system Math object to compute the exponent value 2 . Also be
careful: there is no @ before the numbits argument, because we are already in an inline
expression.

② numBits increments the value in numBits. This is considered better form than writing out the
expression ``numBits = numbits + 1;`` -- you are more likely to see ``numBits`` in code, and
probably already have if you are using StackOverflow.

Your turn: modify this page to take the terminal value from the user rather than as a
TIP
hard-coded constant. What will you need to check to ensure the page works correctly?

Consider what you would need to check if the user is inputting both start and stop values. What
happens if start is more than stop?

Your while loop would still look like this:

99
  while (numBits <= maxBits) {

  <tr><td>@numBits</td><td>@Math.Pow(2,numBits)</td></tr>

  numBits++;
  }

But incrementing numBits would never bring it closer to maxBits. Rather, it would move it further
away. This is called an infinite loop. In Razor, your web page would never display, because the
Razor engine would keep generating the output HTML until the server’s resources were exhausted.

Whenever you are getting values from the user, consider not only what they may input, but also
how the values need to relate to one another and to other values in your code.

5.4.1. The do..while Statement

Sometimes it is more convenient to test the continuation condition at the end of a loop, instead of at
the beginning, as is done in the while loop. The do..while statement is very similar to the while
statement, except that the word "while," along with the condition that it tests, has been moved to
the end. The word "do" is added to mark the beginning of the loop. A do..while statement has the
form

do
  statement
while ( boolean-expression );

or, since, as usual, the statement can be a block,

do {
  statements
} while ( boolean-expression );

Note the semicolon, ';', at the very end. This semicolon is part of the statement, just as the semicolon
at the end of an assignment statement or declaration is part of the statement. Omitting it is a syntax
error. (More generally, every statement in C# ends either with a semicolon or a right brace, '}'.)

To execute a do loop, the computer first executes the body of the loop — that is, the statement or
statements inside the loop — and then it evaluates the boolean expression. If the value of the
expression is true, the computer returns to the beginning of the do loop and repeats the process; if
the value is false, it ends the loop and continues with the next part of the program. Since the
condition is not tested until the end of the loop, the body of a do loop is always executed at least
once.

For example, consider our previous while loop. The do loop makes sense here instead of a while
loop because with the do loop, you know there will be at least one time through the loop.

100
do {
  <tr><td>@numBits</td><td>@Math.Pow(2,numBits)</td></tr>
  numBits++;
} while ( numBits <= maxBits );

This is safe in our example because we know that numBits will always be less than maxBits at the
start. If you have user input, that may not be the case.

Although a do..while statement is sometimes more convenient than a while statement, having two
kinds of loops does not make the language more powerful. Any problem that can be solved using
do..while loops can also be solved using only while statements, and vice versa. In fact, if
doSomething represents any block of program code, then

do {
  doSomething
} while ( boolean-expression );

has exactly the same effect as

doSomething
while ( boolean-expression ) {
  doSomething
}

Similarly,

while ( boolean-expression ) {
  doSomething
}

can be replaced by

if ( boolean-expression ) {
  do {
  doSomething
  } while ( boolean-expression );
}

without changing the meaning of the program in any way.

5.4.2. break and continue

The syntax of the while and do..while loops allows you to test the continuation condition at either
the beginning of a loop or at the end. Sometimes, it is more natural to have the test in the middle of

101
the loop, or to have several tests at different places in the same loop. C# provides a general method
for breaking out of the middle of any loop. It’s called the break statement, which takes the form

break;

When the computer executes a break statement in a loop (or, as we will see later, a switch
statement also), it will immediately jump out of the loop or switch. It then continues on to whatever
follows the loop in the program. Consider this version of our previous while loop for example:

while (true) { // looks like it will run forever!

  <tr><td>@numBits</td><td>@Math.Pow(2,numBits)</td></tr>

  numBits++;

  if (numBits > maxBits) { // time to go


  break;
  }

}
// continue here after break

The test to exit the loop is no longer in the while expression, but instead is embedded in the loop.

The first line of this loop, "while (true)" might look a bit strange, but it’s perfectly legitimate. The
condition in a while loop can be any boolean-valued expression. The computer evaluates this
expression and checks whether the value is true or false. The boolean literal "true" is just a boolean
expression that always evaluates to true. So "while (true)" can be used to write an infinite loop, or
one that will be terminated by a break statement.

A break statement terminates the loop that immediately encloses the break statement. It is possible
to have nested loops, where one loop statement is contained inside another. If you use a break
statement inside a nested loop, it will only break out of that loop, not out of the loop that contains
the nested loop. There is something called a labeled break statement that allows you to specify
which loop you want to break. This is not very common, so I will go over it quickly. Labels work like
this: You can put a label in front of any loop. A label consists of a simple identifier followed by a
colon. For example, a while with a label might look like "mainloop: while…". Inside this loop you
can use the labeled break statement "break mainloop;" to break out of the labeled loop. For
example, here is a code segment that checks whether two strings, s1 and s2, have a character in
common. If a common character is found, the value of the flag variable nothingInCommon is set to
false, and a labeled break is used to end the processing at that point:

102
boolean nothingInCommon;
nothingInCommon = true; // Assume s1 and s2 have no chars in common.
int i,j; // Variables for iterating through the chars in s1 and s2.

i = 0;
bigloop: while (i < s1.length()) {
  j = 0;
  while (j < s2.length()) {
  if (s1.charAt(i) == s2.charAt(j)) { // s1 and s2 have a common char.
  nothingInCommon = false;
  break bigloop; // break out of BOTH loops
  }
  j++; // Go on to the next char in s2.
  }
  i++; //Go on to the next char in s1.
}

It is not considered good style to use a break when a while expression could be
CAUTION used; so our first example is not good programming — use break with caution,
and only when you cannot otherwise write a loop to do what you need it to.

The continue statement is related to break, but less commonly used. A continue statement tells the
computer to skip the rest of the current iteration of the loop. However, instead of jumping out of
the loop altogether, it jumps back to the beginning of the loop and continues with the next iteration
(including evaluating the loop’s continuation condition to see whether any further iterations are
required). As with break, when a continue is in a nested loop, it will continue the loop that directly
contains it; a "labeled continue" can be used to continue the containing loop instead.

break and continue can be used in while loops and do..while loops. They can also be used in for
loops, which are covered in the next section. Later, we’ll see that break can also be used to break
out of a switch statement. A break can occur inside an if statement, but only if the if statement is
nested inside a loop or inside a switch statement. In that case, it does not mean to break out of the
if. Instead, it breaks out of the loop or switch statement that contains the if statement. The same
consideration applies to continue statements inside ifs.

There is one other control flow statement that you will find in the C# reference
manual but will not be discussed further here: the goto statement. It, too, uses
labeled statements, and causes the flow of control to be immediately moved
from the goto statement to the labeled statement. This is never recommended,
and is not necessary given the other control flow statements in the language.
CAUTION
On the other hand, with just if and goto, you can program loops and so have a
complete language without ever using a loop; you would use if and goto to code
loops. But don’t do it. It’s terrible practice and the code written that way is
unreadable.

103
5.5. The for Statement
We turn in this section to another type of loop, the for statement. Any for loop is equivalent to some
while loop, so the language doesn’t get any additional power by having for statements. But for a
certain type of problem, a for loop can be easier to construct and easier to read than the
corresponding while loop. It’s quite possible that in real programs, for loops actually outnumber
while loops.

5.5.1. For Loops

The for statement makes a common type of while loop easier to write. Many while loops have the
general form:

initialization
while ( continuation-condition ) {
  statements
  update
}

For example, consider this example from earlier in the chapter:

  years = 0; // initialization
  while (years < 5) { //continuation condition

  interest = principal * rate; // compute interest for this year


  principal += interest; // add it to principal.
  <p>@principal</p> // display the principal for the year

  years++; // update to the next year


  }

This loop can be written as the following equivalent for statement:

for ( years = 0; years < 5; years++ ) {


  interest = principal * rate; // compute interest for this year
  principal += interest; // add it to principal.
  <p>@principal</p> // display the principal for the year
}

The initialization, continuation condition, and updating have all been combined in the first line of
the for loop. This keeps everything involved in the "control" of the loop in one place, which helps
make the loop easier to read and understand. The for loop is executed in exactly the same way as
the original code: The initialization part is executed once, before the loop begins. The continuation
condition is executed before each execution of the loop, and the loop ends when this condition is
false. The update part is executed at the end of each execution of the loop, just before jumping back
to check the condition.

104
The formal syntax of the for statement is as follows:

for ( initialization; continuation-condition; update )


  statement

or, using a block statement:

for ( initialization; continuation-condition; update ) {


  statements
}

The continuation-condition must be a boolean-valued expression. The initialization is usually a


declaration or an assignment statement, but it can be any expression that would be allowed as a
statement in a program. The update can be any simple statement, but is usually an increment, a
decrement, or an assignment statement. Any of the three parts can be empty. If the continuation
condition is empty, it is treated as if it were "true," so the loop will be repeated forever or until it
ends for some other reason, such as a break statement. (Some people like to begin an infinite loop
with "for (;;)" instead of "while (true)".) Here’s a flow control diagram for a for statement:

Usually, the initialization part of a for statement assigns a value to some variable, and the update
changes the value of that variable with an assignment statement or with an increment or
decrement operation. The value of the variable is tested in the continuation condition, and the loop
ends when this condition evaluates to false. A variable used in this way is called a loop control
variable. In the example given above, the loop control variable was years.

Certainly, the most common type of for loop is the counting loop, where a loop control variable
takes on all integer values between some minimum and some maximum value. A counting loop has

105
the form

for ( variable = min; variable <= max; variable++ ) {


  statements
}

where min and max are integer-valued expressions (usually constants). The variable takes on the
values min, min+1, min+2, …, max. The value of the loop control variable is often used in the body
of the loop. The for loop at the beginning of this section is a counting loop in which the loop control
variable, years, takes on the values 1, 2, 3, 4, 5. Here is an even simpler example, in which the
numbers 1, 2, …, 10 are displayed :

for (int i = 1 ; i <= 10 ; i++ ) {


  <p>@i</p>
}

One-letter variables are usually frowned upon in code; one exception is for-loop
NOTE variables, where we will often see i or j used as simple counters. If there is more
reason than simply counting, give your for-loop variable a meaningful name.

For various reasons, Java programmers like to start counting at 0 instead of 1, and they tend to use
a "<" in the condition, rather than a "⇐". The following variation of the above loop prints out the
ten numbers 0, 1, 2, …, 9:

for (int i = 0 ; i < 10 ; i++ ) {


  <p>@i</p>
}

Using < instead of <= in the test, or vice versa, is a common source of off-by-one errors in programs.
You should always stop and think, Do I want the final value to be processed or not?

It’s easy to count down from 10 to 1 instead of counting up. Just start with 10, decrement the loop
control variable instead of incrementing it, and continue as long as the variable is greater than or
equal to one.

for (int i = 10 ; i >= 1 ; i-- ) {


  <p>@i</p>
}

Now, in fact, the official syntax of a for statement actually allows both the initialization part and the
update part to consist of several expressions, separated by commas. So we can even count up from
1 to 10 and count down from 10 to 1 at the same time!

106
for ( i=1, j=10; i <= 10; i++, j-- ) {
  <pre>@System.format("{0,5}{1,5}", i, j)</pre> // i and j each get 5 character
fields (use pre to keep space)
}

As a final introductory example, let’s say that we want to use a for loop that prints out just the even
numbers between 2 and 20, that is: 2, 4, 6, 8, 10, 12, 14, 16, 18, 20. There are several ways to do this.
Just to show how even a very simple problem can be solved in many ways, here are four different
solutions (three of which would get full credit):

 (1) // There are 10 numbers to print.


  // Use a for loop to count 1, 2,
  // ..., 10. The numbers we want
  // to print are 2*1, 2*2, ... 2*10.

  for (int i = 1; i <= 10; i++) {


  <text>@(2*i) </text>
  }

 (2) // Use a for loop that counts


  // 2, 4, ..., 20 directly by
  // adding 2 to N each time through
  // the loop.

  for (int i = 2; i <= 20; i += 2) {


  <text>@i </text>
  }

 (3) // Count off all the numbers


  // 2, 3, 4, ..., 19, 20, but
  // only print out the numbers
  // that are even.

  for (int i = 2; i <= 20; i++) {


  if ( i % 2 == 0 ) { // is i even?
  <text>@i </text>
  }
  }

 (4) // Irritate the professor with


  // a solution that follows the
  // letter of this silly assignment
  // while making fun of it.

  for (int i = 1; i <= 1; i++) {


  <text>2 4 6 8 10 12 14 16 18 20</text>
  }

107
Perhaps it is worth stressing one more time that a for statement, like any statement except for a
variable declaration, never occurs on its own in a real program. A statement must be inside the
main routine of a program or inside some other subroutine. And that subroutine must be defined
inside a class. (In ASP.NET, the code you put in Razor code blocks are put into a generated class for
the page.)

I should also remind you that every variable must be declared before it can be used, and that
includes the loop control variable in a for statement. In all the examples that you have seen so far
in this section, the loop control variables should be declared to be of type int. It is not required that
a loop control variable be an integer. Here, for example, is a for loop in which the variable, ch, is of
type char, using the fact that the ++ operator can be applied to characters as well as to numbers:

@* Print out the alphabet on one line of output. *@


<p>
@for ( char ch = 'A'; ch <= 'Z'; ch++ ) {
  <text>@ch </text>
}
</p>

Here I show another use of Razor — any of the loop and conditional statements can be directly
placed in your web page with a @ prefix before the keyword for, while, do, if, or switch. This lets
you put all of the contents within a single paragraph as the example shows.

5.5.2. Example: Counting Divisors

Let’s look at a less trivial problem that can be solved with a for loop. If N and D are positive
integers, we say that D is a divisor of N if the remainder when D is divided into N is zero.
(Equivalently, we could say that N is an even multiple of D.) In terms of C# programming, D is a
divisor of N if N % D is zero.

Let’s write a program that inputs a positive integer, N, from the user and computes how many
different divisors N has. The numbers that could possibly be divisors of N are 1, 2, …, N. To compute
the number of divisors of N, we can just test each possible divisor of N and count the ones that
actually do divide N evenly. In pseudocode, the algorithm takes the form

Get a positive integer, N, from the user


Let divisorCount = 0
for each number, testDivisor, in the range from 1 to N:
  if testDivisor is a divisor of N:
  Count it by adding 1 to divisorCount
Output the count

This algorithm displays a common programming pattern that is used when some, but not all, of a
sequence of items are to be processed. The general pattern is

108
for each item in the sequence:
  if the item passes the test:
  process it

The for loop in our divisor-counting algorithm can be translated into Java code as

for (testDivisor = 1; testDivisor <= N; testDivisor++) {


  if ( N % testDivisor == 0 )
  divisorCount++;
}

On a modern computer, this loop can be executed very quickly. It is not impossible to run it even
for the largest legal int value, 2147483647. (If you wanted to run it for even larger values, you could
use variables of type long rather than int.) However, it does take a significant amount of time for
very large numbers. So when I implemented this algorithm, I decided to output a dot every time the
computer has tested one million possible divisors. In the improved version of the program, there
are two types of counting going on. We have to count the number of divisors and we also have to
count the number of possible divisors that have been tested. So the program needs two counters.
When the second counter reaches 1000000, the program outputs a '.' and resets the counter to zero
so that we can start counting the next group of one million. Reverting to pseudocode, the algorithm
now looks like

Get a positive integer, N, from the user


Let divisorCount = 0 // Number of divisors found.
Let numberTested = 0 // Number of possible divisors tested
  // since the last period was output.
for each number, testDivisor, in the range from 1 to N:
  if testDivisor is a divisor of N:
  Count it by adding 1 to divisorCount
  Add 1 to numberTested
  if numberTested is 1000000:
  print out a '.'
  Reset numberTested to 0
Output the count

Finally, we can translate the algorithm into a complete Java program:

Listing 9. CountDivisors.cshtml

<!DOCTYPE html>
<html>
  <head>
  <title>Count Divisors</title>

  <style type="text/css">
  body {background-color: beige; font-family: Verdana, Arial;
  margin: 50px; }

109
  form {padding: 10px; border-style: solid; width: 250px;}
  </style>
  </head>

  <body>
  <p> This page counts how many divisors the number has and prints the result.</p>

  <p>Enter a numbers and then click <strong>Count Divisors</strong>.</p>


  <form action="" method="post">
  <p><label for="principal">Number:</label>
  <input type="text" name="num" />
  </p>
  <p><input type="submit" value="Count Divisors" /></p>
  </form>
  <br/>

  @{
  int num; // A positive integer entered by the user.
  // Divisors of this number will be counted.

  int testDivisor; // A number between 1 and N that is a


  // possible divisor of N.

  int divisorCount; // Number of divisors of N that have been found.

  int numberTested; // Used to count how many possible divisors


  // of N have been tested. When the number
  // reaches 1000000, a period is output and
  // the value of numberTested is reset to zero.

  /* Get the initial number from the user. */


  if (IsPost) {
  num = Request["num"].AsInt();

  if (num <= 0) {
  <p>@num is not positive. Please try again.</p>
  } else {
  // At this point, we know that num > 0

  /* Count the divisors, printing a "." after every 1000000 tests. */

  divisorCount = 0;
  numberTested = 0;

  for (testDivisor = 1; testDivisor <= num; testDivisor++) {


  if ( num % testDivisor == 0 ) {
  divisorCount++;
  }
  numberTested++;
  if (numberTested == 1000000) {
  <text>.</text>

110
  numberTested = 0;
  }
  }

  /* Display the result. */


  <text><br /></text>
  <p>The number of divisors of @num is @divisorCount.</p>

  } // end num > 0

  } // end IsPost
  }
  </body>
</html>

Note that because the whole web page is displayed only once its HTML is generated by the Razor
processor, all of the .'s display at once, after the computation completes. This kind of progress meter
would be displayable during the execution of the computation only with a more complex call-back
in place, beyond the scope of our work.

5.5.3. Nested For Loops

Control structures in Java are statements that contain other, simpler statements. In particular,
control structures can contain control structures. You’ve already seen several examples of if
statements inside loops, and one example of a while loop inside another while, but any
combination of one control structure inside another is possible. We say that one structure is nested
inside another. You can even have multiple levels of nesting, such as a while loop inside an if
statement inside another while loop. The syntax of Java does not set a limit on the number of levels
of nesting. As a practical matter, though, it’s difficult to understand a program that has more than a
few levels of nesting.

Nested for loops arise naturally in many algorithms, and it is important to understand how they
work. Let’s look at a couple of examples. First, consider the problem of printing out a multiplication
table like this one:

 1 2 3 4 5 6 7 8 9 10 11 12
 2 4 6 8 10 12 14 16 18 20 22 24
 3 6 9 12 15 18 21 24 27 30 33 36
 4 8 12 16 20 24 28 32 36 40 44 48
 5 10 15 20 25 30 35 40 45 50 55 60
 6 12 18 24 30 36 42 48 54 60 66 72
 7 14 21 28 35 42 49 56 63 70 77 84
 8 16 24 32 40 48 56 64 72 80 88 96
 9 18 27 36 45 54 63 72 81 90 99 108
10 20 30 40 50 60 70 80 90 100 110 120
11 22 33 44 55 66 77 88 99 110 121 132
12 24 36 48 60 72 84 96 108 120 132 144

111
The data in the table are arranged into 12 rows and 12 columns, so we should generate an HTML
table. The process of printing them out can be expressed in a pseudocode algorithm as

start a table
for each rowNumber = 1, 2, 3, ..., 12:
  start a row
  Print the first twelve multiples of rowNumber on one line
  end the row
end the table

The first step in the for loop can itself be expressed as a for loop. We can expand "Print the first
twelve multiples of rowNumber on one line" as:

for N = 1, 2, 3, ..., 12:


  Print N * rowNumber

so a refined algorithm for printing the table has one for loop nested inside another:

start a table
for each rowNumber = 1, 2, 3, ..., 12:
  start a row
  for N = 1, 2, 3, ..., 12:
  Print N * rowNumber
  end the row
end the table

We want to print the output in neat columns, with each output number taking up four spaces. This
can be done using formatted output with format specifier %4d. Assuming that rowNumber and N
have been declared to be variables of type int, the algorithm can be expressed in Java as

<table>
@for ( int rowNumber = 1; rowNumber <= 12; rowNumber++ ) {
  // start a row in the table
  @: <tr>
  for ( int N = 1; N <= 12; N++ ) {
  // print in columns
  <td align="right">@( N * rowNumber )</td>
  }
  //end the current row in the table
  @: </tr>
}
</table>

112
Note the use of @: to mark the HTML-only rows. This is needed for the </tr> since it
NOTE is just a closing tag on its own. For consistency, I’ve used it on the <tr> as
well — consistency makes the code easier to read.

This section has been weighed down with lots of examples of numerical processing. For our next
example, let’s do some text processing. Consider the problem of finding which of the 26 letters of
the alphabet occur in a given string. For example, the letters that occur in "Hello World" are D, E, H,
L, O, R, and W. More specifically, we will write a program that will list all the letters contained in a
string and will also count the number of different letters. The string will be input by the user. Let’s
start with a pseudocode algorithm for the program.

Ask the user to input a string


Read the response into a variable, text
Let count = 0 (for counting the number of different letters)
for each letter of the alphabet:
  if the letter occurs in text:
  Print the letter
  Add 1 to count
Output the count

This follows our form model very well, since forms' input come to us as strings already. The line of
the algorithm that reads "for each letter of the alphabet" can be expressed as "for (letter='A';
letter⇐'Z'; letter++)". But the if statement inside the for loop needs still more thought before we can
write the program. How do we check whether the given letter, letter, occurs in str? One idea is to
look at each character in the string in turn, and check whether that character is equal to letter. We
can get the i-th character of text with an index into the string like so: text[i], where i ranges from 0
to str.Length - 1.

One more difficulty: A letter such as 'A' can occur in str in either upper or lower case, 'A' or 'a'. We
have to check for both of these. But we can avoid this difficulty by converting str to upper case
before processing it. Then, we only have to check for the upper case letter. We can now flesh out
the algorithm fully:

Ask the user to input a string


Read the response into a variable, text
Convert text to upper case
Let count = 0
for letter = 'A', 'B', ..., 'Z':
  for i = 0, 1, ..., text.Length-1:
  if letter == text[i]:
  Print letter
  Add 1 to count
  break // jump out of the loop, to avoid counting letter twice
Output the count

Note the use of break in the nested for loop. It is required to avoid printing or counting a given
letter more than once (in the case where it occurs more than once in the string). The break

113
statement breaks out of the inner for loop, but not the outer for loop. Upon executing the break, the
computer continues the outer loop with the next value of letter. You should try to figure out exactly
what count would be at the end of this program, if the break statement were omitted. Here is the
complete program:

Listing 10. ListLetters.cshtml

<!DOCTYPE html>
<html>
<head>
  <title>List Letters</title>

  <style type="text/css">
  body {
  background-color: beige;
  font-family: Verdana, Arial;
  margin: 50px;
  }

  form {
  padding: 10px;
  border-style: solid;
  width: 250px;
  }
  </style>
</head>

<body>
  <p>Enter a line and I'll tell you what letters it has, and
  how many different letters there are.</p>

  <p>Enter your line and then click <strong>List Letters</strong>.</p>


  <form action="" method="post">
  <p>
  <label for="principal">Text:</label>
  <input type="text" name="text" />
  </p>
  <p><input type="submit" value="List Letters" /></p>
  </form>
  <br />

@{
  if (IsPost) {
  string text; // Line of text entered by the user.
  int count=0; // Number of different letters found in str.

  text = Request["text"].ToUpper();

  <p>Your input contains the following letters: </p>

  @: <p>

114
  for (char letter = 'A'; letter <= 'Z'; letter++ ) {
  int i; // Position of a character in str.
  for ( i = 0; i < text.Length; i++ ) {
  if ( letter == text[i] ) {
  <text>@letter </text>
  count++;
  break;
  }
  }
  }
  @: </p>

  <p>There were @count different letters.</p>


  } // end IsPost
}
</body>
</html>

In fact, there is actually an easier way to determine whether a given letter occurs in a string, str.
The built-in function str.IndexOf(letter) will return -1 if letter does not occur in the string. It returns
a number greater than or equal to zero if it does occur. So, we could check whether letter occurs in
str simply by checking "if (str.IndexOf(letter) >= 0)". If we used this technique in the above program,
we wouldn’t need a nested for loop. This gives you a preview of how subroutines can be used to
deal with complexity.

It is a good idea to get familiar with the common methods such as those on string so
TIP
that you avoid re-writing code that is available to you in ASP.NET already.

5.6. The if Statement


The first of the two branching statements in Java is the if statement, which you have already seen. It
takes the form

if (boolean-expression)
  statement-1
else
  statement-2

As usual, the statements inside an if statement can be blocks. The if statement represents a two-way
branch. The else part of an if statement — consisting of the word "else" and the statement that
follows it — can be omitted.

This section delves into complex uses of if statements and how to consider what can go wrong with
them.

115
5.6.1. The Dangling else Problem

Since Razor requires {}'s on all bodies of if statements, these types of issues can only
NOTE
occur in your C# class files' code. They will not occur in your .cshtml files.

Now, an if statement is, in particular, a statement. This means that either statement-1 or statement-
2 in the above if statement can itself be an if statement. A problem arises, however, if statement-1 is
an if statement that has no else part. This special case is effectively forbidden by the syntax of C#.
Suppose, for example, that you type

if ( x > 0 )
  if (y > 0)
  msg="First case";
else
  msg="Second case";

Now, remember that the way you’ve indented this doesn’t mean anything at all to the computer.
You might think that the else part is the second half of your "if (x > 0)" statement, but the rule that
the computer follows attaches the else to "if (y > 0)", which is closer. That is, the computer reads
your statement as if it were formatted:

if ( x > 0 )
  if (y > 0)
  msg="First case";
  else
  msg="Second case";

You can force the computer to use the other interpretation by enclosing the nested if in a block:

if ( x > 0 ) {
  if (y > 0)
  msg="First case";
}
else
  msg="Second case";

These two if statements have different meanings: In the case when x <= 0, the first statement
doesn’t set msg to anything, but the second statement sets it to "Second case".

5.6.2. Multiway Branching

Much more interesting than this technicality is the case where statement-2, the else part of the if
statement, is itself an if statement. The statement would look like this (perhaps without the final
else part):

116
if (boolean-expression-1)
  statement-1
else
  if (boolean-expression-2)
  statement-2
  else
  statement-3

However, since the computer doesn’t care how a program is laid out on the page, this is almost
always written in the format:

if (boolean-expression-1)
  statement-1
else if (boolean-expression-2)
  statement-2
else
  statement-3

You should think of this as a single statement representing a three-way branch. When the computer
executes this, one and only one of the three statements — statement-1, statement-2, or statement-
3 — will be executed. The computer starts by evaluating boolean-expression-1. If it is true, the
computer executes statement-1 and then jumps all the way to the end of the outer if statement,
skipping the other two statements. If boolean-expression-1 is false, the computer skips statement-1
and executes the second, nested if statement. To do this, it tests the value of boolean-expression-2
and uses it to decide between statement-2 and statement-3.

Here is an example that will print out one of three different messages, depending on the value of a
variable named temperature:

if (temperature < 50) {


  <p>It's cold.</p>
} else if (temperature < 80) {
  <p>It's nice.</p>
} else {
  <p>It's hot.</p>
}

Notice the brace placement above: Razor allows you to not put braces between the else
TIP
and if, it reads "else if" as a unit.

If temperature is, say, 42, the first test is true. The computer prints out the message "It’s cold", and
skips the rest — without even evaluating the second condition. For a temperature of 75, the first test
is false, so the computer goes on to the second test. This test is true, so the computer prints "It’s
nice" and skips the rest. If the temperature is 173, both of the tests evaluate to false, so the computer
says "It’s hot" (unless its circuits have been fried by the heat, that is).

117
You can go on stringing together "else-if’s" to make multi-way branches with any number of cases:

if (test-1)
  statement-1
else if (test-2)
  statement-2
else if (test-3)
  statement-3
  .
  . // (more cases)
  .
else if (test-N)
  statement-N
else
  statement-(N+1)

The computer evaluates the tests, which are boolean expressions, one after the other until it comes
to one that is true. It executes the associated statement and skips the rest. If none of the boolean
expressions evaluate to true, then the statement in the else part is executed. This statement is called
a multi-way branch because one and only one of the statements will be executed. The final else part
can be omitted. In that case, if all the boolean expressions are false, none of the statements are
executed. Of course, each of the statements can be a block, consisting of a number of statements
enclosed between { and }. Admittedly, there is lot of syntax here; as you study and practice, you’ll
become comfortable with it. It might be useful to look at a flow control diagram for the general
"if..else if" statement shown above:

118
5.6.3. If Statement Examples

As an example of using if statements, let’s suppose that x, y, and z are variables of type int, and that
each variable has already been assigned a value. Consider the problem of printing out the values of
the three variables in increasing order. For example, if the values are 42, 17, and 20, then the
output should be in the order 17, 20, 42.

One way to approach this is to ask, where does x belong in the list? It comes first if it’s less than
both y and z. It comes last if it’s greater than both y and z. Otherwise, it comes in the middle. We
can express this with a 3-way if statement, but we still have to worry about the order in which y
and z should be printed. In pseudocode,

if (x < y && x < z) { // && is the boolean operator, logical and.


  output x, followed by y and z in their correct order
}
else if (x > y && x > z) {
  output y and z in their correct order, followed by x
}
else {
  output x in between y and z in their correct order
}

Determining the relative order of y and z requires another if statement, so this becomes

if (x < y && x < z) { // x comes first


  if (y < z) {
  <p>@x @y @z</p>
  } else {
  <p>@x @z @y</p>
  }
}
else if (x > y && x > z) { // x comes last
  if (y < z) {
  <p>@y @z @x</p>
  } else {
  <p>@z @y @x</p>
  }
}
else { // x in the middle
  if (y < z) {
  <p>@y @x @z</p>
  } else {
  <p>@z @x @y</p>
  }
}

You might check that this code will work correctly even if some of the values are the same. If the
values of two variables are the same, it doesn’t matter which order you print them in.

119
Note, by the way, that even though you can say in English "if x is less than y and z," you can’t say in
C# "if (x < y && z)". The && operator can only be used between boolean values, so you have to make
separate tests, x<y and x<z, and then combine the two tests with &&.

There is an alternative approach to this problem that begins by asking, "which order should x and y
be printed in?" Once that’s known, you only have to decide where to stick in z. This line of thought
leads to different Java code:

if ( x < y ) { // x comes before y


  if ( z < x ) { // z comes first
  <p>@z @x @y</p>
  } else if ( z > y ) { // z comes last
  <p>@x @y @z</p>
  } else { // z is in the middle
  <p>@x @z @y</p>
  }
} else { // y comes before x
  if ( z < y ) { // z comes first
  <p>@z @y @x</p>
  } else if ( z > x ) { // z comes last
  <p>@y @x @z</p>
  } else { // z is in the middle
  <p>@y @z @x</p>
  }
}

Once again, we see how the same problem can be solved in many different ways. The two
approaches to this problem have not exhausted all the possibilities. For example, you might start by
testing whether x is greater than y. If so, you could swap their values. Once you’ve done that, you
know that x should be printed before y.

Finally, let’s write a complete program that uses an if statement in an interesting way. I want a
program that will convert measurements of length from one unit of measurement to another, such
as miles to yards or inches to feet. So far, the problem is extremely under-specified. Let’s say that
the program will only deal with measurements in inches, feet, yards, and miles. It would be easy to
extend it later to deal with other units. The user will type in a measurement in one of these units,
such as "17 feet" or "2.73 miles". The output will show the length in terms of each of the four units
of measure. (This is easier than asking the user which units to use in the output.) An outline of the
process is

Read the user's input measurement and units of measure


Express the measurement in inches, feet, yards, and miles
Display the four results

TWe will read the input from a form and convert the value to a double. The conversion into
different units of measure can be simplified by first converting the user’s input into inches. From

120
there, the number of inches can easily be converted into feet, yards, and miles. Before converting
into inches, we have to test the input to determine which unit of measure the user has specified:

Let measurement = Request["measurement"]


Let units = Request["units"]
if the units are inches
  Let inches = measurement
else if the units are feet
  Let inches = measurement * 12 // 12 inches per foot
else if the units are yards
  Let inches = measurement * 36 // 36 inches per yard
else if the units are miles
  Let inches = measurement * 12 * 5280 // 5280 feet per mile
else
  The units are illegal!
  Print an error message and stop processing
Let feet = inches / 12.0
Let yards = inches / 36.0
Let miles = inches / (12.0 * 5280.0)
Display the results

We can use HTML to limit the user to only the units of measure we currently support. However,
since HTML POST requests could be made without the form, we will check for not only the allowed
values but also illegal values, just in case.

Also, the magic values 12, 36, and 5280 are coded as constants to document what they are.

Here’s the complete program:

Listing 11. LengthConverter.cshtml

<!DOCTYPE html>
<html>
<head>
  <title>Length Converter</title>

  <style type="text/css">
  body {
  background-color: beige;
  font-family: Verdana, Arial;
  margin: 50px;
  }

  form {
  padding: 10px;
  border-style: solid;
  width: 300px;
  }
  </style>
</head>

121
<body>
  <p>Enter your measurement and units and then click <strong>Convert</strong>
  to see it in other units.<br/>
  I will convert your input into the other units
  of measure.</p>
  <form action="" method="post">
  <p>
  <label for="measurement">Measurement:</label>
  <input type="text" name="measurement" />
  </p>
  <p>
  <label for="units">Units:</label>
  <select name="units">
  <option value="inches">inches</option>
  <option value="feet">feet</option>
  <option value="yards">yards</option>
  <option value="miles">miles</option>
  </select>
  </p>
  <p><input type="submit" value="Convert" /></p>
  </form>
  <br />

  @{
  if (IsPost) {
  double measurement; // Numerical measurement, input by user.
  string units; // The unit of measure for the input, also
  // specified by the user.

  double inches, feet, yards, miles; // Measurement expressed in


  // each possible unit of
  // measure.

  const int inchesInFeet = 12; // constants for conversions


  const int inchesInYard = 36;
  const int feetInMile = 5280;

  /* Get the user's input, and convert units to lower case. */


  measurement = (double)Request["measurement"].AsDecimal();
  units = Request["units"].ToLower();

  /* Convert the input measurement to inches. */


  if (units.Equals("inches")) {
  inches = measurement;
  }
  else if (units.Equals("feet")) {
  inches = measurement * inchesInFeet;
  }
  else if (units.Equals("yards")) {
  inches = measurement * inchesInYard;

122
  }
  else if (units.Equals("miles")) {
  inches = measurement * inchesInFeet * feetInMile;
  }
  else {
  // in case the form is submitted incorrectly
  <p>Sorry, but I don't understand @units. Will assume inches.</p>
  inches = measurement;
  }

  /* Convert measurement in inches to feet, yards, and miles. */


  feet = inches / inchesInFeet;
  yards = inches / inchesInYard;
  miles = inches / (inchesInFeet*feetInMile);

  /* Output measurement in terms of each unit of measure. */


  <p>That's equivalent to:</p>
  <p>@inches inches</p>
  <p>@feet feet</p>
  <p>@yards yards</p>
  <p>@miles miles</p>
  } // end IsPost
}
</body>
</html>

Here you can see we have really taken advantage of the web experience to tailor the user’s
selection. Consider how you would write this in a Java application, where you would also have to
request the units from the user rather than provide them with a limited number of choices.

5.6.4. The Empty Statement

As a final note in this section, I will mention one more type of statement in C#: the empty statement.
This is a statement that consists simply of a semicolon and which tells the computer to do nothing.
The existence of the empty statement makes the following legal, even though you would not
ordinarily see a semicolon after a } :

if (x < 0) {
  x = -x;
};

The semicolon is legal after the }, but the computer considers it to be an empty statement, not part
of the if statement. Occasionally, you might find yourself using the empty statement when what you
mean is, in fact, "do nothing." For example, the rather contrived if statement

123
if ( done )
  ; // Empty statement
else
  message="Not done yet.";

does nothing when the boolean variable done is true, and sets message to "Not done yet" when it is
false. You can’t just leave out the semicolon in this example, since Java syntax requires an actual
statement between the if and the else. I prefer, though, to use an empty block, consisting of { and }
with nothing between, for such cases. (So does Razor, which requires the { } instead of the ; here.)

Occasionally, stray empty statements can cause annoying, hard-to-find errors in a program. For
example, the following program segment sets message to "Hello", rather than "Hello Hello Hello
Hello Hello":

for (int i = 0; i < 5; i++);


  message+="Hello ";

Why? Because the ";" at the end of the first line is a statement, and it is this empty statement that is
executed ten times. The assignment statement is not really inside the for statement at all, so it is
executed just once, after the for loop has completed. The for loop just does nothing, ten times!

(In Razor, it would fail to compile, requesting that you use {}s after the for loop.)

5.7. The switch Statement


The second branching statement in C# is the switch statement, which is introduced in this section.
The switch statement is used far less often than the if statement, but it is sometimes useful for
expressing a certain type of multiway branch.

5.7.1. The Basic switch Statement

A switch statement allows you to test the value of an expression and, depending on that value, to
jump directly to some location within the switch statement. Only expressions of certain types can
be used. The value of the expression can be one of the primitive integer types int, short, or byte. It
can be the primitive char or bool types. It can be string. Or it can be an enum type (we are not
covering C# enums in this book, see https://msdn.microsoft.com/en-us/library/sbbt4032.aspx for
information on this type). In particular, note that the expression cannot be a double, float, or
decimal value.

The positions within a switch statement to which it can jump are marked with case labels that take
the form: "case constant:". The constant here is a literal of the same type as the expression in the
switch. A case label marks the position the computer jumps to when the expression evaluates to the
given constant value. As the final case in a switch statement you can, optionally, use the label
"default:", which provides a default jump point that is used when the value of the expression is not
listed in any case label.

A switch statement, as it is most often used, has the form:

124
switch (expression) {
  case constant-1:
  statements-1
  break;
  case constant-2:
  statements-2
  break;
  .
  . // (more cases)
  .
  case constant-N:
  statements-N
  break;
  default: // optional default case
  statements-(N+1)
} // end of switch statement

This has exactly the same effect as the following multiway if statement, but the switch statement
can be more efficient because the computer can evaluate one expression and jump directly to the
correct case, whereas in the if statement, the computer must evaluate up to N expressions before it
knows which set of statements to execute:

if (expression == constant-1) { // but use .equals for String!!


  statements-2
}
else if (expression == constant-2) {
  statements-3
}
else
  .
  .
  .
else if (expression == constant-N) {
  statements-N
}
else {
  statements-(N+1)
}

The break statements in the switch are technically optional. However, does require that execution
not continue to the next switch case: it has to end with a break, throw, return, or other statement
that interrupts the flow of control. The effect of a break is to make the computer jump past the end
of the switch statement, skipping over all the remaining cases. If you leave out the break statement,
you will get a compilation error.

Note that you can leave out one of the groups of statements entirely (including the break). You then
have two case labels in a row, containing two different constants. This just means that the computer
will jump to the same place and perform the same action for each of the two constants.

125
Here is an example of a switch statement. This is not a useful example, but it should be easy for you
to follow. Note, by the way, that the constants in the case labels don’t have to be in any particular
order, but they must all be different:

switch ( N ) { // (Assume N is an integer variable.)


  case 1:
  message="The number is 1.";
  break;
  case 2:
  case 4:
  case 8:
  message="The number is 2, 4, or 8.";
  message+="(That's a power of 2!)";
  break;
  case 3:
  case 6:
  case 9:
  message="The number is 3, 6, or 9.";
  message+="(That's a multiple of 3!)";
  break;
  case 5:
  message="The number is 5.";
  break;
  default:
  message="The number is 7 or is outside the range 1 to 9.";
}

The switch statement is pretty primitive as control structures go, and it’s easy to make mistakes
when you use it. C# has addressed a key issue that exists in other languages by requiring that the
switch be exited at the end of a case block.

5.7.2. Lists and switch Statements

One application of switch statements is in processing list selections. A form can have a drop-down
list of options. The user selects one of the options. The computer has to respond to each possible
choice in a different way. The value of chosen option can be used in a switch statement to select the
proper response.

Here is an example that could be used in a variation of the LengthConverter example from the
previous section:

Listing 12. LengthConverter2.cshtml

<!DOCTYPE html>
<html>
<head>
  <title>Length Converter</title>

  <style type="text/css">

126
  body {
  background-color: beige;
  font-family: Verdana, Arial;
  margin: 50px;
  }

  form {
  padding: 10px;
  border-style: solid;
  width: 300px;
  }
  </style>
</head>

<body>
  <p>Enter your measurement and units and then click <strong>Convert</strong>
  to see it in other units.<br/>
  I will convert your input into the other units
  of measure.</p>
  <form action="" method="post">
  <p>
  <label for="measurement">Measurement:</label>
  <input type="text" name="measurement" />
  </p>
  <p>
  <label for="units">Units:</label>
  <select name="units">
  <option value="inches">inches</option>
  <option value="feet">feet</option>
  <option value="yards">yards</option>
  <option value="miles">miles</option>
  </select>
  </p>
  <p><input type="submit" value="Convert" /></p>
  </form>
  <br />

  @{
  if (IsPost) {
  double measurement; // Numerical measurement, input by user.
  string units; // The unit of measure for the input, also
  // specified by the user.

  double inches, feet, yards, miles; // Measurement expressed in


  // each possible unit of
  // measure.

  const int inchesInFeet = 12; // constants for conversions


  const int inchesInYard = 36;
  const int feetInMile = 5280;

127
  /* Get the user's input, and convert units to lower case. */
  measurement = (double)Request["measurement"].AsDecimal();
  units = Request["units"].ToLower();

  /* Convert the input measurement to inches. */


  switch(units) { ①
  case "inches":
  inches = measurement;
  break;
  case "feet":
  inches = measurement * inchesInFeet;
  break;
  case "yards":
  inches = measurement * inchesInYard;
  break;
  case "miles":
  inches = measurement * inchesInFeet * feetInMile;
  break;
  default: // in case the form is submitted incorrectly
  <p>Sorry, but I don't understand @units. Will assume inches.</p>
  inches = measurement;
  break;
  }

  /* Convert measurement in inches to feet, yards, and miles. */


  feet = inches / inchesInFeet;
  yards = inches / inchesInYard;
  miles = inches / (inchesInFeet*feetInMile);

  /* Output measurement in terms of each unit of measure. */


  <p>That's equivalent to:</p>
  <p>@inches inches</p>
  <p>@feet feet</p>
  <p>@yards yards</p>
  <p>@miles miles</p>
  } // end IsPost
}
</body>
</html>

① This is the new code, using a switch instead of a series of if tests.

5.7.3. Definite Assignment and switch Statements

As a somewhat more realistic example, the following switch statement makes a random choice
among three possible alternatives. The value of the expression rand.Next(3) is one of the integers 0,
1, or 2, selected at random with equal probability, so the switch statement below will assign one of
the values "Rock", "Paper", "Scissors" to computerMove, with probability 1/3 for each case:

128
Random is a useful ASP.NET class, with an interesting collection of methods
available on it for our use: see https://msdn.microsoft.com/en-
us/library/system.random(v=vs.110).aspx. We haven’t introduced objects yet; Random
rand = new Random(); is creating an object based on the Random class so that we can
NOTE
access the object’s methods. Why didn’t ASP.NET just provide a Random object? this
has to do with thread safety and how random numbers are generated: it’s up to an
application to ensure that only one thread at a time accesses the Random objects it
manages. Don’t worry, we only have one thread of execution in our Web Pages.

String computerMove;
Random rand = new Random();
switch ( rand.Next(3) ) {
  case 0:
  computerMove = "Rock";
  break;
  case 1:
  computerMove = "Paper";
  break;
  case 2:
  computerMove = "Scissors";
  break;
}

Now, this switch statement is perfectly OK, but suppose that we use it in the following code
segment:

String computerMove;
Random rand = new Random();
switch ( rand.Next(3) ) {
  case 0:
  computerMove = "Rock";
  break;
  case 1:
  computerMove = "Paper";
  break;
  case 2:
  computerMove = "Scissors";
  break;
}
<p>The computer's move is @computerMove</p>

Now there is a subtle error on the last line! The problem here is due to definite assignment, the idea
that the Java compiler must be able to determine that a variable has definitely been assigned a
value before its value is used. Definite assignment was discussed earlier in this chapter. In this
example, it’s true that the three cases in the switch cover all the possibilities, but the compiler is not
smart enough to figure that out; it just sees that there is an integer-valued expression in the switch
but not all possible integer values are covered by the given cases.

129
A simple solution is to replace the final case in the switch statement with default. With a default
case, all possible values of the expression in the switch are certainly covered, and the compiler
knows that computerMove is definitely assigned a value:

String computerMove;
Random rand = new Random();
switch ( rand.Next(3) ) {
  case 0:
  computerMove = "Rock";
  break;
  case 1:
  computerMove = "Paper";
  break;
  default:
  computerMove = "Scissors";
  break;
}
<p>The computer's move is @computerMove</p>

5.8. Variables and Scope


Variables can be defined within any of the compound statements in the C# statements. Once a
variable is defined within a compound statement, it is visible until the end of that compound
statement. This has two implications:

1. After the compound statement, the variable is no longer visible. You can declare a variable by
the same name in a later compound statement.

2. Another variable by the same name cannot be defined in a nested compound statement.

5.9. Exception Handling


In addition to the control structures that determine the normal flow of control in a program, C# has
a way to deal with "exceptional" cases that throw the flow of control off its normal track. When an
error occurs during the execution of a program, the default behavior is to terminate the program
and to print an error message. However, C# makes it possible to "catch" such errors and program a
response different from simply letting the program crash. This is done with the try..catch statement.
In this section, we will take a preliminary and incomplete look the try..catch statement, leaving out
a lot of the rather complex syntax of this statement. Error handling is a complex topic, which we
will return to in a later chapter, and we will cover the full syntax of try..catch at that time.

5.9.1. Exceptions

The term exception is used to refer to the type of error that one might want to handle with a
try..catch. An exception is an exception to the normal flow of control in the program. The term is
used in preference to "error" because in some cases, an exception might not be considered to be an
error at all. You can sometimes think of an exception as just another way to organize a program.

130
Exceptions in C# are represented as objects of type Exception. Actual exceptions are usually defined
by subclasses of Exception. Different subclasses represent different types of exceptions. We will
look at only three types of exception in this section: FormatException, ArgumentException, and
DivideByZeroException.

A FormatException can occur when an attempt is made to convert a a value with String.Format but
the value and format specifier are not compatible. Consider the function call String.Format("The
cost is {0:Q2}.", 15.32m). Q2 is not a valid format for decimals, so this will receive a
FormatException. If C2 had been specified, then the call would work and return "The cost is $15.32".
If nothing is done to handle the exception, the web page will not render but the exception will be
displayed instead.

An ArgumentException can occur when an illegal value is passed as an argument to a method. For
example, if a method requires that a parameter be greater than or equal to zero, an
ArgumentException might occur when a negative value is passed to the subroutine. How to
respond to the illegal value is up to the person who wrote the code, so we can’t simply say that
every illegal parameter value will result in an ArgumentException. However, it is a common
response.

A DivideByZeroException occurs when a value is divided by zero. This is caught at compile-time


when there is a literal 0, but a computed divisor won’t be known until run-time.

5.9.2. try..catch

When an exception occurs, we say that the exception is "thrown". For example, we say that
String.Format(formatString,val) throws an exception of type FormatException when a format in the
formatString is illegal. When an exception is thrown, it is possible to "catch" the exception and
prevent it from crashing the program. This is done with a try..catch statement. In simplified form,
the syntax for a try..catch can be:

try {
  statements-1
}
catch ( exception-class-name variable-name ) {
  statements-2
}

The exception-class-name could be FormatException, ArgumentException, or some other exception


class. When the computer executes this try..catch statement, it executes the statements in the try
part. If no exception occurs during the execution of statements-1, then the computer just skips over
the catch part and proceeds with the rest of the program. However, if an exception of type
exception-class-name occurs during the execution of statements-1, the computer immediately
jumps from the point where the exception occurs to the catch part and executes statements-2,
skipping any remaining statements in statements-1. Note that only one type of exception is caught;
if some other type of exception occurs during the execution of statements-1, it will crash the
program as usual.

131
Actually, it may not crash the program — what an uncaught exception does is interrupt
the flow of control; the computer will look for a try/catch in a larger scope (the calling
TIP
method) if it cannot find one in the current method. So, at any point in a program, any
layer could choose to handle an exception generated lower down in the stack.

During the execution of statements-2, the variable-name represents the exception object, so that
you can, for example, print it out. The exception object contains information about the cause of the
exception. This includes an error message, which will be displayed if you print out the exception
object.

After the end of the catch part, the computer proceeds with the rest of the program; the exception
has been caught and handled and does not crash the program.

By the way, note that the braces, { and }, are part of the syntax of the try..catch statement. They are
required even if there is only one statement between the braces. This is different from the other
statements we have seen, where the braces around a single statement are optional.

As an example, suppose that you are computing a value that involves division. Then we could say:

double y;
bool success;
try {
  y = Math.PI/x; //x's value previously set by other computations
  success = true;
}
catch ( DivideByZeroException e ) {
  y = Double.NaN;
  success = false;
}

If an error is thrown by the division then the second statement in the try part is skipped, and the
statements in the catch part are executed. (In this example, I set z to be the value Double.NaN when
an exception occurs. Double.NaN is the special "not-a-number" value for type double.)

It’s not always a good idea to catch exceptions and continue with the program. Often that can just
lead to an even bigger mess later on, and it might be better just to let the exception crash the
program at the point where it occurs. However, sometimes it’s possible to recover from an error.

For example, the AsInt() method on strings does not throw ArgumentException when the string
value is not a valid integer value; instead it simply returns a 0. Similarly, if you can take a
reasonable default action rather than throw an exception, you might code your web pages and
methods accordingly.

5.9.3. Multiple catch blocks and finally

You can put multiple catch blocks after a try block. C# will stop at the first one that satisfies the
exception found, using inheritance (see a future chapter for information on inheritance). It is
convention to list only the specific exception classes, not a more general one.

132
There is another type of block you can place after (or instead of) your catch blocks, a finally block.
Its syntax is:

try {
... try code
}
... zero or more catch blocks
finally {
... finally code
}

The finally code is used to clean up; it is always executed (even if a catch block is executed; the
finaly follows the catch block). This is useful to clean up external resources such as file references
and open sockets, as if you do not clean up those resources your code’s runtime environment will
be impacted as it tracks items it does not need to track.

For more information, see MSDN’s Exceptions and Exception Handling (C# Programming Guide).

5.9.4. throw

Exceptions are generated by a throw statement. If, for example, you determine that you have been
handed invalid values for a computation, then instead of having a bad value come back, you can
throw an exception to alert the caller.

if (word.Length < 1) {
  throw new ArgumentException("Input word has to contain characters");
}

Notice that we have to "new" the exception, just as we did with Random. In C#, there are exception
classes, and you create an exception object to throw.

There are many exceptions available to you in C#; you can use these, or define your own. The
standard exceptions all can be created with a message as shown above; it is a good idea to include a
message, but consider also the impact on security — your message has to convey useful information
without providing information that would allow entry into the system.

Table 3. ASP.NET Exception classes

Exception type Description Example

System Exceptions

IndexOutOfRangeException an array is indexed improperly Indexing an array outside its


valid range: arr[arr.Length+1]

NullReferenceException a null object is referenced object o = null;


o.ToString(); // null
referenced

133
Exception type Description Example

AccessViolationException invalid memory is accessed invalid pointer used in


unmanaged or unsafe code (a C
library, typically)

InvalidOperationException method in an invalid state used by collections and other


libraries that track state, for
example, calling
Enumerator.GetNext() after
removing an item from the
underlying collection.

Argument Exceptions

ArgumentNullException null argument when not String s = null;


allowed "hello".IndexOf(s); // IndexOf
can’t take a null

ArgumentOutOfRangeException arguments required to be in a String s = "string";


given range s.Chars[9]; // range check
rather than index check

External Exceptions

OMException encapsulates COM HRESULT Occurs when accessing COM.


information.

SEHException encapsulates Win32 structured Occurs when accessing


exception handling unmanaged code.
information.

To see how to define your own exceptions, see Creating and Throwing Exceptions (C# Programming
Guide)

5.10. Arrays
There is another control structure in C# that requires at least a brief introduction to arrays to be
useful. This structure will turn out to be extremely useful when we visit collections in a later
chapter.

This section is an introduction to arrays. Arrays are a basic and very commonly used data structure,
and array processing is often an exercise in using control structures.

5.10.1. Creating and Using Arrays

A data structure consists of a number of data items chunked together so that they can be treated as
a unit. An array is a data structure in which the items are arranged as a numbered sequence, so
that each individual item can be referred to by its position number. In C# all the items must be of
the same type, and the numbering always starts at zero. You will need to learn several new terms to
talk about arrays: The number of items in an array is called the length of the array. The type of the
individual items in an array is called the base type of the array. And the position number of an

134
item in an array is called the index of that item.

Suppose that you want to write a program that will process the names of, say, one thousand people.
You will need a way to deal with all that data. Before you knew about arrays, you might have
thought that the program would need a thousand variables to hold the thousand names, and if you
wanted to print out all the names, you would need a thousand print statements. Clearly, that would
be ridiculous! In reality, you can put all the names into an array. The array is a represented by a
single variable, but it holds the entire list of names. The length of the array would be 1000, since
there are 1000 individual names. The base type of the array would be string since the items in the
array are strings. The first name would be at index 0 in the array, the second name at index 1, and
so on, up to the thousandth name at index 999.

The base type of an array can be any C# type, but for now, we will stick to arrays whose base type is
string or one of the other primitive types. If the base type of an array is int, it is referred to as an
"array of ints." An array with base type string is referred to as an "array of strings." However, an
array is not, properly speaking, a list of integers or strings or other values. It is better thought of as
a list of variables of type int, or a list of variables of type string, or of some other type. As always,
there is some potential for confusion between the two uses of a variable: as a name for a memory
location and as a name for the value stored in that memory location. Each position in an array acts
as a variable. Each position can hold a value of a specified type (the base type of the array), just as a
variable can hold a value. The value can be changed at any time, just as the value of a variable can
be changed. The items in an array — really, the individual variables that make up the array — are
more often referred to as the elements of the array.

As I mentioned above, when you use an array in a program, you can use a variable to refer to array
as a whole. But you often need to refer to the individual elements of the array. The name for an
element of an array is based on the name for the array and the index number of the element. The
syntax for referring to an element looks, for example, like this: namelist[7]. Here, namelist is the
variable that names the array as a whole, and namelist[7] refers to the element at index 7 in that
array. That is, to refer to an element of an array, you use the array name, followed by element index
enclosed in square brackets. An element name of this form can be used like any other variable: You
can assign a value to it, print it out, use it in an expression.

If this looks familiar, it’s because we already saw indexing when we wanted to look
inside a string value at individual characters: a string behaves like an array of
NOTE characters in this respect. One of the quirks of a primitive type is that the compiler
can choose to handle special cases related to the primitives. Indexing does not work
th
on numbers, that is, you cannot pull out the i digits of an int x using x[i].

An array also has a Length property representing its length. For example, you can refer to the
length of the array namelist as namelist.Length. However, you cannot assign a value to
namelist.Length, since the length of an array cannot be changed.

Before you can use a variable to refer to an array, that variable must be declared, and it must have
a type. For an array of strings, for example, the type for the array variable would be string[], and
for an array of ints, it would be int[]. In general, an array type consists of the base type of the array
followed by a pair of empty square brackets. Array types can be used to declare variables; for
example,

135
string[] nameList;
int[] a;
double[] prices;

and variables declared in this way can refer to arrays. However, declaring a variable does not make
the actual array. Like all variables, an array variable has to be assigned a value before it can be
used. In this case, the value is an array. Arrays have to be created using a special syntax. (The
syntax is related to the fact that arrays in C# are actually objects, but that doesn’t need to concern
us here.) Arrays are created with an operator named new. Here are some examples:

nameList = new string[1000];


a = new int[5];
prices = new double[100];

The general syntax is

array-variable = new base-type[array-length];

The length of the array can be given as either an integer or an integer-valued expression. For
example, after the assignment statement "a = new int[5];", a is an array containing the five integer
elements a[0], a[1], a[2], a[3], and a[4]. Also, a.length would have the value 5. It’s useful to have a
picture in mind:

When you create an array of int, each element of the array is automatically initialized to zero. Any
array of numbers is filled with zeros when it is created. An array of boolean is filled with the value
false. And an array of char is filled with the character that has Unicode code number zero. (For an
array of string, the initial value is null, a special value used for objects that we won’t encounter
officially until a later chapter.)

You assign a value into an array item by referencing the item on the left-hand side of an assignment
statement, like so:

a[0] = 1;

There is another form of initialization that both allocates the array space and assigns values, like so:

136
int[] a = { 2, 4, 6, 8 };

This initializes a to have 4 elements with the initial values 2, 4, 6, and 8, respectively. It is equivalent
to saying:

int[] a = new int[4];


a[0] = 2;
a[1] = 4;
a[2] = 6;
a[3] = 8;

5.10.2. Arrays and For Loops

A lot of the real power of arrays comes from the fact that the index of an element can be given by
an integer variable or even an integer-valued expression. For example, if list is an array and i is a
variable of type int, then you can use list[i] and even list[2*i+1] as variable names. The meaning of
list[i] depends on the value of i. This becomes especially useful when we want to process all the
elements of an array, since that can be done with a for loop. For example, to print out all the items
in an array, list, we can just write

for (int i = 0; i < list.Length; i++) {


  <p>@list[i]</p>
}

The first time through the loop, i is 0, and list[i] refers to list[0]. So, it is the value stored in the
variable list[0] that is printed. The second time through the loop, i is 1, and the value stored in
list[1] is printed. The loop ends after printing the value of list[4], when i becomes equal to 5 and the
continuation condition "i < list.Length" is no longer true. This is a typical example of using a loop to
process an array.

Notice what is going on here: because arrays count elements starting from zero, the
length is always one more than the highest index. So, for loops compare the index to
be < the length. You might try changing this to <= the length and see how it behaves.
NOTE In fact, you will be walking off the end of the array, and should expect an exception
to be thrown. C# and Java added this protection — in earlier languages such as C,
you could walk off the end of an array and look at memory you didn’t actually have
access to.

Let’s look at a few more examples. Suppose that A is an array of double, and we want to find the
average of all the elements of the array. We can use a for loop to add up the numbers, and then
divide by the length of the array to get the average:

137
double total; // The sum of the numbers in the array.
double average; // The average of the numbers.
total = 0;
for ( int i = 0; i < A.Length; i++ ) {
  total = total + A[i]; // Add element number i to the total.
}
average = total / A.Length; // A.length is the number of items

Another typical problem is to find the largest number in the array A. The strategy is to go through
the array, keeping track of the largest number found so far. We’ll store the largest number found so
far in a variable called max. As we look through the array, whenever we find a number larger than
the current value of max, we change the value of max to that larger value. After the whole array
has been processed, max is the largest item in the array overall. The only question is, what should
the original value of max be? One possibility is to start with max equal to A[0], and then to look
through the rest of the array, starting from A[1], for larger items:

double max; // The largest number seen so far.


max = A[0]; // At first, the largest number seen is A[0].
int i;
for ( i = 1; i < A.length; i++ ) {
  if (A[i] > max) {
  max = A[i];
  }
}
// at this point, max is the largest item in A

Sometimes, you only want to process some elements of the array. In that case, you can use an if
statement inside the for loop to decide whether or not to process a given element. Let’s look at the
problem of averaging the elements of an array, but this time, suppose that we only want to average
the non-zero elements. In this case, the number of items that we add up can be less than the length
of the array, so we will need to keep a count of the number of items added to the sum:

138
double total; // The sum of the non-zero numbers in the array.
int count; // The number of non-zero numbers.
double average; // The average of the non-zero numbers.
total = 0;
count = 0;
for (int i = 0; i < A.length; i++ ) {
  if ( A[i] != 0 ) {
  total += A[i]; // Add element to the total
  count++; // and count it.
  }
}
if (count == 0) {
  <p>There were no non-zero elements.</p>
}
else {
  average = total / count; // Divide by number of items
  <p>Average of @count elements is @average</p>
}

5.10.3. Random Access

So far, my examples of array processing have used sequential access. That is, the elements of the
array were processed one after the other in the sequence in which they occur in the array. But one
of the big advantages of arrays is that they allow random access. That is, every element of the array
is equally accessible at any given time.

As an example, let’s look at a well-known problem called the birthday problem: Suppose that there
are N people in a room. What’s the chance that there are two people in the room who have the
same birthday? (That is, they were born on the same day in the same month, but not necessarily in
the same year.) Most people severely underestimate the probability. We will actually look at a
different version of the question: Suppose you choose people at random and check their birthdays.
How many people will you check before you find one who has the same birthday as someone
you’ve already checked? Of course, the answer in a particular case depends on random factors, but
we can simulate the experiment with a computer program and run the program several times to
get an idea of how many people need to be checked on average.

To simulate the experiment, we need to keep track of each birthday that we find. There are 365
different possible birthdays. (We’ll ignore leap years.) For each possible birthday, we need to keep
track of whether or not we have already found a person who has that birthday. The answer to this
question is a boolean value, true or false. To hold the data for all 365 possible birthdays, we can use
an array of 365 boolean values:

bool[] used;
used = new bool[365];

For this problem, the days of the year are numbered from 0 to 364. The value of used[i] is true if
someone has been selected whose birthday is day number i. Initially, all the values in the array are

139
false. (Remember that this is done automatically when the array is created.) When we select
someone whose birthday is day number i, we first check whether used[i] is true. If it is true, then
this is the second person with that birthday. We are done. On the other hand, if used[i] is false, we
set used[i] to be true to record the fact that we’ve encountered someone with that birthday, and we
go on to the next person. Here is a program that carries out the simulated experiment (of course, in
the program, there are no simulated people, only simulated birthdays):

<!DOCTYPE html>
<html>
<head>
  <title>Duplicate Birthdays</title>
  <style type="text/css">
  body {
  background-color: beige;
  font-family: Verdana, Arial;
  margin: 50px;
  }
  </style>
</head>

<body>
  <p>We simulate choosing people at random and checking the day of
  the year they were born on. If the birthday is the same as one that
  was seen previously, stop, and output the number of people who were checked.
  </p>
@{
  boolean[] used = new boolean[365];
  // For recording the possible birthdays
  // that have been seen so far. A value
  // of true in used[i] means that a person
  // whose birthday is the i-th day of the
  // year has been found.
  // Initially, all entries are false.

  int count = 0; // The number of people who have been checked.

  Random rand = new Random(); // for generating random numbers.

  while (true) {
  // Select a birthday at random, from 0 to 364.
  // If the birthday has already been used, quit.
  // Otherwise, record the birthday as used.

  int birthday; // The selected birthday.


  birthday = rand.Next(365);
  count++;

  <p>Person @count has birthday number @birthday.</p>

  if ( used[birthday] ) {

140
  // This day was found before; it's a duplicate. We are done.
  break;
  }

  used[birthday] = true;

  } // end while

  <p>duplicate birthday was found after @count tries.</p>


}
</body>
</html>

You should study the program to understand how it works and how it uses the array. Also, try it out!
You will probably find that a duplicate birthday tends to occur sooner than you expect.

5.10.4. Partially Full Arrays

Consider an application where the number of items that we want to store in an array changes as
the program runs. Since the size of the array can’t be changed, a separate counter variable must be
used to keep track of how many spaces in the array are in use. (Of course, every space in the array
has to contain something; the question is, how many spaces contain useful or valid items?)

Consider, for example, a program that reads positive integers entered by the user and stores them
for later processing. The program stops reading when the user inputs a number that is less than or
equal to zero. The input numbers can be kept in an array, numbers, of type int[]. Let’s say that no
more than 100 numbers will be input. Then the size of the array can be fixed at 100. But the
program must keep track of how many numbers have actually been read and stored in the array.
For this, it can use an integer variable. Each time a number is stored in the array, we have to count
it; that is, value of the counter variable must be incremented by one. One question is, when we add
a new item to the array, where do we put it? Well, if the number of items is count, then they would
be stored in the array in positions number 0, 1, …, (count-1). The next open spot would be position
number count, so that’s where we should put the new item.

As a rather silly example, let’s write a program that will read the numbers input by the user and
then print them in the reverse of the order in which they were entered. We will provide the user
with a form, and then use an empty field to determine where the numbers stop. (This is, at least, a
processing task that requires that the numbers be saved in an array. Note that many types of
processing, such as finding the sum or average or maximum of the numbers, can be done without
saving the individual numbers.)

<!DOCTYPE html>
<html>
<head>
  <title>Reverse Numbers</title>

  <style type="text/css">
  body {
  background-color: beige;

141
  font-family: Verdana, Arial;
  margin: 50px;
  }
  form {
  padding: 10px;
  border-style: solid;
  width: 300px;
  }
  </style>
</head>

<body>
  <p>Enter up to 10 numbers and I will print them out in reverse order
  after you click Reverse. I stop looking at numbers after the first blank entry.</
p>
  <form action="" method="post">
  <p>
  <input type="text" name="a" />
  <input type="text" name="b" />
  <input type="text" name="c" />
  <input type="text" name="d" />
  <input type="text" name="e" />
  <input type="text" name="f" />
  <input type="text" name="g" />
  <input type="text" name="h" />
  <input type="text" name="i" />
  <input type="text" name="j" />
  </p>
  <p><input type="submit" value="Reverse" /></p>
  </form>
  <br />

  @{
  if (IsPost) {
  int[] numbers = new int[10]; // An array for storing the input values.
  int count = 0; // The number of numbers saved in the array.
  int i=0;
  for (char c='a';c<'k';c++,i++) {
  if (Request[c.ToString()].IsInt()) {
  numbers[i] = Request[c.ToString()].AsInt();
  count++;
  } else {
  break; // stop at first non-integer
  }
  }

  <p>Your numbers in reverse order are:</p>


  @: <ul>
  for (i = count - 1; i >= 0; i--) {
  <li> @numbers[i] </li>
  }

142
  @: </ul>
  } // end IsPost
}
</body>
</html>

It is especially important to note how the variable count plays a dual role. It is the number of items
that have been entered into the array. But it is also the index of the next available spot in the array.

 When the time comes to print


out the numbers in the array, the last occupied spot in the array is location
count - 1, so the for loop prints out values starting from
location count - 1 and going down to 0. This is also a nice
example of processing the elements of an array in reverse order.

Note that the page says it stops at the first blank — IsInt will return false on a blank, so
that satisfies it. However, what other values will cause IsInt to return false? Consider
TIP
how to inform the user in those situations - take ReverseNumbers.cshtml and modify it
to make this change.

You might wonder what would happen in this program if our array was not large enough for the
expected number of values. The result would be an error that would crash the program. When the
processing attempts to store a number beyond the end of the array, there is no such array element.
The attempt to use an index past the end of the array generates an exception of type
IndexOutOfBoundsException. Exceptions of this type are a common source of run-time errors in
programs that use arrays.

5.10.5. Two-dimensional Arrays

The arrays that we have considered so far are "one-dimensional." This means that the array
consists of a sequence of elements that can be thought of as being laid out along a line. It is also
possible to have two-dimensional arrays, where the elements can be laid out in a rectangular grid.
We consider them only briefly here.

In a two-dimensional, or "2D," array, the elements can be arranged in rows and columns. Here, for
example, is a 2D array of int that has five rows and seven columns:

143
This 5-by-7 grid contains a total of 35 elements. The rows in a 2D array are numbered 0, 1, 2, …, up
to the number of rows minus one. Similarly, the columns are numbered from zero up to the
number of columns minus one. Each individual element in the array can be picked out by
specifying its row number and its column number. (The illustration shown here is not what the
array actually looks like in the computer’s memory, but it does show the logical structure of the
array.)

In C#, the syntax for two-dimensional arrays is similar to the syntax for one-dimensional arrays,
except that an extra index is involved, since picking out an element requires both a row number
and a column number. For example, if A is a 2D array of int, then A[3][2] would be the element in
row 3, column 2. That would pick out the number 17 in the array shown above. The type for A
would be given as int[][], with two pairs of empty brackets. To declare the array variable and create
the array, you could say,

int[][] A;
A = new int[5][7];

The second line creates a 2D array with 5 rows and 7 columns. Two-dimensional arrays are often
processed using nested for loops. For example, the following code segment will print out the
elements of A in a table:

<table>
@for (int row = 0; row < 5; row++ ) {
  @:<tr>
  for (int col = 0; col < 7; col++ ) {
  <td> A[row][col] </td>
  }
  @:</tr>
}
</table>

The base type of a 2D array can be anything, so you can have arrays of type double[][], String[][],
and so on.

There are some natural uses for 2D arrays. For example, a 2D array can be used to store the
contents of the board in a game such as chess or checkers. Tables in databases are natural two-
dimensional arrays, but with more complex types. But sometimes two-dimensional arrays are used
in problems in which the grid is not so visually obvious. Consider a company that owns 25 stores.
Suppose that the company has data about the profit earned at each store for each month in the year
2014. If the stores are numbered from 0 to 24, and if the twelve months from January 2014 through
December 2014 are numbered from 0 to 11, then the profit data could be stored in an array, profit,
created as follows:

double[][] profit;
profit = new double[25][12];

144
profit[3][2] would be the amount of profit earned at store number 3 in March, and more generally,
profit[storeNum][monthNum] would be the amount of profit earned in store number storeNum in
month number monthNum (where the numbering, remember, starts from zero).

Let’s assume that the profit array has already been filled with data. This data can be processed in a
lot of interesting ways. For example, the total profit for the company — for the whole year from all
its stores — can be calculated by adding up all the entries in the array:

double totalProfit; // Company's total profit in 2014.


int store, month; // variables for looping through the stores and the months
totalProfit = 0;
for ( store = 0; store < 25; store++ ) {
  for ( month = 0; month < 12; month++ ) {
  totalProfit += profit[store][month];
  }
}

Sometimes it is necessary to process a single row or a single column of an array, not the entire
array. For example, to compute the total profit earned by the company in December, that is, in
month number 11, you could use the loop:

double decemberProfit;
int storeNum;
decemberProfit = 0.0;
for ( storeNum = 0; storeNum < 25; storeNum++ ) {
  decemberProfit += profit[storeNum][11];
}

Two-dimensional arrays are sometimes useful, but they are much less common than one-
dimensional arrays. Java actually allows arrays of even higher dimension, but they are only rarely
encountered in practice.

5.10.6. For-each Loops

Arrays are often processed using for loops. A for loop makes it easy to process each element in an
array from beginning to end. For example, if nameList is an array of strings, then all the values in
the list can be printed using

for (int i = 0; i < nameList.Length; i++) {


  <p>nameList[i]</p>
}

This type of processing is so common that there is an alternative form of the for loop that makes it
easier to write. The alternative is called a for-each loop. It is probably easiest to start with an
example. Here is a for-each loop for printing all the values in an array of Strings:

145
foreach ( string name in nameList ) {
  <p>name</p>
}

The meaning of "foreach (string name in nameList)" is "for each string, name, in the array,
nameList, do the following". The effect is that the variable name takes on each of the values in
nameList in turn, and the body of the loop is executed for each of those values. Note that there is no
array index in the loop. The loop control variable, name, represents one of the values in the array,
not the index of one of the values.

The for-each loop is meant specifically for processing all the values in a data structure, and we will
see later that it applies to other data structures besides arrays. The for-each loop makes it possible
to process the values without even knowing the details of how the data is structured. In the case of
arrays, it lets you avoid the complications of using array indices.

A for-each loop will perform the same operation for each value that is stored in an array. If
itemArray is an array of type BaseType[], then a for-each loop for anArray has the form:

foreach ( BaseType item in itemArray ) {


  .
  . // process the item
  .
}

As usual, the braces are optional if there is only one statement inside the loop, except in Razor. In
this loop, item is the loop control variable. It is declared as a variable of type BaseType, where
BaseType is the base type of the array. (In a for-each loop, the loop control variable must be
declared in the loop; it cannot be a variable that already exists outside the loop.) When this loop is
executed, each value from the array is assigned to item in turn and the body of the loop is executed
for each value. Thus, the above loop is exactly equivalent to:

for ( int index = 0; index < itemArray.Length; index++ ) {


  BaseType item;
  item = itemArray[index]; // Get one of the values from the array
  .
  . // process the item
  .
}

For example, if A is an array of type int[], then we could print all the values from A with the for-
each loop:

foreach ( int item in A ) {


  <p> item </p>
}

146
and we could add up all the positive integers in A with:

int sum = 0; // This will be the sum of all the positive numbers in A
foreach ( int item in A ) {
  if (item > 0) {
  sum = sum + item;
  }
}

The for-each loop is not always appropriate. For example, there is no simple way to use it to process
the items in just a part of an array, or to process the elements in reverse order. However, it does
make the code a little simpler when you do want to process all the values, in order. since it
eliminates any need to use array indices.

It’s important to note that a for-each loop processes the values in the array, not the elements
(where an element means the actual memory location that is part of the array). For example,
consider the following incorrect attempt to fill an array of integers with 17’s:

int[] intList = new int[10];


foreach ( int item in intList ) { // INCORRECT! DOES NOT MODIFY THE ARRAY!
  item = 17;
}

The assignment statement item = 17 assigns the value 17 to the loop control variable, item.
However, this has nothing to do with the array. When the body of the loop is executed, the value
from one of the elements of the array is copied into item. The statement item = 17 replaces that
copied value but has no effect on the array element from which it was copied; the value in the array
is not changed. The loop is equivalent to

int[] intList = new int[10];


for ( int i = 0; i < intList.length; i++ ) {
  int item = intList[i];
  item = 17; // Doesn't change intList[i]!
}

which certainly does not change the value of any element in the array.

In order to change the items in the array, you have to use a for loop, like so:

int[] intList = new int[10];


for ( int i = 0; i < intList.length; i++ ) {
  intList[i] = 17; // OK!
}

147
5.11. When good code has bugs
Review Chapter 1’s debugging tips now that you have the core programming operations behind
you. Even with that general advice, you will find that you still collect your own set of "gotchas",
problems you hit due to your own style. If you’re curious to see what other people hit, see Top 10
useful yet paranoid Java programming techniques. Yes, it’s Java, but the issues listed occur in C#
also.

5.12. There’s more …


C# is rich with features that an introductory course can’t reach. Explore these features of C# that
add greatly to its functionality:

• the using() { } statement manages an object, automatically creating and disposing of it once the
block completes, even with exceptions.

• defining your own exceptions

• threading, which involves locking, synchronization, and controlling threads within a single
application

5.13. Further Reading


• https://msdn.microsoft.com/en-us/library/system.string.format(v=vs.110).aspx String.Format

• C# Succinctly Chapter 2 https://www.syncfusion.com/resources/techportal/ebooks/csharp


(requires account)

5.14. Exercises
1. Now that you know more C#, you can come up with even more inventive "Stump the Newbie"
problems. Start with a web page that compiles and displays correctly. One player looks away
while the other player adds an error to the program. Then the first player tries to find and fix
the error. You get two points if you find the error without compiling the program, one point if
you find it using the compiler, and your opponent gets a point if you don’t find it.

2. Consider the following code:

  int n = 10;
  int i = n;
  while (i > 1) {
  <p>@i</p>
  if (i % 2 == 0) {
  i = i / 2;
  } else {
  i = i + 1;
  }
  }

148
a. Draw a table that shows the value of the variables i and n during the execution of loop. The
table should contain one column for each variable and one line for each iteration.

b. What is the output of this program?

c. Can you provide an explanation that this loop will terminate for any positive value of n?

3. How many times do you have to roll a pair of dice before they come up snake eyes? You could
do the experiment by rolling the dice by hand. Write a web page that simulates the experiment,
using C# for your algorithm. The page should report the number of rolls that it makes before the
dice come up snake eyes. (Note: "Snake eyes" means that both dice show a value of 1.) Simulate
rolling a pair of dice. You can simulate rolling one die by choosing one of the integers 1, 2, 3, 4, 5,
or 6 at random. The number you pick represents the number on the die after it is rolled. The
expression rand.Next(6)+1 does the computation to select a random integer between 1 and 6.
You can assign this value to a variable to represent one of the dice that are being rolled. Do this
twice and add the results together to get the total roll.

4. Which integer between 1 and 10000 has the largest number of divisors, and how many divisors
does it have? Write a Web Page to find the answers using Razor and C# for your algorithm and
display the results. It is possible that several integers in this range have the same, maximum
number of divisors. Your program only has to print out one of them. The example
CountDivisors.cshtml in this chapter discussed divisors.

You might need some hints about how to find a maximum value. The basic idea is to go through
all the integers, keeping track of the largest number of divisors that you’ve seen so far. Also,
keep track of the integer that had that number of divisors.

5. Write a Web Page application that will evaluate simple expressions such as 17 + 3 and 3.14159 *
4.7. The expressions are to be typed in by the user. The input always consists of a number,
followed by an operator, followed by another number. The operators that are allowed are +, -, *,
and /. Have the user put the values in a form with 3 fields: the left operand, the operation, and
the right operand. Allow decimal values in the operands and use a select list for the operators.
You should report an error if either value is not a number. Your program should print out the
expression and the result after the user clicks Compute. The form should be available for the
user to enter a new expression: make this a one-page Web Page application.

6. Write a Web Page application that reads one line of input text and breaks it up into words. Your
page should give the user a text input so the user can only input one line; however, that line can
be as long as they want it to be. The words should be output one per line. A word is defined to
be a sequence of letters. Any punctuation in the input that is not part of a word (i.e.,
apostrophes are parts of words if there is an s before and after them; semicolons, commas,
quotes, and other punctuation are not parts of words) should be discarded. For example, if the
user inputs the line He said, "That’s not a good idea." then the output of the program should
be

149
He
said
That's
not
a
good
idea

Use string.Split() to break up a string into an array using the space character as the word
separator. You will still need to clean up the "words" since punctuation may be on either end, or
it may be punctuation in its entirety. You will need to trim punctuation (look into string.Trim()
for this).

To test whether a character is a letter, you might use (ch >= 'a' && ch ⇐ 'z') || (ch >= 'A' && ch ⇐
'Z'). However, this only works in English and similar languages. A better choice is to call the
standard function ch.IsLetter(), which returns a boolean value of true if ch is a letter and false if
it is not. This works for any Unicode character. You might want to look at all of the methods
available on char values here: https://msdn.microsoft.com/en-us/library/system.char.aspx to
determine if one will help you break up strings and handle punctuation at the same time.

7. The goal of this exercise is to program a “Guess My Number” game. When it’s finished, it will
work like this:

I'm thinking of a number between 1 and 100


(including both). Can you guess what it is?
Enter a number: 45 [Submit Guess]

// once submit is clicked, it would output:

Your guess is: 45


The number I was thinking of is: 14
You were off by: 31

To choose a random number, use the Random class as shown in the previous chapter, like so:

  Random rand = new Random();


  int number = rand.Next(100)+1;
  ...

The result of Next(100) is between 0 and 99, including both. Adding 1 yields a number between 1
and 100, including both.

Let the user keep playing as much as they want; you generate a new number each time they
enter their guess.

8. An exercise above asked you to find the number in the range 1 to 10000 that has the largest

150
number of divisors. You only had to print out one such number. Revise the program so that it
will print out all numbers that have the maximum number of divisors. Use an array as follows:
As you count the divisors for each number, store each count in an array. Then at the end of the
program, you can go through the array and print out all the numbers that have the maximum
count. The output on the Web Page should look something like this:

Among integers between 1 and 10000,


The maximum number of divisors was 64.
Numbers with that many divisors include:
  7560
  9240

9. An example in this chapter tried to answer the question, How many random people do you have
to select before you find a duplicate birthday? The source code for that web page was given in
BirthdayProblem.cshtml. Here are some related questions:

• How many random people do you have to select before you find three people who share the
same birthday? (That is, all three people were born on the same day in the same month, but
not necessarily in the same year.)

• Suppose you choose 365 people at random. How many different birthdays will they have?
(The number could theoretically be anywhere from 1 to 365).

• How many different people do you have to check before you’ve found at least one person
with a birthday on each of the 365 days of the year?

Write three separate pages to answer these questions and a home page that directs the user
to each of the pages. Review the elements of Web Design from chapter 2 in deciding on your
flow and the content of each page. Each of your pages should simulate choosing people at
random and checking their birthdays. (In each case, ignore the possibility of leap years.)

10. Write a page that requests a line of text from the user and then tests to see if the letters in it
form a palindrome. A palindrome as the same letters forward and back; it is not case sensitive.
For example,"A Man, A Plan, A Canal - Panama!" is a famous long palindrome. It informs the
user where in the string the palindrome test failed, if it is not a palindrome, and lets them know
it is a palindrome, if it is.

11. Write a page that requests a line of text from a user, and regardless of how it was typed in (all
upper, all lower, or a mix), converts it to "Title Case" where every word has its first letter
transformed to upper case and the rest transformed to lower case. You will want to use
string.Split() to break the line into an array of strings. You will need to ensure that any
punctuation at the start of a word does not cause it to fail to be capitalized. So, for example, if
the user input: He said, "hello" then you would output He Said "Hello".

To test whether a character is a letter, you might use (ch >= 'a' && ch ⇐ 'z') || (ch >= 'A' && ch ⇐
'Z'). However, this only works in English and similar languages. A better choice is to call the
standard function ch.IsLetter(), which returns a boolean value of true if ch is a letter and false if
it is not. This works for any Unicode character. You might want to look at all of the methods
available on char values here: https://msdn.microsoft.com/en-us/library/system.char.aspx to
determine if one will help you break up strings and handle punctuation at the same time.

151
Remember that you have both the string and the char types here, so be sure to check both for
useful methods for this exercise.

5.15. Project
Look at your original proposal and layout; introduce functionality with data hard-coded in arrays.
We will be conquering databases next, and will replace array accesses with database accesses there.

For example, you might hard-code several GPS locations in an array, and then take the user’s
location and calculate which of the "stored" locations they are closest to.

152
Chapter 6. Deploying Web Page Applications
Your web application isn’t live until it’s actually on the internet. So far, we’ve been running our
website on the same machine as our browser; that’s highly unrealistic — and may have lead you to
take non-viable shortcuts such as absolute paths and security loopholes.

In this chapter we will deploy our web applications so that we can test for any defects due to our
assumptions. We will explore security issues in a later chapter.

You’ve probably heard of the cloud at this point in your studies. We will deploy our web
applications to a cloud provider that lets small applications like ours be deployed for free. This will
require creating an account — so read through the privacy policy and ensure you are comfortable
with it.

What can you do if you do not want cloud deployment? That’s a much larger task, outside the scope
of this text. You would need to set up an IIS server on a computer that is visible on the internet,
with a fixed IP address and domain name, so that you could put your application on it and your
users could find it.

6.1. Choosing a service


Most services have free trials, but cost money after the first few weeks. There is one, at the time of
this writing, that is free for one application at a time: appharbor.com. Read their terms of service
https://appharbor.com/page/terms before you create your account (which is free) at
https://appharbor.com/ .

Creating an account requires only a valid email address; you will be required to use a link provided
to that email address to complete your registration.

It’s important, when using a cloud service, such as AppHarbor, to be aware of any requirements
they put on your application. AppHarbor in particular requires that if you have user accounts, you
inform the user that the information is available to both your application and to AppHarbor. Also,
as is common among cloud services, AppHarbor reserves the right to use your application in their
advertising.

Because you are deploying to the cloud, you must not violate anyone’s copyright, per the Digital
Millenium Copyright Act. Disney is well-known for going after anyone putting Disney images on
their pages. Keep it safe, use wikimedia commons, flickr commons, or use your own images (photos
or drawings). Yes, this may make your pages not look as good without an authentic Mickey Mouse
image, but your future employers may actually come across your web application (especially if you
put it in your portfolio), and will appreciate that you respected copyrights rather than "borrowing"
images, text, or code. If you really feel the need to re-use copyrighted material, be sure it falls
within general fair use guidelines, not academic fair use, which is more lenient, but only pertains to
material kept in the school setting.

6.2. Platform as a Service


AppHarbor is a way for you to publish your application and make it available on the internet. They

153
provide the ASP.NET platform as a service.

AppHarbor takes the source for an ASP.NET-based website and builds, tests, and deploys it. You
provide your source to AppHarbor using a software versioning system (Git, Mercurial, Subversion,
or Team Foundation Server) to provide a stable version of your software to AppHarbor.

AppHarbor then builds your code locally. Why? This way it can compile to its host operating system
and available libraries, and not rely on being compatible with your local build and system setup. It
also has hooks to run unit tests if you provide them, so you can stop a deployment if the tests do not
pass.

If the build and tests succeed, then AppHarbor will deploy your application: install it and make it
available through an IIS server. It will do all of this for free, giving you one "worker thread". You
purchase additional worker threads and services such as databases, caching, and e-mail if you want
to, for scaling or more functionality; we won’t purchase any for our projects.

AppHarbor can scale your application across CPUs, disks, and servers to provide better
performance and reliability (for a fee). This means it could actually run within several different
instances, and have copies of its data on several different disks, to allow more users to access it and
to provide failover should a disk go bad.

When your web application is live, it is available through a free subdomain of apphb.com or a
domain name you’ve purchased and configured (for a fee).

AppHarbor is actually running within Amazon Web Services — so their service layer is the ASP.NET
configuration and management, and how they choose to do scaling and services within the AWS
infrastructure. (AWS provides direct ASP.NET support as well.) Your application is running in the
same server as other applications, but AppHarbor isolates different applications from each other.

For more information, visit https://appharbor.com/page/how-it-works

The basic setup can be found in a variety of services like this; ASP.NET C# cloud service include:

• AppHarbor

• Microsoft Azure

• Amazon Web Services for ASP.NET

• Moncaí (in beta)

• many ISPs offer ASP.NET support, from monolith GoDaddy to smaller shops

• and, via Docker, a wide variety of hosting services are available

6.3. Deploying on AppHarbor


AppHarbor provides instructions for deployment here: https://support.appharbor.com/kb/getting-
started/deploying-your-first-application-using-git

This requires that you have Git installed on your machine. Git is code versioning/repository
software that manages source code.

154
Once you have an AppHarbor account (created at appharbor.com), follow these steps:

1. Log in to your account at appharbor.com

2. Create an application at appharbor.com/applications. You will pick a name for the


application — call it the same name you gave your application (not Default, but
"SimpleCalculator", for example).

3. Once the application is created, you are on the application page. The box on the left that has the
application name at the top has a button "Repository URL" on the bottom. Click that box, and
then get the AppHarbor respository URL that is provided. It will look something like this:
https://username@appharbor.com/applicationname-32.git
4. Make or update your local code repository with Git:

a. The very first time you deploy, you will need to install Git on your machine. See "How do I
get Git?" below for how to do this.

b. The first time you deploy a new application, you first need to put it into a local Git
repository. See "Create a Git Repository" below for how to do this.

c. Re-deployments will require udpating your local Git Repository; it is not sufficient to just
edit the files. See "Update a Git Repository" below for the steps to do this.

5. Open a git command window on your local machine, and cd to the directory at the root of your
site (where _AppStart.cshtml and Default.cshtml and other files are located). Add the remote
repository like this:

git remote add appharbor MY_REPOSITORY_URL ①

① Replace MY_REPOSITORY_URL with the repository URL you got in step 3 above.

You will only need to do this step one time, the first time you deploy your repository.

6. Deploy using:

git push appharbor master

This step will ask you for your AppHarbor password. Once you supply that, it will then prepare
and upload the files from your local code repository to AppHarbor. You will see messages
similar to this (but with different numbers and specific names):

Counting objects: 126, done.


Compressing objects: 100% (123/123), done.
Writing objects: 100% (126/126), 535.97 KiB | 0 bytes/s, done.
Total 126 (delta 14), reused 0 (delta 0)
To https://appharbor.com/simplecalculator-1.git
 * [new branch] master -> master

The number of files will change based on what was changed since your last commit and upload.

155
Do this step each time you want to update the code on AppHarbor. It will be updated to the
currently committed code on your local git repository (see step 4.c. above for how to do that).

Once you deploy to AppHarbor, there may be issues. So next you will need to go to your live
application and start testing it. Continue with Deployed on AppHarbor.

6.3.1. How do I get Git?

Git software will need to be on your machine; there is a great download writeup here with Linux,
Mac, and Windows links:

We will be installing the portable Windows version.

1. Go to https://git-scm.com/download/win

2. Cancel the default download that starts

3. Scroll down to the portable thumbdrive versions, and download the appropriate one for your
hardware (32-bit or 64-bit). This will get you the most current version. At the time of this
writing, that was the 8-19-16 release of 2.9.3, and is almost 30MB in size.

4. Once it is downloaded, run the installer. You can install it on a local drive, or if you want to take
Git with you between several machines, install it on a thumb drive for portable use.

a. The first question the installer asks is where to install it.

b. Then it unpacks the compressed file to proceed — depending on your machine, this can take
some time.

c. That’s it, it’s installed.

5. You can now get to a git command window by double-clicking on git-cmd.exe in your portable
git directory. If you want some more information on what you now have, open
"Readme.portable", located in the installation directory, in a text editor such as notepad or
notepad++. This file contains instructions on how to set up your environment to make git
available in regular Windows cmd windows.

There is a good online tutorial of Git available at try.github.io if you’d like to see some of the power
of this new tool. Below we will discuss just the commands needed for deployment.

6.3.2. Create a Git Repository

Before your first deployment of a given application you will need to create a local Git repository so
that you can push your application to AppHarbor. Git provides a web API that AppHarbor uses to
get its copy of your code.

156
Why not use FTP?
AppHarbor uses Git and not FTP since it expects you to be working on code that is
under active development or maintenance — that means version control to any
professional developer. Git provides that version control, so AppHarbor doesn’t have
TIP to.

AppHarbor even supports deployment from GitHub accounts, so true multi-user cloud-
based development can be done with several users sharing code through GitHub and
deploying to AppHarbor when they have a stable codeline.

In a git command window (start with git-bash or git-cmd in our portable Git) do:

1. cd path\to\my\application — your application is located in the directory you put your WebSite


in when you first created it.

2. git init — this creates a new directory, .git, which will be used by git to track your software
files.

3. Add a file named .gitignore with the contents of the .gitignore file available here.

4. Add a file named .gitattributes with the contents of the .gitattributes file available here.

These two files clarify what files in your local codeline get transferred to AppHarbor and how
they are dealt with in that transfer. They are needed due to "fluff" Visual Studio needs that your
deployed application should not have present, and because AppHarbor does its own builds, it
does not use the compiled code from your local machine.

5. Issue these two commands so that line endings in your text files (a perennial issue with Linux
vs. Windows file transfers) do not cause deployment issues:

git config core.autocrlf false


git config core.safecrlf false

6. git add . — this adds all files, except for those mentioned in .gitignore, to your repository

7. git commit -m "Initial commit" — this finalizes the initial state of your repo and makes it
deployable to AppHarbor. The list of all of the files (not excluded by .gitignore) will scroll up
your screen as the commit completes. There will be quite a few files if you worked from a Visual
Studio template, both files you created and files the template provided.

Your repository is now ready for its first deployment.

6.3.3. Update a Git Repository

Once your code is in a Git Repository, you can use Git to save its state. Git is a very powerful version
control tool; you can save the state of your code at any point in its development. Once saved, you
can return to that state at a future time, or undo recent saves if they turn out to be flawed. We
aren’t going to explore those capabilities of Git, but there are good writeups on that at git-scm.com
and a tutorial at try.github.io

157
You have to save its state when you want to push that state up to AppHarbor.

These are the steps in making an update:

1. In Visual Studio, make the changes to your local code; you may add files, remove files, or alter
files.

2. Open a git command window. You will need to:

a. git add . to add any newly created files and any altered files to your commit. This will find
them all.

b. git rm FILENAME with the FILENAME of any file that you deleted from your project, to
remove it in your commit (so it will be removed on AppHarbor);if you did not remove any,
you do not need to issue any git rm requests. If you are not sure if you have deleted any,
perform a git status command and see if it reports any files removed. Those files will need
to have git rm commands issued to record their removal. Read the output of git status
carefully — it tells you what commands to issue before issuing a commit.

c. git commit -m "UPDATE_MESSAGE" — record a one-line summary (think "tweet") of the changes


captured in this commit; this captures all of your changes for the next upload

6.4. Deployed on AppHarbor


You’ve set up Git, set up AppHarbor, and pushed your local code. But how do you get to your
application?

First, it needs to be compiled on AppHarbor. Once you deploy with a git push, go to
https://appharbor.com/applications — here I have just my first one, SimpleCalculator (circled):

Figure 11. AppHarbor applications page

158
Click on your application name to go to its administrative panel. There you will see the build status
for all of your uploads:

Figure 12. AppHarbor SimpleCalculator application page

If it failed, there will be a red crossed circle to the left of the build. As you can see, it took me a few
tries to clean up my deployment. Click on the red crossed circle to see the build details page:

Figure 13. AppHarbor SimpleCalculator build details page

159
Click on the second "View Log" to see what the problems are. You may need to resort to
StackOverflow if it is a configuration issue — as you can see from the list of failures on my screen, I
worked through a few configuration issues (now addressed in this writeup and associated
.gitignore file).

You will have to go back to your source code in Visual Studio, fix the issue, re-build and test locally,
then update your local repository and git push the code back up to AppHarber. Check the build
status again. Once your codeline is completely working, you will see the other mark next to your
build, a green bulls-eye.

The green bulls-eye means that your application is working! AppHarbor automatically deploys a
working build to its live site, putting it on the internet. It takes a minute or two to deploy your
application. If you had a previously working one, it will be a few minutes until the new one
replaces it. The build that is deployed has ACTIVE next to it; if you want a different build to be
deployed, you can click its DEPLOY button to swap it with the currently active one.

6.5. Access a Deployed Application on AppHarbor


Once you have a green build that is deployed, you can access your web application with the "Go to
your application" link in the upper-right of the administration panel. The link for your deployed
application will be some variant of the application name. For example, my application is named
SimpleCalculator, and my URL is simplecalculator-1.apphb.com.

You can give that link to anyone — anyone with internet access can get to your deployed website.

The URL goes to the home page of your website. For ASP.NET, that is Default.cshtml. If you have not
defined that page in your web site, users will get a page that says "Welcome to nginx!" - so you
should make sure to include a Default landing page, even if all it does is reroute the user to your
application page. Users can type in a full URL to a particular page, if you provide it to them. So,

http://simplecalculator-1.apphb.com/SimpleCalculator.cshtml

will bring up my calculator page. (Note, I deleted it, so that link won’t take you to it.)

6.6. Got Database?


We haven’t covered databases yet, but if you used the ASP.NET Web Site with Identity Template, you
already have a database. You are going to need to locate and add database support for this database
to work in deployment. App Harbor only supports a single database in an application, so any
additional tables will also need to be (re-)located in the Identity database.

If you used the Web Site Starter Site Template, then you have a SQL Compact
Edition (SQLCE) database (.sdf file). This textbook does not discuss how to deploy
CAUTION
a SQLCE database, and App Harbor recommends that you not use it, as it will
only be a transient database (destroyed each time the app idles).

Go to your application’s main administration panel and look for "Add ons". Click this, then page
down until you find "Shared SQL Server"; click "See More" for that service, and then add the Free

160
level of support. This provides 20 MB of storage (something to keep in mind).

Upon a successful install, you are returned to the Application Console. Click the "SQL Server"
service that appears under so that you go back to the Add On console for SQL Server — you need to
return to do some more configuration.

On the SQL Server add-on page, you need to click "Go to SQL Server" to configure the connection
string. This puts you on a page with private configuration information (not the kind of information
to publish yourself — these are the private keys that get you to your private SQL Server instance).

On that page click the "Edit database configuration" button. In the Alias box, put the name of your
connection — this is the name that you used in the Web.config file. With the Web Pages with
Identity template it is DefaultConnection. Click Apply. This returns you to the previous page, and the
alias now shows up in the information there.

Why did you do this? So that AppHarbor will find its database server rather than the one you
developed with. It has to do this, as it has a shared database server, not private ones for each
application.

It is possible to access this deployed database, if you want to "look behind the web
site". Install SQL Server 2008, and use it to access the database

On the Application Console, you will see a "Configuration variables" link by your
SQL Server add-on (below the builds). Click this link. Three keys are listed there:

• SQLSERVER_CONNECTION_STRING

NOTE • SQLSERVER_CONNECTION_STRING_ALIAS

• SQLSERVER_URI

You can use these values to initiate a connection to your database from your local
machine using SQL Server 2008 Management Studio. For more information on the
AppHarber shared SQL Server service, see Using Sequelizer and the support note on
remote access Can’t connect to SQL Server from Management Studio, both on
appharbor.com.

6.7. Your Second Application


You can have multiple applications available on your AppHarbor account. Use all of the steps
provided earlier in this chapter for each deployed application:

1. Create a Visual Studio Web Site or Project

2. Create a local Git Repo for it.

3. Create an AppHarbor application for it.

The local repo and AppHarbor deployment are specific to the VS Web Site; each Web Site needs its
own local Git repo and its own AppHarbor application.

161
6.8. Summary of Deployment
th
Setup (per machine) First Time (per application) N Time

1. Install Visual Studio 1. Create a VS Web Site 1. Modify a VS Web Site


2. Install Portable Git 2. Create an AppHarbor 2. Update the local git repo
3. Create an AppHarbor application * open git-cmd window
Account 3. Create a local git repo: * cd to directory
* open git-cmd window * git status
* cd to directory * git add .
* git init * git rm FILENAME (if needed)
* create .gitignore and * git commit -m
.gitattributes "DESCRIBE_CHANGES"
* git config core.autocrlf 3. Put the code on AppHarbor:
false * git push appharbor master
* git config core.safecrlf 4. Go to AppHarbor application
false build result page; if working, go
* git add . to application, otherwise
* git commit -m "initial repeat.
commit"
4. Tie the local git repo to your
AppHarbor application:
* git remote add appharbor
MY_REPOSITORY_URL
5. Put the code on AppHarbor:
* git push appharbor master
6. If needed, configure Shared
SQL and tell it your connection
name. 7. Go to AppHarbor
application build result page; if
working, go to application,
th
otherwise see N time.

6.9. Removing an Application


If you decide you no longer want an application to be deployed, you can delete it from AppHarbor.
This removes your code from AppHarbor and removes the last build from AppHarbor’s Web
Server.

To do this, navigate to your application from appharbor.com/applications and on that page, select
Settings under the application name (I’ve circled it in red in the image):

162
Figure 14. Demo Application Management Menu

On the Settings page, at the very bottom, there is a DELETE button. Click on that to remove your
application from AppHarbor:

Figure 15. Demo Application Settings Page (bottom)

It will double-check with you in case you slipped; but once you click on SURE?, your application is
gone.

163
Figure 16. Demo Application Deleted

Your local code and local git repository are still on your machine. So, if you wish to deploy it in the
future, you will be able to create a new application and then connect your existing git repository to
that application by issuing a new git remote command to connect that existing local Git repository
to your new AppHarbor application.

To remove your local Git repository, you would delete the .git directory and all of its contents from
within your Web Site directory on your machine. (If you have hidden system files in your File
Explorer view, you will not see the .git director. It is there; change the File Explorer properties on
your machine to display hidden files to see it.) Your .gitignore and .gitattributes files will still be
there; they can also safely be deleted. This has no effect on Visual Studio or the files currently in
your VS Web Site or Project.

6.10. Keeping it Free


Remember to review the AppHarber policies. They are there to ensure in part that they can keep
their free service free. As long as you never request an add-on or resource that costs
money — AppHarbor will tell you if it costs money — then it’s free (given their current policies).

There are limits; your database can only grow to a certain size, and there are likely bandwidth
limits for the amount of data going between your application and its users.

6.11. Debugging on the Internet


If you publish to Azure, then there are hooks to let you debug your web application in real time, as
described here: https://azure.microsoft.com/en-us/documentation/articles/web-sites-dotnet-
troubleshoot-visual-studio/

Since we are using AppHarbor, we have these choices:

• expose errors as they happen in the deployed site

164
• put output in our web page to show what is happening on the live server

• use try/catch to trap exceptions so our pages work around the error

• debug on the local machine (not the live server) with Visual Studio’s debugger

Note that AppHarbor offers you advice on this also here https://support.appharbor.com/kb/getting-
started/frequently-asked-questions.

6.11.1. Expose errors as they happen in the deployed site

One of the differences between a Debug build and a Release build is that a Release build (which is
what AppHarbor does) prevents clients from seeing stack traces that occur in your web application.

You can turn this back on, but should only use it for testing and turn it off in general in a deployed
site.

If you see this page:

Figure 17. AppHarbor default error page

Then follow its instructions to change your Web.config file, adding

<customErrors mode="Off"/>

within the <system.web> block within <configuration>.

In a live website, you would instead actually not turn the custom errors off, but add a custom error
page that overrides the default AppHarbor custom error page (the one shown in the picture above).
You may have seen this on another website, a typical error page displays the HTML error code and

165
some sort of "oops" image.

Figure 18. Tumbler’s 503 error page

6.11.2. Put output on a web page

You can gain quite a bit of information about the state of your web server using the object
ServerInfo that is available to you.

Listing 13. ServerInfo.cshtml

<!DOCTYPE html>
<html>
  <head>
  <title>Server Info</title>
  </head>
  <body>
  @ServerInfo.GetHtml()
  </body>
</html>

the GetHTML generates a table that will provide you with information about the state of your
server: environment variables, configuration, version, and much more. Do not use this on a
production page that casual users can see, as it provides hackers with information they can use to
break into the server and your application.

166
Do not use this on a production page that casual users can see, as it
CAUTION provides hackers with information they can use to break into the server
and your application.

Rather than display global information, pick and choose what you display. You already know how
to do this in the HTML and in a Razor code block (this same line works the same way in both):

<p>@totalServed</p>

This will display the value in the variable totalServed.

There is a shorthand in a Razor code block as well:

@{
  // code here
  ...

  @totalServed

  // code continues
  ...
}

This will also display the value, at that point in the code block. The @ tells Razor to put the current
value of totalServed into the output stream. Since there is no HTML formatting around it, it is
simply put there, so it will show up without formatting on your page.

This works with strings, numbers, and even objects — the ToString() method of non-strings is called
to convert them to string values. Most objects just report on their type, which isn’t very useful.
ASP.NET provides you with a useful helper, ObjectInfo, which will generate a string containing the
type of the expression it is handed and its value.

167
Listing 14. DebugDemo.cshtml

<!DOCTYPE html>
<html>
  <head>
  <title>Debug Demo</title>
  </head>
  <body>
  @{
  var weekday = DateTime.Now.DayOfWeek;
  @ObjectInfo.Print(weekday)

  var message = "Hello, it's" + weekday;


  }
  @ObjectInfo.Print(DateTime.Now)

  @ObjectInfo.Print(message)

  </body>
</html>

The output HTML on a Friday afternoon in August was:

<!DOCTYPE html>
<html>
  <head>
  <title>Debug Demo</title>
  </head>
  <body>
  <p>DayOfWeek Friday<p> ① ②
  <p>DateTime 8/23/2016 2:00:20 PM</p> ③
  <p>string "Hello, it's Friday"</p>
  </body>
</html>

① If you view the Page Source, you will see quite a bit of generated styling using div’s, not simple
paragraphs. ObjectInfo.Print colorizes its contents to hint at their difference, putting the type
name in blue, strings in red, and so on.

② DayOfWeek is a C# enum, and Friday is one of its values.

③ For non-strings, the ToString() is used to get the value for ObjectInfo.Print. The argument passed
to it does not have to be a local variable — it can be a property or method or more complex
expression.

You can use ObjectInfo.Print() with some very interesting objects such as Request and Response,
like so: @ObjectInfo.Print(Request). They will print out complex information that exposes the
internal workings of your website, so use them with caution on a live website.

168
If you start printing out values in a live website, be careful not to give away
private information. You must protect data such as passwords and personal
information. When we cover users, you will see how to restrict display to only
WARNING
administrative users, but even that should be done with caution. Once your
information is in an HTTP response, anyone can "watch the wire" and see the
information, unless you encode it.

6.11.3. Use try..catch

When a page hits an exception, the displayed page shows just the exception, not the HTML that was
generated before it on the page. Sometimes it helps to be able to see what was happening before the
exception was hit; try..catch can be used as a debugging tool to help you do this.

The try..catch block stops ASP.NET from turning the response into just an error message. Instead,
you retain control on the page and can add your own error text to provide information that is
useful to you.

@{
  try {
  // do a lot of math that you think should work
  ...

  }
  catch (DivideByZeroException ex ) {
  <p>Please report the following information to tech support:</p>
  <p>ex.Message</p>
  ObjectInfo.Print(someVar)
  ObjectInfo.Print(anotherVar)
  <p>Thank you</p>
  }

// Other code or markup here ...

Now when your page gets a DivideByZeroException, it is not halted, but will add the exception and
the values of someVar and anotherVar to the output to help you determine the cause of the error.

When you use this approach, be careful about how the page behaves should the exception
occur — execution will continue after the catch block, so your local variables need to hold values
that will not trigger continued exceptions, or you will still have an exception result rather than a
complete HTML page.

6.11.4. The Visual Studio debugger

When you run your web site locally on your development machine, you can debug it in Visual
Studio. Its debugger lets you step through code, line by line, or from breakpoint to breakpoint, and
inspect the value of local variables. You can drill into variables to look at their contents when they

169
are complex objects.

you can set breakpoints on any C# code in your page. To do this, click in the gutter to the left of your
code on the Visual Studio. If a red circle appears, then you have a "breakpoint". If no red circle
appears, then either you didn’t hit the correct gutter (on mine it is the grey column left of the code)
or the line is not actual C# code. You cannot set breakpoints on HTML-only lines, only those that the
Razor Engine will evaluate.

Now, when you run your web site, it will stop at that breakpoint and a debug toolbar will be
available to you. You can inspect variables by mousing over them to see their current contents.
When you are ready to continue, use the debug tool bar to move to the next statement or to
continue running the program until the next breakpoint.

Figure 19. Visual Studio debug toolbar

The "step into" item is highlighted: use that to move to the next statement. Use the "continue" item (
→ ) to have your website run until another break point is hit.

For more information on the Visual Studio debugger, see Debugging in Visual Studio.

6.12. Further Reading


• AppHarbor Terms of Service

• How AppHarbor Works

• AppHarbor Support: Deploying your first application using Git

• AppHarbor FAQ

• git-scm.com a git informational site by the folks at git.

• Try Git

• Getting Started with Git a DZone reference card

• ASP.NET Web Pages (Razor) Troubleshooting Guide

• Deploying your ASP.NET App on AppHarbor from the DevCurry blog

6.13. Exercises
1. Pick a previous exercise and deploy it. Visit its pages on the internet.

2. Then deploy a second application and visit it on the internet.

3. Remove an application and its local git repo. Try to visit its page on the internet — it will no
longer be there.

4. Play "Stump The Newbie" with a classmate: make a page that runs but requires some debugging
for your peer to fix. See what steps they take to determine the cause of the problem and how
they fix it. Would you have looked for the problem differently, or fixed it differently?

170
6.14. Project
Deploy your prototype web application. Once you have a working deployment, get some friends or
classmates to try it out, collect feedback from them, make changes, and re-deploy it.

171
Chapter 7. C# Methods, Classes, and Objects
So far, C# looks very similar to JavaScript and Java. It is object-oriented, so it supports reusability
through classes with methods and properties and polymorphism with inheritance, interfaces,and
overloading. C# also introduces some unique and powerful features, such as delegates (type-safe
function pointers) and lambda expressions (anonymous functions). There is a rich set of foundation
classes provided in ASP.NET, the Foundation Class Library, providing collections, threads and
locking, security, and much more.

Object oriented design requires defining a class and then giving it both class (static) properties and
methods and object (instance) properties and methods. Instances of the class are called objects.
Static properties and methods are shared by all of the instances — if one changes it, they all see the
change. In fact, anyone who can see the class can see them (more on this in a bit). Each instance of
the class gets its own copy to manipulate of the instance properties and methods in the class.

So far we’ve been playing fast and loose with static versus instance methods and properties; it’s
time to clear that up:

• When we call a method or access a property by dotting off of a local variable or a property
(remember, DateTime.Now is a property), then we are calling the instance method or property
for the object instance that variable holds. If we change the property value, then it only changes
it for that instance.

• When we call a method or access a property by dotting off of a class name (DateTime and Math
are class names), then we are calling the static method or property of the class — there is only
one copy of that property or method, and it’s visible to us. If we change the property value, then
everyone who accesses that property sees the change.

DateTime.Now.Month accesses the Month property of the instance stored in the Now property of
the DateTime class. Math.Sqrt(9) accesses the static method Sqrt on the Math class.

How do we tell which ones are static versus instance? As you will see as we introduce the language
structures, the keyword static is used on static properties and methods, and no such keyword is
used on instance properties and methods.

Let’s look at methods first, then classes and their properties and methods.

7.1. Methods
So far we’ve only written short blocks of code in our web pages. In this chapter, we’ll show you how
to organize more complex code and make code reusable, using methods and classes.

A method is a collection of code with a name and some inputs; it may or may not produce an
output, and it may also alter the state of the object and of any objects it has access to. Because we
can give it inputs, the method can change its action based on the values it is given. If the method
returns a value, our program gets the value when the method completes.

Methods provide the behaviors for a class or an object; typically these are things the class or
instance will want to do repeatedly. Rather than have a huge method for a complex action, we may

172
also define smaller methods that are called by other methods. Each method should have one clear
action that it performs.

Methods can be used over and over, at different places in the program. A method can even be used
inside another method. This allows you to write simple methods and then use them to help write
more complex methods, which can then be used in turn in other methods. In this way, very
complex programs can be built up step-by-step, where each step in the construction is reasonably
simple.

7.1.1. Adding methods to a page

Razor provides a way for us to put server-side code in a web page. There is a special Razor block for
adding methods to the web page, @functions { .. }. This block has to contain pure C#, no embedded
HTML is permitted; this keeps the Razor engine simpler, and Razor provides Helpers, a similar tool,
to create re-usable code blocks that do contain embedded HTML.

Razor’s @functions are methods. We’ve mentioned earlier that your page is an object; in fact, there
is a class for it, and each user who accesses your page gets an instance of that class. The @functions
that you define are methods in that class.

Here is a function block containing functions to compute a tip amount:

@functions {
  double ComputeTip(double subtotal, double tipRate) {
  double tip;

  tip = subtotal * tipRate;

  return tip;
  }

Notice that this is computing just the tip — it is important to clearly document what your method is
doing, so that those who use it can tell what it is doing. We see this with Math.Sin and the other
trigonometric functions: they clarify that they work on radian values, not degrees. There are tools
that will turn the comments on your methods into such documentation, so be sure to clearly
document the assumptions your method makes and the computation it performs. Not everyone will
have access to your source code.

Let’s pull apart the function above: double ComputeTip specifies that this method will return a value
of type double, and that its name is ComputeTip. If it did not return a value, its return type would
be the non-type void. Notice the keyword static did not appear — that makes this an instance
method. Instance methods are mainly needed if they change the object state, and you may be able
to determine that this one does not change the object state: it computes a value based solely on its
inputs. It could have been defined static.

Notice that the C# convention is that method names start with an initial uppercase letter and
parameter names start with an initial lowercase letter.

173
Next we see (double subtotal, double tipRate). The parentheses tell the compiler "I am giving you
the parameters now", and are needed even if your method has no parameters. Each parameter is
specified with a type and a name. The name becomes a local variable that we can use inside the
method. When the method is called, the argument value is computed and then copied into the
parameter for use within the method. The parameter’s value is never copied back out to the caller,
so any changes to it will not be seen by the caller.

A parameter’s scope is the method it is defined within. Parameters behave like variables, so no
variable within a method can have the same name as a parameter.

Finally, we see { .. } — this looks like our Razor code block. It is the body of the method. It can only
contain C#, Razor does not permit HTML lines within a method.

Within the code block, you may notice a statement you have not seen before: the return statement:
return tip;. The syntax for this statement is:

  return EXPRESSION;

When that statement is seen within a method, the EXPRESSION is evaluated and the method is
exited, with the value of the expression returned to the caller. This happens no matter where the
return is within the method; if it is within a for loop or a switch statement, execution of the method
halts at that point, and the value is returned to the caller.

Void methods (those not returning values) can use a return; statement to return control to the
caller, or will return control when the closing } is reached, if there was no explicit return
statement.

You can include additional methods in the @functions { } block; and because of how Razor
processes it, the functions can appear anywhere in the page and be called even before they appear.
By convention, we will place them at the top, before they are used.

You can invoke the same method more than once, and you can have one method invoke another. A
method can even invoke itself.

subTotal += ComputeTip(subTotal,chosenRate); ①
total = subTotal + ComputeTax(subTotal,locationCode); ②

① In the code above, you see that subTotal is passed to ComputeTip, and the result is added to
subTotal and put back into the subTotal local variable.

② Next you see that the tax is computed using the new value of subTotal and a location code for
looking up tax rates, and added to subTotal to compute the total amount.

We see that two different methods are called and used in the code above. Notice that the methods
are not executed when the @functions { } block is seen; rather, they are executed when the are
called from other C# code. This is called the flow of execution. It’s important to keep this in mind; if
you never call a method, then it is never executed.

Beginners often wonder why it is worth the trouble to create new methods. There are many

174
reasons, here are a few of them:

• Creating a new method gives you an opportunity to give a name to a group of statements, which
makes code easier to read and understand.

• Introducing new methods can make a program smaller by eliminating repetitive code. For
example, we can compute the tip amount based on the value the user gave us without a
separate computation for each specific amount.

• A common problem solving technique is to break tasks down into sub-problems. Methods allow
you to focus on each sub-problem in isolation, and then compose them into a complete solution.

7.1.2. Parameters and Arguments

Some of the methods we have used require arguments, which are the values you provide when you
invoke the method. For example, to take a substring, you provide the starting and stopping
locations with in the string value.

When you use a method, you provide the arguments. When you write a method, you name the
parameters. The parameter list indicates what arguments are required. The following code shows
an example:

@functions {

  // Put the first letter at the end and add "ay"


  string PigLatin(string word) {
  return word.Substring(1,word.Length-1)+word[0]+"ay";
  }
}

// form to get a word from the user

<p>@PigLatin("Hello") @PigLatin("There"), in Pig Latin your word is: @PigLatin


(yourWord).</p>

PigLatin has a parameter named word with type string. When we call PigLatin, we have to provide
an argument with type string. This can be a variable, a string literal, another method call (for a
method that also returns a string), or an expression which evaluates to a string. In our example,
we’ve called it three times: twice with string literals, and once with a local variable.

Before the method executes, the argument gets assigned to the parameter. In this example, the
argument "Hello" gets assigned to the parameter word for the first call to PigLatin. In each
subsequent call, the value of the argument is assigned to word in turn.

This process is called parameter passing because the value gets passed from outside the method to
the inside. An argument can be any kind of expression, so this works also:

@PigLatin(yourWord+"s");

175
Here the word you supplied has an s added to the end before that value is assigned to the
parameter named word. The value you provide as an argument must have the same type as the
parameter. So if your word was "round", word get the value "rounds" assigned to it.

The value you supply has to be a string. For example, if you try:

 @PigLatin(17); // syntax error

You will get an error message like this:

PigLatin.cshtml(25,10): error CS1502: The best overloaded method match for


'ASP._Page_PigLatin_cshtml.PigLatin(string)' has some invalid arguments
PigLatin.cshtml(25,19): error CS1503: Argument 1: cannot convert from 'int' to
'string'

The first error message is letting you know the compiler tried to find any method named PigLatin
that will work (you can define two methods with the same name — more on this in a bit). The
second one is more useful: it’s telling you your argument has the wrong type.

Sometimes C# can convert an argument from one type to another automatically. For example,
Math.Sqrt requires a double, but if you invoke Math.Sqrt(25), the integer value 25 is automatically
converted to the floating-point value 25.0. But in the case of PigLatin, C# can’t (or won’t) convert the
integer 17 to a string.

Parameters and other variables only exist inside their own methods. Inside your page, there is no
variable named word. If you try to use it there, you’ll get a compiler error.

Because variables and parameters only exist inside the methods where they are defined, they are
often called local variables.

7.1.3. Named Parameters and Optional Arguments

You may have noticed an issue with our pig latin implementation: PigLatin("There") returns the
value hereTay when it should return the value ereThay, since "Th" is the first sound-unit in the word.

Usually only one letter is needed; so we could require a length, but that makes everything work
harder. C# solves this by offering us default parameters. You can specify a default value for a
parameter, and if it is not specified, its default value is used.

To make this work, C# also lets you specify a name next to an argument value, to say what
parameter the value is for. Let’s rewrite our code and see how this works:

176
@functions {

  // Put the first letter at the end and add "ay"


  // if the length gives us nonsense, ignore it and return the word
  string PigLatin(string word, int numChars = 1) {
  if (numChars < 1 || numChars > (word.Length-1)) {
  return word; // just return the word on bad lengths
  }

  return word.Substring(numChars,word.Length-numChars)
  + word.Substring(0,numChars)
  + "ay";
  }
}

// form to get a word from the user

<p>@PigLatin("Hello") @PigLatin("There",2), in Pig Latin your word is: @PigLatin(word:


yourWord).</p>

Because we have given a default value for numChars, if it is not specified then when the method
executes it is given the value 1. We say that numChars is an optional argument.

Notice the final call: @PigLatin(word: yourWord). Here we use the parameter name and a colon to say
what parameter the argument value is assigned to. With named parameters, we don’t have to
match the order specified in the method. We could say: @PigLatin(numChars:2, word:"cheese"). C#
will match up the arguments to the named parameters, rather than using their positions.

If you do not specify parameter names on the method invocation, then positional matching is done.
C# lets you use positional matching for the start of a method call, but once you use a named
parameter, then you have to name the rest of your arguments as well. Any unnamed or unspecified
parameters in the method call must have defaults, and those defaults will be used when the method
is invoked.

Notice that I took care in writing the new version of PigLatin to deal with bad input
values. I also stated how I handled them in the comments on the method. Consider
what inputs can make your method mis-behave, and determine what behavior you
want it to have. Here are some typical choices:

1. just let it do whatever C# would have it do, whether that is to throw an exception
or continue on with a corrupt value (sometimes this is the right thing to do, but it
TIP
should still be made clear that it was a decision made in your design)

2. throw an explicit exception about the bad input values (this informs the caller
about specifically what went wrong, and lets the caller decide how to handle it)

3. handle the situation so that the program continues with some known good state
(this lets the program continue uninterrupted, but does mask the problem of the
bad inputs)

177
C# has another type of variable parameter list, for details on that see
https://msdn.microsoft.com/en-us/library/w5zay9db.aspx.

7.1.4. Parameters and Objects

C# uses pass by value for parameters: the argument value is copied into the parameter value, and
no changes to the parameter’s value are ever seen by the caller. However, if you go through a
parameter to values it has access to (if it is an object or an array), then the changes you make
through the parameter will be visible to the caller.

With arrays, this means that you can change the contents of the array, and the caller will see those
changes.However, if your method changes the parameter’s value, to point to a new array, that
change will not be seen by the caller.

C# also provides two other parameter modes: pass by reference and pass as
output.

"pass by reference" on parameters means that changes to them are seen; this is
done by putting the keyword ref before the parameter type. When used, the
keyword ref must be put before the argument as well, and it must be a storage
location (something that can be on the left of an assignment statement). Any
changes to the parameter’s contents will be visible to the caller.

CAUTION "pass as output" on parameters means that the values are not read in from the
arguments, but are only assigned within the method and then visible upon
return. out must be put both on the parameter declaration and the argument
value. The argument will not be read or copied to the parameter when the
method is called, but they will be updated with the value of the parameter when
the method completes.

This isn’t generally good practice in OO programming, but does give fine-grained
control that is useful in procedural systems programming.

7.1.5. the call stack

When a method is called, it needs space for its parameters. The system notes where it was called
from (the calling method’s activation record). It creates an activation record with room for the
methods parameters, and puts that on the activation record stack, often just called the "call stack",
as its primary contents are method invocations.

When the method completes, its activation record is removed from the stack; if it had a return
value, that is supplied to the calling method for that method to use in the containing expression.

Let’s step through an example with these methods:

178
int Times2(int val) {
  return val*2;
}

int Times10(int val) {


  return val * Times2(5);
}

int TImes20(int val) {


  return val * Times10(2);
}

When Times20(4) is called, an activation record is put on the top of the stack to hold the fact that
Times20 is called, and its parameter val is given the value 4, from the argument value.

Times20(4) will call Times10(2); this creates a new activation record which is put on top. Times10(2)
will call Times2(5). At this point the call stack looks like this:

top of stack

Times2(5) val = 5

Times10(2) val = 2

Times20(4) val = 4

… calls below Times20(4)

bottom of stack

When Times2(5) completes, it is removed from the call stack and returns the value 10 to its caller
(Times10(2)), who then uses it to compute val * 10, using its own value of val, i.e. 2. That then
removes itself from the call stack, returning its value, 20, to Times20(4). That then removes itself
from the call stack, using the returned 20 and its value of val, 4, to compute 80; it then removes
itself from the call stack and returns 80 to its caller.

It’s important to be able to draw call stacks and trace the values in variables — a key style of
debugging is the "code walkthrough" where you are the computer, checking that the code is doing
what you expect with a manual walkthrough yourself rather than running the code.

7.1.6. method syntax

A method is defined in a class; since our Razor pages are turned into classes, it provides us with the
@functions { .. } block to permit us to do this. We can also put methods in classes, as we will see in
the next section.

A method definition in C# takes the form:

179
modifiers return-type method-name ( parameter-list ) {
  statements
}

The statements between the braces, { and }, in a method definition make up the body of the method.
These statements are the instructions that the computer executes when the method is called.
Methods can contain any of the statements discussed previously.

The modifiers that can occur at the beginning of a method definition are words that set certain
characteristics of the method, such as whether it is static or not. Another modifier that can be
specified is the visibility of the method, one of these:

public
the method can be called from anywhere.

private
the method is only visible within the class, so it can only be called from other methods in the
same class.

protected
the method is only visible to its class, or from a subclass of this class.

internal
the method is only visible from within the same project. This limits callers to just your library, if
you were building a library and wanted some internal utility methods.

protected internal
the method is visible from this class, any subclasses (even if in another project), and any other
class in the same project.

If you do not specify a visibility for your method, then its visibility is private . Since you do not
explicitly access the page class for your Razor page, and won’t need to access the methods outside
of the page, this is appropriate.

For the full list of modifiers, some of which are beyond the scope of this text, see
https://msdn.microsoft.com/en-us/library/ms173121.aspx.

If the method computes a value, then the return-type is used to specify the type of value that is
returned by the function. It can be a type name such as string, an array type such as double[], or a
Class - any valid C# type. If the method does not return a value, then the return-type is replaced by
the special value void, which indicates that no value is returned. The term "void" is meant to
indicate that the return value is empty or non-existent.

Finally, we come to the parameter-list of the method. Parameters represent information that is
passed into the method from outside, to be used by the method’s internal computations. The
parameter list in a subroutine can be empty, or it can consist of one or more parameter
declarations of the form parameter-modifier type parameter-name optional-default-value. If there
are several declarations, they are separated by commas. Note that each declaration can name only

180
one parameter. For example, if you want two parameters of type double, you have to say "double x,
double y", rather than "double x, y".

parameter-modifier
is optional and specifies either pass by value (no modifier), pass by reference (ref), or pass as
output (out). ref and out have to be used as prefixes to argument values as well.

type
any valid C# type can be used as a parameter type.

optional-default-value
is specified as = constant-value, providing a default value if no argument value is provided for
this parameter. The constant value can be a literal or a constant expression (something the
compiler can evaluate).

You may also see methods with abbreviated bodies such as this:

public string Name => First + " " + Last;

Here, the method Name has no parameters, and returns the value computed using the
TIP
properties First and Last from the containing class.

These are Expression Body Definitions, and you can read more about them here:
https://msdn.microsoft.com/en-us/library/ms173114.aspx

7.1.7. Helpers

Razor has a feature not found in C# classes, the helper. This is a type of function that embeds HTML
within it, the same way we have already done in our Razor code blocks. You define one helper at a
time, like so:

@helper HelperName (parameters) {


  .. helper body ..
}

Then you can invoke the helper with @HelperName(arguments) later in your Razor page. The
helper body can contain the same code as any other Razor block, that is, it can contain both C# and
HTML.

When you invoke the helper, it is replaced with the HTML that its helper body generates. You do not
use a return statement in a helper.

For example:

181
@helper OperatorList() {
  <option value="add">+</option>
  <option value="sub">-</option>
  <option value="mul">*</option>
  <option value="div">/</option>
  <option value="mod">%</option>
}

<form ...>

...
<select name="op1">@OperatorList</select>
...
<select name="op2">@OperatorList</select>
...

</form>

Here you can see we have a helper that will put the same list of operators wherever it is used. This
helps us keep our page correct — if we need to change the list, we only change it once, and that is
seen everywhere the list is used.

7.2. Classes
Classes are what make object orientation so rich; they provide many, many capabilities. We’ve
already seen methods, but there are properties also, and many aspects of classes to fulfill the OO
features of inheritance, encapsulation, and overloading.

You will define each class in its own file with the file extension .cs. To make your source code
deployable, put these files in the App_Code directory of your project. ASP.NET looks to that
directory to compile code.

What code goes in a class, versus in Razor functions? Object-oriented design says that you design a
class when you want to have the ability to use the functionality from different pages in your web
site. So if you have common functionality that several of your pages use, you would define a class
for it, and then use the class’s methods and properties to access the functionality.

Remember to be DRY : if you find yourself repeating code, then methods and classes are called
for.

7.2.1. Classes live in Namespaces

Namespaces give you a way to group classes into logical groups. You place a class within a
namespace when you define the class, like so:

182
namespace Storage {

  // class definitions here

Typically you put one class in a file; this means you put the namespace clause around it in that file.
You use the same namespace clause in each of your files containing classes in that namespace.

If you do not use a namespace clause, your class is put into the default, unnamed, namespace.
Although this is not good practice, you will often see this done in learn-to-program situations. A
general convention is to put your code in a namespace that matches your project name, and then to
further organize it into multi-level namespaces to separate your code into logical groups.

The namespace name can have multiple parts separated by dots, i.e. Storage.Binary, Storage.Text,
and Storage.Text.Utc are all valid namespace names.

By convention, you build a directory structure that matches your namespace names; where
namespaces use . to separate the name, you make another level of directories. Your classes go in the
lowest directory. So, if the namespace Storage.Text.Utc had a class UtcUtilities, you would see this
directory structure:

Figure 20. Namespace Directory Hierarchy

Namespaces, like classes and methods, start with an Uppercase letter. This is a coding
convention, not a requirement.

TIP Notice another convention here: CamelCase even applies to acronynms like UTC — in a
C# name, we write it as Utc. Similarly, HTML becomes Html when used in a C# name.
This convention may seem grating, but if you want your code to appear professional,
it’s best to follow the convention.

You can decide if the class ought to be visible outside of its assembly by setting an access modifier
on it; these are similar to the ones for methods:

• public : visible outside of its assembly

• internal : only visible within its assembly (the default)

internal, the default, is sufficient for our needs.

What’s an assembly? it’s whatever code was assembled for your application. We aren’t
TIP building cross-assembly projects here, but we do use ASP.NET: everything from that
that we use had to have been declared public.

183
Once you have classes within namespaces, you can then decide how to access them outside of their
namespaces. In order to access a class from another Namespace without qualifying it by its
namespace name, you add a using statement to the top of your .cs file, before the namespace
clause:

using System.Collections;
using System.Web.WebMail;

namespace Storage {

  // class definitions here

The using statement lets you reference classes within that namespace without qualifing them. It
does not let you reference nested namespaces — you have to explicitly add a using statement for
each nested namespace to use its classes without qualification.

You can put any number of using statements at the top of your file, or even within the namespace
clause. If they define classes that have the same names, references to those names are considered
ambiguous; C# has ways to resolve this, the simplest is to fully qualify those names. If your using
namespace contains a class by the same name as your class, the class you are defining is the one
used.

For other ways to resolve ambiguous class names, see https://msdn.microsoft.com/en-


us/library/aa664766(v=vs.71).aspx

7.2.2. Classes define Methods

We’ve already stepped through method definitions; methods are placed within a class, and can
operate either as static methods, called by dotting off of the class name, or as instance methods,
called by dotting off of a variable or property referencing an object of the class type.

namespace Utilities {

  /// methods to manipulate strings


  public class StringUtilities {

  /// returns the word turned into pig latin


  /// assumes the word is a word (not more than one word)
  public static string PigLatin(string word) {
  ...
  }
  }

Here we have put our PigLatin method in a class called StringUtilities, in a namespace called

184
Utilities. So we can invoke the method like so:

  string result = Utilities.StringUtilities.PigLatin("hello");

Because it is a static method, we dot off of the class name.

7.2.3. Constructors: how Classes create Objects

How would we call an instance method? First, we need to be able to create instances of the class.
We saw an early example of this with Random, where we created a new Random object by saying
new Random(). This was actually using something in the class: the constructor.

A constructor is a special code block (you may hear it called a "special method", as it looks like a
method) defined in the class to say what steps to take when a new instance is created. For instance,
you may want to initialize the instance’s properties or you may want to require certain information
be provided when instances are created.

You define a constructor in the same manner as a method except that it has no return type, and the
name is the same as the class name. It also has no return statement — it can only be used within a
new statement, to create an instance of the class.

public class Car


{
  string model;

  public Car()
  {
  model = "Ford";
  }
}

Yes, I did sneak a variable definition into the class; they are allowed in class bodies,
NOTE
too; more on this in a bit.

If you do not define a constructor, then a class implicitly has one that takes no arguments, and
initializes any class variables to their default values (0, false, or null).

If you define a constructor that takes parameters, then there is no longer a default constructor. You
can define as many constructors for a class as you like; they must all take different parameter types
or a different number of parameters.

185
public class Car
{
  string model;

  public Car()
  {
  this("Ford"); // "call" the other constructor; you can only call
  // constructors from other constructors, and you use the
  // special 'method' name `this` to do it.
  // It's good practice to call the more specific
  // constructor, supplying defaults.
  // This avoids duplicating code between constructors.
  }

  public Car(string m)
  {
  model = m;
  }
}

If you do not want instances of the class created, then you can define a 0-arg constructor that is
private; this hides the construtor from any other class. We might do this in our StringUtilities class
to prevent anyone from creating instances, since it only defines static methods:

public class StringUtilities


{
  private StringUtilities() { } // no instances can be created

  ... static methods here


}

In order to create an instance of a class (an object), you have to know what constructor(s) it has.
You create the instance with a new operator, passing the values the constructor requires.

  Car myCar = new Car();


  Car myDaughtersCar = new Car("Volkswagon");

The new operator takes a class name and constructor arguments and returns a new object that has
been created and initialized by the constructor. That new object can be:

1. stored in a variable (as our example)

2. stored in an array of that object’s class

3. stored in a Property of that object’s class

186
  DateTime[] importantDates = {
  new DateTime(1944,1,1), // first computer
  new DateTime(1991,8,6) // first web server
  };

Here we initialize an array with two objects.

That’s handy, but what about the class — perhaps we want to initialize the static
properties. You can define a static initializer in a class like so:

class CalendarEvent {

  static DateTime calendarStarted;

TIP   static {
  calendarStarted = DateTime.Now;
  }
}

In this code, we have a private variable in the class and we initialize it to the current
system time when the class is loaded. It captures the time the calendar was started in
our application.

7.2.4. Objects: where are they?

Objects are pretty complex entities. As such, it’s important to understand that what is in the
variable, array entry, or property is not the mass of the object but is an object reference. Objects are
located in a separate part of your computer’s memory usually called the heap. The address of your
object is what is stored in the variable, array entry, or property. We call this an object reference.

So, if two variables are assigned the same object, then changes to the object in one variable are seen
by the other variable. But we need properties to show this more clearly, so let’s return to this in a
bit.

7.2.5. Classes define Variables and Properties

Classes get their power from having not only methods, to implement common behaviors, but also
by having properties, to store state.

Properties can be at the class level: static; or they can be at the object level: instance.

C# does a very nice job of separating the idea of a property from another idea, that of a variable.

Properties are the visible state of the object.

187
Class local variables (aka fields)

I hinted above that you can have variables defined directly in your class. Static variables are
defined for the class (so all instances share them) and instance variables are defined for instances
(so each instance has its own instance of the local variable, the other instances get their own).

These are defined just like those in code blocks:

class Car
{
  string model;
  int odometer;
  int gallons;

  ... rest of class here


}

Here we see we define three variables in the class; these are not defined static, so when an object is
created, it gets its own three variables local to it. All of its methods can see these variables; they are
primarily used as a way to track the object’s properties.

You could make these variables available outside of the class by giving them an access modifier.
Variables use the same access modifiers as methods, and their default is also private.

It is not good practice to give outside access to class variables; proeprties should be
TIP used instead. For this reason, by convention a class’s variables are initial lower case
like other local variables and are private.

Properties

Properties define state. Static properties define the class state (like Now on DateTime) and instance
properties define the object state (like Month on DateTime).

Poperties are defined like this:

188
class Car
{
  string model;
  int odometer;
  int gallons;

  public int Model {


  get { return model; }
  set { model = value; }
  }

  public double MilesPerGallon {


  get { return odometer/(double)gallons; }
  }

  ... rest of the class


}

Properties define their visibility, type, and name, and then provide their get and set operations. The
get operation is used whenever you access the property in an expression, and the set operation is
used whenever you have the property as the target of an assignment statement.

As you can see in our example, Model is very simple: it simply reads from the instance variable
model, and writes to it (value is a keyword in C#, meaning the value of the right side of the
assignment statement). However, MilesPerGallon only has a get operation, and that is computed
from two of the instance variables. This means that MilesPerGallon cannot be the target of an
assignment statement.

You can put access modifiers on the get and set code blocks; this is useful if you want those who use
your class to get it, but only make it settable within the class. You will see this in StatClass.cs in the
exercises.

Since the style of property that directly reads and writes it underlying variable is so common, C#
defines a shorthand to do both at the same time:

class Car {
  int odometer;
  int gallons;

  public int Model { get; set; }

  public double MilesPerGallon {


  get { return odometer/(double)gallons; }
  }

  ... rest of the class


}

189
Notice that we don’t have to define the variable separately.

This clear definition of properties is a very clever feature of C#. You often want
to "gate" property access with security levels, and ensure that assignments only
CAUTION
get valid values. By using code blocks, you can make sure your properties are
correctly accessed and updated.

Properties, like methods and variables, can have access modifiers. They, like other class contents,
are private by default. When you want a property to be visible state of the class (static) or object
(instance), you need to make it public.

For more on C# Properties see Properties (C# Programming Guide).

7.3. Objects
Now that we have classes, how do we use them?

Let’s define one for our examples with objects:

class CalendarEntry {

  static const Date OldestYearPermitted = new Date(1900,0,0);

  DateTime date;

  public CalendarEntry(Date d, string e) {


  EventDate = d;
  Event = e;
  }

  public string Event { get; set; }

  public DateTime EventDate {

  get {
  return date;
  }

  set {
  // Check boundaries for dates.
  if (value.Year > 1900 && value.Year <= DateTime.Today.Year) {
  date = value;
  } else {
  throw new ArgumentOutOfRangeException();
  }
  }
  }
}

190
Notice the order of defintions in CalendarEntry. Any order is allowed, but by
convention we put them in this order:

• constants (variables defined static const cannot change value and are available
to the class and all instances).

• static variables
NOTE
• instance variables

• constructors

• public methods (static and then instance)

• private methods (static and then instance)

• destructors

7.3.1. The new expression creates instances

When we want to create a CalendarEntry instance, we use a new expression. Because it has defined
a constructor, there is no default constructor; this forces us to provide values for the object’s
properties.

 CalendarEntry internetBirthday =
  new CalendarEntry(
  new DateTime(1991,8,6),"internet's birthday");

Notice that we had to create a DateTime object to put in the EventDate property, used when we create
the CalendarEntry instance, which is then put into the local variable internetBirthday.

This is what that looks like conceptually.

We have two objects on the heap, and the local variable within its scope (which may be a method or
a class).

191
There is a shorthand way to create and initialize an object when its class has only a default or no-
argument constructor:

  new DateTime{ Year = 1901, Month = 6, Day = 30 }

This creates a new instance and then updates its properties to the supplied values. The example
here shows DateTime with three of its properties being initialized. Any uninitialized properties are
set to default values (0, false, or null).

7.3.2. The null value

Now, you might not always have an object; what do you do then? C# provides a special value, null.
This can be assigned to any variable or property that holds an object. If you recall, arrays are
actually objects — so any variable that holds an array can also be set to null.

You can turn any primitive type to one that can also hold a null; do this by delaring the
TIP
variable with a ? after the type. This does require more storage space for the variable.

The ?? operator is a shorthand way to check nullability: x ?? y has the result y if x is


TIP
null, and x if it is not null.

Because variables can hold this value, if you try to look at a property or invoke a method on an
object when there is no object (the value is null), you will get a NullReferenceException. Usually
this is a defect in your code — you should always check for nulls and then determine appropriate
handling, whether it is raising an exception or taking a substitute action.

7.3.3. this

Notice that we have accessed the instance variables, methods, and properties directly by name
within the class, while outside the class you have to dot off of a local variable to access them. There
is an implicit local variable always available within the methods of your class, named this. this
refers to the current object that the method or property is being invoked upon. Within the class
definition, if the reference is not ambiguous, this is optional.

For CalendarEntry, I could have written the constructor like this:

  public CalendarEntry(Date d, string e) {


  this.EventDate = d;
  this.Event = e;
  }

The optional this. has been put in front of each of the properties having values assigned. When the
properties' set code blocks are executed, they are executed against the current object, this.

192
7.3.4. Objects as parameters

Notice that variables hold references to objects. When you change a property in that object, it
makes the change on the heap.

That means if two different variables hold references to the same object, each will see changes the
other made.

  DateTime internetBirthdate = new DateTime(1990,8,6);


  DateTime firstWebPageServed = internetBirthday; ①
  firstWebPageServed.Day = 7;

① Notice that the object reference is copied from internetBirthdate to firstWebPageServed. So both
refer to the same object on the heap. When the Day property of one is changed, it changes it on
the heap: so the change is immediately visible to the other variable as well.

Figure 21. Two Variables Reference the same Object

That also means if a variable passes its value to a parameter, and the method makes changes to the
object through the parameter, they will be visible to the variable after the call completes.

The only way to have that not happen is to ensure the variables point to different objects on the
heap, using a separate new for each one. Even if they have the same property values, there will be
two distinct instances on the heap.

7.3.5. But wait, won’t memory fill up?

It would, yes, if all we did was`new` all day. However, the system is watching everything we do (in
this case, the system is the ASP.NET CLR engine that is running our compiled code). In particular, it
keaps track of whether we have a variable or property referencing an object or not. Once no
variable or property references an object, it can be thrown out, and its memory made available
back to the heap. This is called "garbage collection".

7.3.6. Boxing and Unboxing

I already mentioned the nullable attribute for the primitive types; but that is not always sufficient;
sometimes, you have to have an Object rather than a primitive type.

In fact, each of the C# primitives maps to a specific ASP.NET Class, as shown in the following table.

Table 4. C# type and .NET class

193
C# Type .NET Framework Type

bool System.Boolean

byte System.Byte

sbyte System.SByte

char System.Char

decimal System.Decimal

double System.Double

float System.Single

int System.Int32

uint System.UInt32

long System.Int64

ulong System.UInt64

object System.Object

short System.Int16

ushort System.UInt16

string System.String

This means if you declare a parameter with the .NET type, and use a variable or expression that
results in the C# type, that value will be boxed within an object of the .NET type. Similarly, if you
use of the thes .NET types in an expression where the C# type is needed, it will be automatically
unboxed and its value used; note that a null value in this situation will be handled according to
how the variable was defined: if it’s nullable, it takes the null. Otherwise, it raises a
*NullReferenceException`.

  int currentDay = 26;


  Int32 tomorrow = currentDay + 1; ①

  ... time passes

  currentDay = tomorrow; ②
  tomorrow = currentDay + 1; ①

① currentDay is an int, so it can be added to 1 and will result in an int. The target of the assignment
statement is a Int32 so that result will have to be boxed; it would be the same as saying: Int 32
tomorrow = new Int32(currentDay + 1); We don’t have to explicitly use the new, as our int value
result will be wrapped in an Int32 to automatically box the primitive with object-ness. (We could
call this boxing’s object-ive. Couldn’t resist.)

② When we want to assign an Int32 to an int, the reverse has to happen. The int value within the
Int32 is unboxed, and its value is copied into the variable. Because this behavior is specific to
each particular target type, there is no single method that is called to do it.

194
You may have noticed the type object in our list above; objects can hold any item at all; if they are
assigned a primitive from a local variable, they will box it. To unbox from an object, you have to
first typecast it down to the appropriate primitive type.

  int currentDay = 26;


  object objectDay = currentDay; // boxed, put in the heap

  currentDay = (int)objectDay; // to get it back out

Similarly, you can put any object instance in an object. But to see it as its original class, you will
have to typecast it back to that class. As an object, the methods specific to your class are not
accessible.

  DateTime internetBirthday = new DateTime(1991,8,6);


  object something = internetBirthday; // copies the object reference,
  // but loses its DateTime-ness

  internetBirthday = (DateTime)something; // transform it back

Boxing and Unboxing have a huge impact on performance, so it is best to be aware


NOTE of when you have the C# type and when you have the .NET class. In general, stick
with the C# types unless there’s no way to avoid using the .NET types.

7.4. Inheritance
The object built-in type hints at a key object-orientation feature: inheritance.

Class definitions are a good start at smart programming, as they modularize our code into
understandable units with state and behavior.

We get an even stronger amount of re-use when one class can be a subclass of another class: that is,
it inherits all of the fields, properties, and methods and then adds more.

Often you need classes that differ only a little bit; either one can be the supertype of the other, or
they have a common supertype and they are both its subclasses.

The keyword extends is used to note that a class has a superclass, like so:

class CalendarRepeatingEntry extends CalendarEntry {


  Public int NumRepeats { get; set; }

  ... more added to class


}

All of the public methods, properties and variables in CalendarEntry are now available to
CalendarRepeatingEntry and its instances. So it not only has NumRepeats but also has EventDate

195
and Event.

If you do not specify extends, then your class automatically extends System.Object.

The method, property, and variable access modifiers may make more sense at this point, now that
you have seen inheritance:

public
the method can be called from anywhere.

private
the method is only visible within the class, so it can only be called from other methods in the
same class.

protected
the method is only visible to its class, or from a subclass of this class.

internal
the method is only visible from within the same project. This limits callers to just your library, if
you were building a library and wanted some internal utility methods.

protected internal
the method is visible from this class, any subclasses (even if in another project), and any other
class in the same project.

If you do not specify a visibility for a method, property, or variable then its visibility is private . If
you do not specify a visibliity for a class, then its visibility is internal.

If you have a class and you do not want anyone to create a subclass of it, you add the class modifier
sealed prior to the class name.

7.4.1. Impact on types

We can assign any instance to an object variable because object is the superclass of all other classes.
In fact, for any variable defined to hold a particular class, we can assign not only instances of that
class but also instances of its subclasses. Basically, an object instance is an instance of its immediate
class and also an instance of its superclasses. Each class has one single immediate superclass,
except object (and System.Object, the same class), which has no superclass.

Let’s walk through an example:

196
 CalendarEntry internetBirthday;

 RepeatingCalendarEntry internetParty =
  new RepeatingCalendarEntry {
  EntryDate = newDateTime(1991,8,6),
  Entry = "Internet's Party",
  NumRepeats = 100 };

 internetBirthday = internetParty; // OK
 internetParty.NumRepeats = 101; // OK
 internetBirthday.NumRepeats = 102; // ERROR

 internetParty = internetBirthday; // ERROR


 internetParty = (RepeatingCalendarEntry) internetBirthday; // OK but...

 CalendarEvent tcpBirthday = new CalendarEvent(


  newDateTime(1983,1,1),"TCP's Ratification Date");

 RepeatingCalendarEntry tcpParty;

 tcpParty = tcpBirthday; // ERROR

When we assign internetParty to internetBirthday, this works. Any access of the object through that
variable (internetBirthday) will assume it is a CalendarEntry, and not a RepeatingCalendarEntry. This
means that we can’t access NumRepeats through internetBirthday, since it is hidden by the implicit
cast to be just CalendarEvent.

The other direction is worse: when we try to assign a CalendarEvent instance to a


RepeatingCalendarEvent variable, we can’t do it at all. Why not? because there is no NumRepeats
property in our CalendarEvent instance.

If we know we have a RepeatingCalendarEvent in our CalendarEvent variable, we can typecast it


back to a RepeatingCalendarEvent. Now, our "know" may actually be riddled with bugs, and a
CalendarEvent object may have snuck into our variable; the execution engine does a final type
check at runtime, and if the type cannot be cast because it is not actually a
RepeatingCalendarEvent, then a InvalidCastException is thrown.

7.5. Overloading and Overriding


You may have noticed, if you have been looking at MSDN ASP.NET class specifications, that they
often have methods with the same name but different parameter lists (a different number of
parameters, or a different type parameter at a particular position in the list). This is called
overloading a method with multiple implementations. When you call a method, method resolution
occurs based on the arguments specified; their types have to match the types declared for one of
the overloaded methods. That will be the method called.

For example:

197
namespace System;

class StringUtilities {

  static public char FirstLetter (long i) {


  .... determines the first letter of a short, int, or long
  return i.ToString()[0];
  }

  ststic public char FirstLetter (string s) {


  return s[0];
  }
}

Our class defines two FirstLetter methods, one that operates on longs (and thus, due to automatic
conversion, will also work on ints and shorts — this type of widening of parameters is a common
design choice) and one that operates on strings.

When used, the type of the argument is used to determine which method to call:

  char firstOfOne = StringUtilities.FirstLetter(1); // returns '1'


  char firstOfOne = StringUtilities.FirstLetter("hello"); // returns 'h'

The first call resolves to FirstLetter(long i) while the second call resolves to FirstLetter(string s).
Notice that both return the same type — that is required in overloaded methods.

You saw overloading at work in our constructor; you can define more than one constructor as long
as the type or number of parameters differs.

For more on overloading, including how it is resolved with named parameters, see Member
Overloading in the .NET Development Guide.

Overriding, on the other hand, is about defining the same method with the same signature in a
superclass and a subclass. We say the subclass’s method overrides the superclass’s method.

You must design a method to deliberately allow itself to be overridden:

1. declare it to be a virtual method, with a method body; then its body is used unless it is later
overridden; or

2. declare it to be an abstract method, without a method body, just a signature, and a ; where the
body would have been; or

3. declare it to be an override method, providing a method body; such a method must be


overriding a method in its parent using these three rules (note this requires some overall
superclass to initially define the method virtual or static).

abstract and virtual methods cannot be static; only one is used, and it typically goes before the
access modifier for the method (public, protected, etc.).

198
The overriding method must declare itself to override in the same manner that the base method
delared itself override-able. It must also have the same access modifier, return type and parameter
types as the overridden method.

Properties can also be overridden, using the same rules on the overriding modifier on the property
(static, virtual, abstract, or override).

To access the superclass’s overridden method or property within the overriding class, use 'base.'
before the method or property name. This resolves to the method in the superclass rather than the
local one, and is done so that your class can extend the definition found in the subclass, adding to it
rather than completely replacing it.

If you want to call the superclass’s constructor from your class’s constructor, you do that by
invoking it as the special method name base() and pass the arguments to match the parameters for
the superclass constructor you want. This call has to be placed after the constructor’s parameters
and before its opening brace, like so:

public class FlyingCar extends Car


{
  public FlyingCar(string model, int maxAltitude) : base(model)
  {
  ... rest of constructor
  }

  ... rest of class


}

For more information about how to use the override keyword, see Versioning with the Override
and New Keywords (C# Programming Guide) and Knowing when to use Override and New
Keywords.

The root class in C# is System.Object. System.Object defines two methods, Equals and ToString that is
expects all classes under it to redefine. When you do so, you will be overriding these methods.
Equals returns a boolean saying whether this instance is equal to the one passed to it; and ToString
returns a string representation of the object. System.Object.Equals bases equals on object identity;
it’s up to you to use that, or to replace it with one based on object state, which is commonly done.
ToString returns a representation as a string of the object’s type and value.

We might define these on CalendarEntry like so:

199
class CalendarEntry {
  ... other contents

  public override bool Equals(Object obj) {


  CalendarEntry calObj = obj as CalendarEntry;
  if (calObj == null)
  return false;
  else
  // base it on the date and string values...
  // not perfect, what about nulls?
  return EntryDate.Equals(calObj.EntryDate)
  && Entry.Equals(calObj.Entry);
  }

  public override string ToString() {


  return EntryDate+": "+Entry;
  }
}

Notice that I want to ensure value equality; I am using the .Equals methods on DateTime and String,
which check value equality. If i read the API, I can determine if they have overridden the ==
operator to use value equality (have they? Check their specification pages on
http://msdn.microsoft.com/

7.6. Interfaces
Inheritance is very powerful, and complex. So C#, like Java before it, restricts programmers to 1
immediate parent; we call this "single inheritance". There are designs so complex that single
inheritance is not sufficient. However, implementing multiple inheritance is very complex.

C# took the same route as Java in this regard, adding interfaces and allowing a class to implement
several different interfaces. An interface can be thought of as a class without any implementation,
for example:

interface IListableCalendarItem {

  ... methods and properties without code bodies

We can use more than one interface when we define a class:

200
class CalendarEntry implements IListableCalendarItem, IIterable {

  ...

The keyword implements on the class definition specifies which interfaces the class implements.

The C# naming convention is to start all interfaces with the letter I and then an
NOTE initial uppercase letter of the first word in its name. I’ve followed that convention in
my example, and we will see it throughout ASP.NET.

If the class does not implement all of the methods and properties in the interface, then it is
considered an abstract class, and it must have subclasses that complete the implementation. You
cannot use a new expression on an abstract class. You can also explicitly make a class abstract by
putting abstract before the keyword class in its definition.

We won’t be defining interfaces ourselves in this text, but there are many useful interfaces in
ASP.NET. We will see these in the chapter on Collections and Databases.

7.7. The ASP.NET and .NET Libraries


There are so many classes in ASP.NET that reviewing them all takes time; most developers get
familiar with the ones they use regularly, and know how to look up the ones they don’t use as often.

It’s a good idea to always look around a little bit, as the ASP.NET libraries are large, and it’s very
possible the code you want, or some portion of it, is available to you in ASP.NET already. Why use
the library? That code has been field-tested in diverse applications and environments, and stood
the test of time. Are you going to test your code as thoroughly?

You can find the core classes in the .NET Framework Class Library.

The framework comes with .NET, which is underneath ASP.NET.

Here are a few classes it’s useful to be familiar with:

System.Math - useful functions for numbers


System.String - many utilities for string manipulation
System.Convert - static functions to convert among the base types
System.DateTime - a date/time representation
System.Random - a random number generating class

System.Text is a useful namespace to explore if you are manipulating strings; it contains the class
System.Text.StringBuilder, which is more efficient and building strings than System.String.

System contains the core classes, but as we expand our look into databases, we will also be looking
at the namespaces System.Collections and System.Data.

201
The Framework Class Library comes in .NET, which is underneath ASP.NET. ASP.NET adds the
System.Web namespace and all of its sub namespaces, which provide web functionality to your
application.

7.8. There’s more …


We can only go so deep with C# classes in a first C# course. There are many more complex features
to the C# class system including:

• partial classes

• abstract classes

• asynchronous methods

• delegates

• destructors

• nested types

• structs and enums

• anonymous types

• generic types

• class attributes

• overloading operators

The Microsoft Developer Network C# Programming Guide provides an overview of these features.

7.9. Further Reading


• http://dotnetslackers.com/articles/aspnet/Razor-Functions-and-Helpers.aspx#s2-overview-of-
functions

• http://weblogs.asp.net/scottgu/asp-net-mvc-3-and-the-helper-syntax-within-razor

• https://msdn.microsoft.com/en-us/library/x9afc042.aspx C# Programming Guide on Classes

• https://en.wikibooks.org/wiki/C_Sharp_Programming

• https://msdn.microsoft.com/en-us/library/ms173114.aspx

• https://msdn.microsoft.com/en-us/library/t990ks23(v=vs.140).aspx APP_CODE

• https://prezi.com/0qr6eqniejad/the-10-most-important-events-in-computer-history/

7.10. Exercises
1. Rewrite your GPS coordinate code from Chapter 3 to be two functions in a @function block. One
returns the radians given the degrees, and the second returns the distance between two points
in feet.

2. Remember the dice calculations in previous exercises? Build a PairOfDice class that simulates
having two dice; it will have a Roll method with a void return type that generates two new

202
random, valid dice values, and methods ValueDie1 and ValueDie2 that return the individual
values on the dice, and Total that returns the sum of the two die. This can be impelemented to
require an object or as static methods and properties (explain your choice in comments on the
PairOfDice class). It should have both of its dice values be stored in private variables (or an
array of 2).

Roll simulates olling a pair of dice. You can simulate rolling one die by choosing one of the
integers 1, 2, 3, 4, 5, or 6 at random. The number you pick represents the number on the die
after it is rolled. The expression rand.Next(6)+1 does the computation to select a random integer
between 1 and 6, where rand is a variable holding a Random object.

Do not store the total, but compute it when it is requested from the two dice values. OO design is
always a tradeoff: if you stored the total, you would recalculate it whenever there was a new
roll, even if it was not requested, while if you don’t, then you have to compute it each time it is
requested. Your design would consider which of these was more likely, and program for that.
Since we only request the total once for each roll, not storing it makes sense — we won’t be
slower, and our object will require less storage in memory.

With that class, rework your page from Chapter 5. Make a page that reports how many times it
has to roll a pair of dice before they come up snake eyes. This is a simulation using your
PairOfDice Class and using its Roll method to roll its dice.

The page should report the number of rolls that it makes before the dice come up snake eyes.
(Note: "Snake eyes" means that both dice show a value of 1.)

3. A common programming task is computing statistics of a set of numbers. (A statistic is a number


that summarizes some property of a set of data.) Common statistics include the mean (also
known as the average) and the standard deviation (which tells how spread out the data are
from the mean). I have provided a class called StatCalc that can be used to compute these
statistics, as well as the sum of the items in the dataset and the number of items in the dataset.

203
Listing 15. StatCalc.cs

using System;

/// <summary>
/// An object of StatCalc can be used to gather statistics about numbers
/// that are entered. The enter(double) method adds the numbers to those
/// already evaluated. You can get the current statistics with the properties,
/// which provide them in getters.
/// </summary>
public class StatCalc {

  private double squareSum;

  /// Add a number to the dataset. The statistics will be computed for all
  /// the numbers that have been added to the dataset using this method.
  public void enter(double num) {
  Count++;
  Sum += num;
  squareSum += num * num;
  }

  /// Return the number of items that have been entered into the dataset.
  public int Count { get; set; }

  /// Return the sum of all the numbers that have been entered.
  public double Sum { get; set; }

  /// Return the average of all the items that have been entered.
  /// The return value is Double.NaN if no numbers have been entered.
  public double Mean {
  get { return Sum / Count; }
  }

  /// Return the standard deviation of all the items that have been entered.
  /// The return value is Double.NaN if no numbers have been entered.
  public double StandardDeviation {
  get {
  if (Count == 0)
  return Double.NaN;
  return Math.Sqrt(squareSum / Count - Mean * Mean);
  }
  }

} // end class StatCalc

Notice the <summary> tag and the use of three /'s — this is C#'s way of providing documentation
in published classes. If you are interested to find out more, see XML Documentation Comments
on MSDN.

204
If calc is a variable of type StatCalc, then the following instance methods and properties are
available:

• calc.Enter(item) where item is a number, adds the item to the dataset.

• calc.Count is a property that returns the number of items that have been added to the
dataset.

• calc.Sum is a property that returns the sum of all the items that have been added to the
dataset.

• calc.Mean is a property that returns the average of all the items.

• calc.StandardDeviation is a property that returns the standard deviation of the items.

Typically, all the data are added one after the other by calling the Enter() method over and
over, as the data become available. After all the data have been entered, any of the other
methods and properties can be called to get statistical information about the data. The
properties Mean and StandardDeviation should only be called if the number of items is
greater than zero.

Starting with StatCalc.cs, add properties Max and Min. The Max property should return the
largest of all the items that have been added to the dataset, and Min should return the
smallest. You will need to keep track of the largest and smallest items that have been seen so
far; consider your initial values for these properties carefully and initialize them in a 0-
argument constructor.

Test your new class by using it in a web site to compute statistics for a set of non-zero
numbers entered by the user. Start by creating an object of type StatCalc:

StatCalc calc; // Object to be used to process the data.


calc = new StatCalc();

Read numbers from the user and add them to the dataset. Request 5 numbers from the user;
decide how to handle blank entries and document it on your page so your user knows what
to expect. After all the user’s numbers have been entered, print out each of the six statistics
that are available from calc. You do not need to print the numbers again.

4. This problem uses the PairOfDice class from exercise 1 and your updated StatCalc.cs class from
exercise 2.

The program you wrote for a previous chapter performs the experiment of counting how many
times a pair of dice is rolled before a given total comes up. It repeats this experiment 10000
times and then reports the average number of rolls. It does this whole process for each possible
total (2, 3, …, 12).

Redo that exercise. But instead of just reporting the average number of rolls, you should also
report the standard deviation and the maximum number of rolls. Use a PairOfDice object to
represent the dice. Use a StatCalc object to compute the statistics. (You’ll need a new StatCalc
object for each possible total, 2, 3, …, 12. You can use a new pair of dice if you want, but it’s not
required.)

205
5. In the board game Scrabble, each tile contains a letter, which is used to spell words in rows and
columns, and a score, which is used to determine the value of words.

1. Write a definition for a class named Tile that represents letter/number tiles like those used
in Scrabble. The properties should include a character named Letter and an integer named
Value.

2. Write a constructor that takes parameters named letter and value and initializes the
instance variables.

3. Write a method named ToString that returns the two property values combined in a string
that is the return value, for examples A(1).

Create a web site that generates random tiles and displays a hand of 6 tiles upon request.
The letters should be between A and Z, and the values should be between 1 and 10. The 6
tiles should be stored in an array of tiles, and then displayed from the array.

Stretch goal: Write the display in a helper, and invoke the helper on your page.

6. Write a page to play Hangman. Let’s keep it simple and limit ourselves to 6 letter words; make
an array of 20 strings and store 20 6-letter words in it. You’re going to have to track which word
the user is guessing, but don’t give it away in the HTML; I recommend passing the index into the
word array in a hidden form field; the hidden field won’t be displayed, but by using the index
you are making sure your word can’t be found in the HTML source.

Decide if you want to just use code blocks on your page or a separate class holding property and
methods. Note that a class and its instances is specific to each load of your page: a function
created on a page is no longer available when the user resubmits a form on that page or clicks
to another page.

7. Review the System.Text.StringBuilder specification and then rewrite PigLatin to use a


StringBuilder in building its return value (it should still return a string).

8. Write a performance test on the two versions of PigLatin: call one PigLatinS and the other
PigLatinSB; run each within a loop 1000 times and see which is faster. If they are the same
speed, run them 10000 times. Once you see a difference, double the number and see if the
difference doubles or not. Write a report summarizing your testing and its results. This type of
analysis of performance and reporting of the results often happens as part of the prototyping
cycle, when you are exploring alternatives and want to determine which is better, and by how
much.

7.11. Project
We are early for the database portion, but consider the data you would want to have be persistent.
Databases store data in tables, with each row representing an object. Design the objects you will
want to store in your database; create a class for each object, if you have more than one (there will
be one type of object per table).

Redo your prototype to use this object — create a static array that holds several instances of this
object to represent data you might look through or present to the user.

206
Chapter 8. Collections and Databases
A key value proposition of web sites is that they provide global access to persistent information. We
typically store the persistent information in databases and files on a file system. Databases store the
data as tables (or sometimes more complex structures, but for now, let’s stick with tables).

A table is a set of rows, where each row has the same entries (the entry is called a column in the
database). In OO design, you typically define an object that holds as its properties the entries within
a row; so a table can be viewed as holding a collection of rows, or objects.

C# uses this model when it interacts with databases — a query against a table returns a collection of
objects; each property in a returned object maps to a column in the table or query.

8.1. Collections
C# has one built-in collection, the array. Arrays are fine, but consider what happens when you need
to remove the second item in an array: if it’s an array of objects, you can put a null there, but if it’s
a primitive, it has to have a value. If you wanted to "fill" the hole but maintain order, you would
have to copy down all of the entries above, and then track that the array has one more entry empty
at the end. Collections are much richer: they do all of that management of entries for you, so you
can add and remove entries as you need to. They can also maintain an order, based on the
collection type: some maintain a sorted order, some maintain the order items were inserted.

An interesting feature that makes all of this possible is the generic class. A generic class lets you
specialize a class when you use it, providing additional types used by that class. This lets you say
what your collection holds; so you can specialize your collection to contain a particular type of
object, rather than any object at all. This is similar to how you give an element type for your array
when you declare it; that type is the only type allowed in the array (if it is a class, then instances of
the class or of any of its subclasses are allowed).

8.1.1. Collection Interfaces

Although the implementations of collections provided in C# are classes, it defines interfaces for
them as well. It is wise to use the interface on your variables, and restrict use of classes to the new
statement. This lets you replace the chosen class with another one if you need to alter its
performance or sort behavior. Collections' performance differ based on the types of operations you
are performing or the type of sorting that is desired, if any.

The main Collection interfaces

ICollection the most general interface; it mainly defines Count, ToArray, and
GetEnumerator

IDictionary a collection of key/value pairs; values can be accessed by keys . The Keys
function on an IDictionary will return an ICollection containing just the keys.

IList a collection that can be accessed by a numeric index (like an array)

There are two more interfaces in System.Collections which we make heavy use of: IEnumerator`and

207
`IEnumerable. A class that implements IEnumerator will provide an IEnumerable. This is important
because IEnumerable lets you not only move through the collection item by item, but also lets you
access the collection’s elements using a foreach loop. We say that the foreach loop enumerates
through the items in the collection.

8.1.2. Collection Classes

The popular collection classes are:

Popular Collection classes

ArrayList IList Items are ordered in the list. This looks alot like an array,
but it lets you add and remove items dynamically (resizing
the array). Sort and search capabilities are provided as
well.

Hashtable IDictionary Keys map to values, and you use keys to access the
elements. The collection is not sorted; with a good hash
function (which is used to assign storage locations), your
data is dispersed in memory and both access and removal
are quick.

SortedList IList & IDictionary this allows both key and index access into a list; its entries
when indexed contain both key and value. It is sorted on
the key values.

Stack IList the stack is a special type of list that only allows items to
be pushed on top of the stack and taken off of the top of
the stack. Knowing this is the main type of access lets the
implementation focus on being fast for those accesses. It is
often described as "Last In, First Out".

Queue IList the queue is a special type of list as well; it only allows
items to be added at one end, and taken off of the other
end. It is described as "First In, First Out".

When you use these, or the interfaces, you can just use them "as-is", as they are fully-fledged
classes. However, when you do that, it means the collection can contain any type of object at all; the
default element type in the collection is object. And, boxing and unboxing means that primitives
will get boxed up and stored in your collection as well.

8.1.3. Generic Collections

If you want to ensure that your collection contains only a particular type of object, you can do so by
using a generic Collection type that permits adding a special type parameter to the class. This uses
<> notation rather than a method’s () notation for its parameters.

List<element-type> a type-safe ArrayList, permits any instance of


element-type or its subtypes

208
Dictionary<key-type,value-type> a type-safe Hashtable, permits any instance of
the key-type or its subclasses for the key, and
any instance of value-type or its subclasses for
the value.

So, an ArrayList can hold anything: ints (boxed), Cars, Pirates, even ArrayLists. But a List<Pirate>
can hold only Pirates and instance of subclasses of Pirates.

When you want to ensure your collection contains only a particular type of objects, use the generic
collections. This ability is referred to as generic classes, since you create a new, specialized class
when you provide the type parameters to it.

C# provides a way for you to create your own generic classes as well; however that is advanced
programming, not covered in this text.

8.1.4. Example using collections

209
@using System.Collections.Generic;

... later in the page ...

@{
  IDictionary<string,int> phoneBook; // a map from strings to integers

  phoneBook = new Dictionary<string,int>();

  phoneBook.Add("Sarah Adams",1234567);
  phoneBook.Add("Jim Jones",5551212);
  phoneBook.Add("Nancy Smith",5010001);
  phoneBook.Add("Bill Blass",1237654);

  if (phoneBook.ContainsKey("Jim Jones")) {
  <p>Jim Jone's phone number is @phoneBook["Jim Jones"]</p>
  }
  else {
  <p>No phone number for Jim Jones.</p>
  }

  /// can also add items like so:


  phoneBook["Sam Sanders"] = 5051122;

  // this will also update an existing item:


  phoneBook["Nancy Smith"] = 5019999;

  ICollection<string> names = phoneBook.Keys;

  <p>Here is your current phone list:</p>


  foreach (string name in names) {
  // the key indexes into the dictionary to retrieve the value:
  <p>@name : @phoneBook[name]</p>
  }

8.2. Database Access


Today there are two popular database choices: Relational or NoSQL databases. For this text, our
focus is a relational database. These databases store data in tables, which have rows and columns.
You can query the database, selecting which rows you want from your tables and then which
columns from the rows. You do this with the language SQL.

210
This text assumes familiarity with SQL, so it will not introduce it to you, but will use
it and provide descriptions of that use. We use Microsoft SQL Server Compact
Edition through Visual Studio and IIS Express; applications developed in this
NOTE manner transfer seamlessly to Microsoft SQL Server when deployed. But to deploy
onto Oracle, MySQL, or some other database, you would need to adjust the
connection mechanism and possibly the SQL syntax, as each database system has its
own dialect of SQL.

Let’s assume we have a contact list in our database with the following data:

Id Name PhoneNumber Email TwitterHandle

1 Sarah Adams 123-4567 sarah@nowhere.c @sarahnowhere


om

2 Jim Jones 555-1212 jjones@gmail.com @jjones3254

3 Nancy Smith 501-0001 null @flywitheagles

4 Bill Blass 123-7654 bblass@bblass.net @blassisback

Note that we have an Id column; this is because good database design requires having a unique
identifier (called a primary key) for each row. Name may not be good enough to be unique, if we
have lots of contacts. Strings are slower in comparisons than integers, so we will usually see
integers used as Id values.

In order to access a database, you first need to create one; in Visual Studio, in addition to IIS
Express providing a local web server, SQL Server Express provides a local database server.

8.2.1. Create a Database

To create a database for your website, you must have it open in Visual Studio. If your website has
an App_Data folder with a .sdf or .mdf file in it, then it already has a database; if you choose to use
that one, jump ahead to "Create a Table".

If you do not have an App_Data directory in your project, right click in the Solution Explorer
window on your web site/project name and click Add; in its menu click Add ASP.NET directory; and
select App_Data from the list provided. You want to use this menu and not create it in the file
system so that your project knows it exists.

Once you have an App_Data directory, right-click on that and click Add; then click Add New Item. In
the dialog, under Installed>Visual C#, you should see "SQL Server database" in the list of choices.
Select that, and then enter a name for your database (keep the .mdf file extension intact).

Once you are done, your database should appear under App_Data.

211
If you are deploying to AppHarbor, or some other cloud ASP.NET PaaS, check to see
if it allows more than one database. You may need to put all of your tables in a
single database, rather than separate ones. This can be an issue if you are already
using ASP.NET Identity, which assumes it can use a database named Identity with
NOTE
the connection name DefaultConnection.

You can add tables to the Identity database for your application’s database
functionality; it’s just not the cleanest design to do so.

8.2.2. Database Configuration in Web.config

Your project Web.config file needs to have a connection string for your database. Check, and if it
does not, add within the <connectionStrings> section of the file the following XML:

  ... if tag not found, add this as a child of <configuration>,


  ... after <system.web>
  <connectionStrings>
  <add name="DatabaseName" connectionString="Data
source=(LocalDB)\MSSQLLocalDB;|DataDirectory|\DatabaseName.mdf;Initial
Catalog=DatabaseName;Integrated Security=true" providerName="System.Data.SqlClient"/>
  ... the rest of the element's children, if any
  </connectionStrings>

Replace DatabaseName in 3 places with the name you gave your database file. If you need to make
this change, you will want to check that the setting in Tools→Options→Database Tools→Data
Connections says (LocalDB)\MSSQLLocalDB. If you need to make either of these changes, exit and
restart Visual Studio to ensure the changes are used when you access the database from within
Visual Studio (before you create the table).

8.2.3. Create a Table

Creating a database is an administrative task that requires actions such as those done above;
however, creating a table can be done by issuing an SQL statement. It’s up to you, to do it manually
or programmatically. If you code it, then you can re-run that code in the future to create the table
again; if you do it manually, you will need to repeat the steps each time you want the table re-
created. It is not uncommon for web developers to keep special pages for their website that will
issue SQL commands to check or recreate the database.

Manual table creation

1. Click on the "Server Explorer" tab to open it (it is under View if you do not have the tab visible
already).

2. If it is not open, click to open the list under "Data Connections". You should see your database
there, click to expand its contents if it is not showing a list within it.

3. Right-click on the Tables item (first in the list, usually) and click "Add New Table".

4. This puts you in the table designer, where you can either create the table using the chart,

212
defining each column and its type, or enter the SQL in the window at the bottom of the page.

Enter the following SQL to create our table:

CREATE TABLE PhoneBook(


  Id INT NOT NULL IDENTITY PRIMARY KEY,
  Name VARCHAR(50),
  PhoneNumber INT,
  Email VARCHAR(100),
  TwitterHandle VARCHAR(20)
  )

Click Update in the table design window. It will then ask if you want a Script before it does the
update. Typically database administration involves keeping a collection of SQL commands in scripts
to re-run them at a future date to update or repair a database. This is one such script. Since we have
the command here, you can skip that and just click Update Database.

The log window will show if the database was successfully updated or not.

Once the table is created, you will need to right-click and click Refresh on your database name in
the Server Explorer window for it to appear.

Code to create the table

The following Razor Page presents us with buttons; when clicked, they return us to the page and
execute the specified SQL command.

Listing 16. DBAdmin.cshtml

@using System.Data.SqlClient;

<!DOCTYPE html>
<html>
<head>
  <title>Database Administration Tasks</title>
</head>
<body>
  @{
  int choice = Request.Form["choice"].AsInt();
  string command = null;

  switch (choice)
  {
  case 1:
  command = "DROP TABLE PhoneBook";
  break;

  case 2:
  command = @"CREATE TABLE PhoneBook(
  Id INT NOT NULL IDENTITY PRIMARY KEY,

213
  Name VARCHAR(50), PhoneNumber INT,
  Email VARCHAR(100), TwitterHandle VARCHAR(20) )";
  break;

  }

  Database db = null;
  if (command != null) {
  try {
  //my connection name in web.config is PhoneBookDB
  db = Database.Open("PhoneBookDB");
  db.Execute(command);
  } catch (SqlException se) {
  <p>
  Oops, that didn't work. I got this exception:
  @se.GetType()
  </p>
  <pre>@se.Message</pre>
  <pre>@se.StackTrace</pre>
  } finally {
  if (db != null) {
  db.Close();
  }
  }

  }
  }

  <form method="post">
  <button type="submit" name="choice" value="1">Drop Table PhoneBook</button>
  <br /><br />
  <button type="submit" name="choice" value="2">Create Table PhoneBook</button>
  </form>

</body>
</html>

This is an interesting Razor example since it uses several features of Razor, C#,and HTML:

• @using — to import the namespace that SQLException lives in

• try..catch — so we can tell the user if something went wrong with the SQL command; note that
returning stack traces is not good in live sites, you would want to protect this by requiring that
the page only be used by administrators (see the next chapter for security information).

• we also used a finally block; it’s important to free up the database connection when you are
done with it, as it is holding onto quite a few system resources. If you don’t explicitly close it,
eventually the garbage collector will clean it up, but it’s not a good idea to rely on that
happening. We use a finally because it ensures the connection is closed no matter what
exception was thrown.

• We use a special string value syntax, opening it with C#'s @",so that our long SQL command

214
string can span lines in the file.

• The form has two submit buttons with the same name and different values; this is how the POST
action can tell which button was clicked — the value of the clicked button is the value of the
buttons' name in the Request.Form dictionary.

• Notice if a form submission is manufactured with a bad choice, no command is run — we don’t
even tell the user it was an invalid choice. This was a design decision, to give back minimal
information to malicious users (since only spoofed POSTs could use bad values).

8.2.4. Put Data in the Table (INSERT)

Once you have a table, you need to be able to put data into it. If your table’s data is static, you can
do this through the Server Explorer view of the table in Visual Studio. If you right-click on the table
in the Server Explorer view, you can see its data with the "Show Table Data" menu item. This shows
you the data, and if you enter additional rows, they are saved to the table.

However, it is likely you will want to update your tables from your website; either as an
administrative action or to let users share data with one another. You could request data directly
from the user with a form, or you could collect the data more indirectly, such as a GPS location
request or to save the results of a game they played in their browser.

When passing user data to an SQL command, do not ever just concatenate a
user string to your SQL command. If you do, you open up your system to an
SQL Injection attack, which can wreak havoc within your database system. For
a hint at how to do this, see the XKCD comic usually referred to as Little Bobby
Tables (CC-BY-NC-2.5):

WARNING

We will always use safe strings, either checking values or passing them through
dynamic parameters to prevent SQL injection attacks.

In order to issue an INSERT command, we have to connect to the database, and then we can issue
commands to it. Database connections use the connection name assigned in the Web.config file, so
we make the connection like this:

var db = Database.Open("PhoneBookDB");

Notice we are just letting C# determine the type of the variable db; in fact it is a Database, which is a
helper class in WebMatrix.Data, supplied to make direct database interactions available.

215
PhoneBookDB is the name I gave this database in the Web.config file. It is usually the database name
without the .mdf file extension.

Once you have a connection, you can issue an INSERT into a table that exists in that database. If the
table does not exist, you will get an SQLException. The INSERT needs to list the columns and then
list its parameters in the same order. Here is an insert into our PhoneBookDB:

  var insertQuery = "INSERT INTO Product (Name, Description, Price) " +


  "VALUES (@0, @1, @2)";
  db.Execute(insertQuery, Name, Description, Price);

The @0, @1, and @2 are not Razor @'s, here they are SQL @'s, marking the parameters to the SQL
statement. This protects against SQL injection because the values supplied are kept separate and
not simply concatenated into the SQL string.

Never, ever, ever, do this instead:

var insertQuery = "INSERT INTO Product (Name, Description, Price) " +


  "VALUES
(\""+@Name+"\",\""+Description+"\","+@Price+")";
CAUTION db.Execute(insertQuery);

Why not? because if Name came directly from a form field, it can contain
malicious content that will take over the command and turn it into whatever
SQL command the malicious user wants to make your database do, such as
dropping all the tables or pulling out private data.

When you create your INSERT statement, you need to list all of the columns that you want to supply
data for. If a column is not listed, then a SQL NULL value is put into that column in the new row.

Here is a page that will insert data into our table; note that if the form has no data, it is going to put
in empty strings or 0’s for numbers — we really need validation on the values prior to this; you will
see how to add validation in Validation and Helpers.

Listing 17. AddPhoneBookEntry.cshtml

@{
  string name = "";
  string email = "";
  string twitter = "";
  int? phone = null;
  string message = "";

  if (IsPost) {
  var db = Database.Open("PhoneBookDB");
  name = Request.Form["name"]; // required
  phone = Request.Form["phone"].AsInt(); // 0 if blank or missing
  email = Request.Form["email"]; // "" if blank or missing

216
  twitter = Request.Form["twitter"];

  // make no data turn into SQL NULL values


  if (phone == 0) {
  phone = null;
  }
  if (email.Length == 0) {
  email = null;
  }
  if (twitter.Length == 0) {
  twitter = null;
  }

  // Define the INSERT statement. The values to assign to the


  // columns in the PhoneBook table are defined as parameters.
  var insertStatement =
  @"INSERT INTO PhoneBook (Name, PhoneNumber, Email, TwitterHandle)
  VALUES (@0, @1, @2, @3)";
  db.Execute(insertStatement, name, phone, email, twitter);

  message = "Phone Book entry "+ db.GetLastInsertId()+" created.";

  db.Close(); // clean-up
  }
}

<!DOCTYPE html>
<html>
<head>
  <title>Add PhoneBook Entry</title>
  <style type="text/css">
  label { float: left; width: 8em;
  text-align: right; margin-right: 0.5em; }
  form { padding: 1em; border: 1px solid; width: 50em; }
  </style>
</head>
<body>
  <h1>Add PhoneBook Entry</h1>
  <form method="post" action="">
  <div>
  <label>Name:</label>
  <input name="Name" type="text" size="50" value="@name" required />
  </div>
  <div>
  <label>Phone Number:</label>
  <input name="phone" type="text" size="50"
  value="@phone" />
  </div>
  <div>
  <label>Email:</label>
  <input name="email" type="text" size="50" value="@email" />

217
  </div>
  <div>
  <label>Twitter Handle:</label>
  <input name="twitter" type="text" size="50" value="@twitter" />
  </div>
  <div>
  <label>&nbsp;</label>
  <input type="submit" value="Insert" class="submit" />
  </div>
  </form>
  <p>@message</p>
</body>
</html>

This is a very basic page; when the insert succeeds, the user is given a brief note, but if there is a
problem, the page is replaced with an error page. There is almost no data validation — all the code
does is make sure SQL NULL values will be inserted when the form fields were left blank. It
assumes the required field (name) will be present. We will see how to address this in a later chapter
with the Validation helper.

Notice that we do not insert into the Id column — because it was defined as an


TIP IDENTITY column, unique values will be automatically generated for us. Most SQL
engines have this capability, though the syntax is often different.

We used the same Execute method that the CREATE TABLE and DROP TABLE statements used in our
admin page, and could have used the same try..catch around it to determine what went wrong.
Execute takes a variable number of parameters, so that you can specify the number to match all of
the SQL parameters you have defined in your statement. If you specify fewer values than you have
parameters, the Execute statement will throw an SQLException.

The database class has a useful method, GetLastInsertId, that you see used in the page. Because we
inserted into a table with an identity column, the database will give us back the value it generated
for that column. We give it to the user (though usually you would not, but you might use it for some
other, internal purpose).

8.2.5. View Data in the Table (SELECT, WebGrid)

Once you have data in your database, you will want to display it to the user. This means getting the
data back out of the database. There are three methods on Database that return data:

• Query — for a SELECT statement that you expect to return any number of rows (including zero).

• QuerySingle — for a SELECT statement that you expect to return exactly one row (just a single
row)

• QueryValue — for a SELECT statement that you expect to return exactly one column in one row
(just a single value).

These methods all have the same parameters as Execute: the SELECT statement as a string, followed
by any needed parameter values for parameters in the statement.

218
The Query method returns a collection as an IEnumerable — it is typical to use a foreach loop on the
query result, to generate an HTML table. Toward this end, there is a WebGrid helper which will
transform your IEnumerable not only to a HTML table, but to one with multiple pages.

But let’s explore that returned type, first. It is an IEnumerable of … objects. C# transforms the row
in the result to an anonymous object. Anonymous objects are objects created on the fly without an
associated class. The row is transformed into an object by making each column value in it a
property of the object. The property names are the SELECT column names — so it’s important to
name expressions in your SELECT list, or understand how SQL Server names columns that are
computed from expressions in SELECTs. If you look at the type of the variable of a row, you see it is
dynamic. That means that the compiler doesn’t know its type, and the runtime will only know it at
the moment it gets created.

Let’s generate our own table first, and then look at WebGrid.

Listing 18. SelectTable.cshtml

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Phone Book</title>
</head>
<body>
  <h1>Phone Book</h1>
@{
  var db = Database.Open("PhoneBookDB");
  var select = "SELECT * FROM PhoneBook";

  var rows = db.Query(select);

  <table border="1">
  <tr><th>Name</th><th>Phone Number</th><th>Email</th><th>Twitter Handle
</th></tr>
  @foreach (var row in rows)
  {
  <tr><td>@row.Name</td><td>@row.PhoneNumber</td>
  <td>@row.Email</td><td>@row.TwitterHandle</td></tr>
  }
  </table>

  db.Close();
}
</body>
</html>

As you can see, we can dot off of our foreach variable row (which has the type dynamic) with the
column names from our table. If you try to dot off of it with a different name, the compiler won’t
detect the error — at runtime, you would get an exception.

The row is actually a WebMatrix.Data.DynamicRecord, and there are three different ways to access a

219
given column:

1. row.ColumnName as used in the code above

2. row["ColumnName"]

3. row[1] if ColumnName is column number 1 (remember, numbering starts at 0), returns that
column

In addition to those access methods, DyanmicRecord provides the property Columns, which returns a
list containing the column names. This can be useful if you do not know the names — you can use
that list to index into the rows with the column names, or to get the count of columns to use the
integer indexing. You can read more about DynamicRecord here: https://msdn.microsoft.com/en-
us/library/webmatrix.data.dynamicrecord(v=vs.111).aspx.

8.2.6. WebGrid Helper

You could use the DynamicRecord ability to report column names and index the row columns to write
your own helper that would generate an HTML table — but you don’t have to, since ASP.NET has
done that. It has developed a very rich helper, WebGrid, which not only generates an HTML table,
but provides paging so that long data results don’t cause long pages.

Here is our example, changed to use WebGrid:

220
Listing 19. SelectWebGrid.cshtml

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Phone Book</title>
  <style>
  .grid { margin: 4px; border-collapse: collapse; width: 600px; }
  .grid th, .grid td { border: 1px solid #C0C0C0; padding: 5px; }
  .head { background-color: #E8E8E8; font-weight: bold; color: #FFF; }
  .alt { background-color: #E8E8E8; color: #000; }
  </style>
</head>
<body>
  <h1>Phone Book at @DateTime.Now</h1>
  <div>
  @{
  var db = Database.Open("PhoneBookDB");
  var select = "SELECT * FROM PhoneBook";

  var rows = db.Query(select);


  var grid = new WebGrid(source: rows, defaultSort: "Name", rowsPerPage: 3);
  }

  @grid.GetHtml(
  tableStyle: "grid",
  headerStyle: "head",
  alternatingRowStyle: "alt",
  columns: grid.Columns(
  grid.Column("Name"),
  grid.Column("PhoneNumber"),
  grid.Column("Email")
  )
  )
  </div>

  @{
  db.Close();
  }
</body>
</html>

As you can see, we create the WebGrid in a Razor code block, and then use its GetHtml method to
generate the HTML for the Grid later on our page. When we use the WebGrid constructor, we supply:

• source: an IEnumerable (in fact, it doesn’t even need to come from a query…)

• defaultSort: the column to sort the results on in the table

• rowsPerPage: how many rows to put in the table at a time

221
The WebGrid will generate an HTML table that lets you click back and forth between "pages" in the
table. That switching is all done in the client, so there are no additional trips to the server.

To generate the HTML, call WebGrid’s GetHtml method. This lets you specify:

• tableStyle: the class to put on the table; in the CSS of our example, you can see how we also
applied it to the td’s and th’s within the table using CSS selectors.

• headerStyle: the class to put on the header row of the table.

• alternatingRowStyle: the class to put on alternating rows; this lets you shade every other row
for more visual impact. If not specified, all rows are styled the same.

• columns: identify which columns of the result to display - you can include some or all, and put
them in the order you want them to show up in the table.

You can rely on information from the database, and get a basic table, by passing just the SELECT
result to WebGrid:

  var grid = new WebGrid(rows);

and then calling GetHtml with no styling options:

  @grid.GetHtml()

This displays all of the data returned in one table, with default table styling.

WebGrid is a very rich helper; as used here, it repeats the call whenever the next/previous page
links are clicked. However, it has the ability to only update the table portion and not the whole page
with a callback. This uses AJAX, Asynchronous Javascript And XML — the link is turned into a
JavaScript call that interacts with the server independently of the rest of the page, updating just the
table to display the next (or previous) page of data.

To read more about this, see https://msdn.microsoft.com/en-


us/library/system.web.helpers.webgrid(v=vs.111).aspx

8.2.7. Change Data in the Table (UPDATE and DELETE)

In addition to having data entered, you may wish to allow users to update or delete their data.

Good design is to have the user identify the row they wish to edit or delete, and then to write your
code to use the primary key to identify the row in the database. The user should typically not see
the keys when they are autogenerated, so you don’t display them, but do track them in your code.

When requesting an update, you can either spend effort determining which values were changed
by the user, or take the simpler route of assuming they’ve updated all of the columns. This works
fine unless you have a very large column — then knowing that it was or was not changed is good,
since you save alot of space and time by not sending unchanged data back to the server.

A typical model for this is to present the user with a table of all of their data, and then let them

222
choose a row to delete or update. This means that each row in the table has two operations; we
could choose to make them links or buttons. Since I’ve given an multi-butotn example already, I will
do this one with links.

Listing 20. PhoneBookChoices.cshtml

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Phone Book</title>
  <style>
  .grid { margin: 4px; border-collapse: collapse; width: 600px; }
  .grid th, .grid td { border: 1px solid #C0C0C0; padding: 5px; }
  .head { background-color: #E8E8E8; font-weight: bold; color: #FFF; }
  .alt { background-color: #E8E8E8; color: #000; }
  </style>
</head>
<body>
  <h1>Phone Book</h1>
  @{
  var db = Database.Open("PhoneBookDB");
  var select = "SELECT * FROM PhoneBook";

  var rows = db.Query(select);


  var grid = new WebGrid(source: rows, defaultSort: "Name", rowsPerPage:5);
  }

  <div>
  @grid.GetHtml(
  tableStyle: "grid",
  headerStyle: "head",
  alternatingRowStyle: "alt",
  columns: grid.Columns(
  grid.Column("Name"),
  grid.Column("PhoneNumber","Phone Number"),
  grid.Column("Email"),
  grid.Column("TwitterHandle", "Twitter Handle"),
  grid.Column("Id","Change",
  format: @<text><a href="~/DeleteEntry.cshtml?id=@item.Id">Delete</a>&nbsp;
  <a href="~/UpdateEntry.cshtml?id=@item.Id">Update</a> </text>)
  )
  )
  </div>
  <div><a href="~/AddPhoneBookEntry.cshtml">Add new entry</a></div>
  @{
  db.Close();
  }
</body>
</html>

223
Notice the "extra" column in the GetHtml on the grid:

grid.Column("Id","Change",
  format: @<text>
  <a href="~/DeleteEntry.cshtml?id=@item.Id">Delete</a>&nbsp;
  <a href="~/UpdateEntry.cshtml?id=@item.Id">Update</a> </text>)

This column uses Id as its underlying value, but has its displayed column header say "Change". We
don’t want to display the Id, but we do want to use it in links. We do this by generating links directly
in the format parameter. Notice that this is embedded HTML, not a string value, for the parameter.

The page link is useful, because it gives us the opportunity to confirm the change with the user; and
since we pass in the id, we can fetch the record to display it to them before the confirm their
change.

You may have noticed the added link below the table as well, to add a new entry. This links to our
AddPhoneBookEntry.cshtml page, which does an insert, but does not link back to our page. ASP.NET
gives us a way to make that happen automatically — once AddPhoneBookEntry.cshtml completes an
insert, it doesn’t have to stay on its page. If we add this code after db.Close(), we will return to the
PhoneBookChoices.cshtml page:

Response.Redirect("~/PhoneBookChoices.cshtml");

Let’s take a look at the delete operation, which also will use a redirect when it completes:

Listing 21. DeleteEntry.cshtml

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Phone Book Delete</title>
  <style>
  .grid { margin: 4px; border-collapse: collapse; width: 600px; }
  .grid th, .grid td { border: 1px solid #C0C0C0; padding: 5px; }
  .head { background-color: #E8E8E8; font-weight: bold; color: #FFF; }
  .alt { background-color: #E8E8E8; color: #000; }
  </style>
</head>
<body>
  <h1>Remove Phone Book Entry</h1>
  @{
  var db = Database.Open("PhoneBookDB");
  var select = "SELECT * FROM PhoneBook WHERE Id=@0";
  var id = Request["id"].AsInt();

  var row = db.Query(select,id);


  //only one row, but use Query so we can use WebGrid...
  var grid = new WebGrid(source: row);

224
  if (IsPost) {
  var delete = "DELETE FROM PhoneBook WHERE Id=@0";
  db.Execute(delete,id);
  db.Close(); // clean up then return to the list
  Response.Redirect("~/PhoneBookChoices.cshtml");
  }

  }

  <div>
  @grid.GetHtml(
  tableStyle: "grid",
  headerStyle: "head",
  alternatingRowStyle: "alt",
  columns: grid.Columns(
  grid.Column("Name"),
  grid.Column("PhoneNumber","Phone Number"),
  grid.Column("Email"),
  grid.Column("TwitterHandle", "Twitter Handle"),
  grid.Column("Id","Confirm",
  format: @<form method="post">
  <button type="submit" name="id" value="item.Id">Confirm
Delete</button>
  </form>)
  )
  )
  </div>
  <div><a href="~/PhoneBookChoices.cshtml">Cancel</a></div>
  @{
  db.Close();
  }
</body>
</html>

You can see the redirect after a successful delete — it returns us to the previous page; the cancel
link at the bottom also does this, without making a delete. We keep the id value in the same place by
making submit button use id as its name and the id value as its value. Alternatively, we could have
made it a hidden field in our form.

This page should be more defensive; it makes these assumptions:

• that the id will find a row

• that a post will find a valid row

• that the delete will remove exactly 1 row, not 0 or more than 1 (since it’s a primary key, the 'not
more than one' is actually a fine assumption).

So we should expand the page to do these checks and inform the user appropriately if the delete
request is no good.

225
The update operation is similar, but since we have to let the user change the data, we can use
QuerySingle rather than Query to get the single row we are expecting. This time, we will code more
defensively as well.

Listing 22. UpdateEntry.cshtml

@{
  string name = "";
  string email = "";
  string twitter = "";
  int? phoneNumber = null;
  string message = "";

  var db = Database.Open("PhoneBookDB");
  var select = "SELECT * FROM PhoneBook WHERE Id=@0";
  var id = Request["id"].AsInt();

  // using QuerySingle because id selections have to return 0 or 1 rows:


  var row = db.QuerySingle(select,id);

  //no row, 'quiet' error and return to the list page


  if (row == null) {
  db.Close();
  Response.Redirect("~/PhoneBookChoices.cshtml");
  }

  if (IsPost) {
  name = Request.Form["name"]; // required
  phoneNumber = Request.Form["phone"].AsInt(); // 0 if blank or missing
  email = Request.Form["email"]; // "" if blank or missing
  twitter = Request.Form["twitter"];

  // make no data turn into SQL NULL values


  if (phoneNumber == 0) {
  phoneNumber = null;
  }
  if (email.Length == 0) {
  email = null;
  }
  if (twitter.Length == 0) {
  twitter = null;
  }

  // Define the UPDATE statement. The values to assign to the


  // columns in the PhoneBook table are defined as parameters.
  var update =
  @"UPDATE PhoneBook SET Name=@0, PhoneNumber=@1, Email=@2, TwitterHandle=@3
  WHERE Id=@4";

  int numRows = db.Execute(update, name, phoneNumber, email, twitter, id);


  if (numRows != 1) {

226
  @: <script>alert("Oops, @numRows rows were altered.")</script>
  }

  db.Close(); // clean-up
  Response.Redirect("~/PhoneBookChoices.cshtml");
  } else {
  // get the values from the row to see what changes the user wants to make
  name = row.Name;
  email = row.Email;
  phoneNumber = row.PhoneNumber;
  twitter = row.TwitterHandle;
  }
}

<!DOCTYPE html>
<html>
<head>
  <title>Change PhoneBook Entry</title>
  <style type="text/css">
  label { float: left; width: 8em;
  text-align: right; margin-right: 0.5em; }
  form { padding: 1em; border: 1px solid; width: 50em; }
  </style>
</head>
<body>
  <h1>Change PhoneBook Entry</h1>

  <form method="post" action="">


  <div>
  <label>Name:</label>
  <input name="Name" type="text" size="50" value="@name" required />
  </div>
  <div>
  <label>Phone Number:</label>
  <input name="phoneNumber" type="text" size="50"
  value="@phoneNumber" />
  </div>
  <div>
  <label>Email:</label>
  <input name="email" type="text" size="50" value="@email" />
  </div>
  <div>
  <label>Twitter Handle:</label>
  <input name="twitter" type="text" size="50" value="@twitter" />
  </div>
  <div>
  <label>&nbsp;</label>
  <input type="submit" value="Update" class="submit" />
  </div>
  </form>
</body>

227
</html>

As you can see, before we display data or make any changes, we validate that we got a row back
from QuerySingle. If there is no row, we return to the list page (a quiet error) rather than let the
user know they phished us, if they were malicious.

We also check the number of rows updated by looking at the value returned by Execute; up until
now, we’ve been ignoring this value; but we can use it to code more defensively. On an Update,
Insert, or Delete, it returns the number of rows affected by the statement. In order for our Update
to fail to find the 1 row, we’d need to have a very busy website with multiple users making changes
at the same time — so it is possible, but highly unlikely. I’ve coded a simple JavaScript alert but it
would be more appropriate to say something like "please reissue request", or just bounce the user
back to the home page to try again.

This collection of 4 pages: the list of entries, add, delete, and update lets us control the contents of
our table. You will see this "CRUD" (create, update, delete) model again in ASP.NET MVC. These are
the 4 basic operations on persistent storage; knowing how to do these 4 lets you then use the
operations within other contexts to suit your application’s needs.

8.2.8. Database class

We’ve used several methods of the Database class. Here is a list of its property and methods to
review:

Static property description

Connection the current connection

Static methods description

Open(string) Opens a connection using the specified


connection name or file name.

OpenConnectionString(string) Opens a connection to a database using the


specified connection string (these are like the
values in our Web.config file).

OpenConnectionString(String, String) Opens a connection to a database using a


connection string and a provider.

Method description

Close() Closes the database.

Dispose() Releases all resources used by the database.

Execute(string) Executes an SQL statement.

Execute(string,object,..) Executes an SQL statement with the specified


values for its parameters.

228
Method description

GetLastInsertId() Returns the generated identity column value of


the most recently inserted row.

Query Executes a SQL query that returns a list of rows


as the result (as an IEnumerable); can specify
parameter values

QuerySingle Executes a SQL query that returns a single row


as the result (as an anonymous object); can
specify parameter values

QueryValue Executes a SQL query that returns a single value


as the result (as an object); can specify
parameter values

When using this class, it’s important to remember to clean up. Otherwise, you may use up more
system resources than you need to. So, once you are done with the database, use the Close method
to release the connection. If you don’t call this explicitly, the resources will be released when the
garbage collector realizes no-one is using the database object any longer; but that relies on
something that may not occur for a while.

As you saw with the Query, it returns a collection of objects; each object is made up of properties
that match the columns in the query. C#'s support for anonymous objects lets this happen
automatically. If you define a class to match your query row result, you can convert the SQL result’s
anonymous class to your class. This lets you treat the rows in your tables like object instances, and
your class can define additional behaviours and checks above the database to control how the
values are set. You do have to pull them back out to properties to do an INSERT, but you could
choose to write behaviors for your objects that handled that for you.

One thing we have not explored is a multi-table database and joins to reconnect their data; with
any sizeable application, your database will end up with several tables related to each other in
particular ways.

ASP.NET provides an automatic object-to-relational mapping called the Entity


Framework and an additional language integrated into C# called LINQ for
NOTE
manipulating databases. Those are beyond the scope of this text, but we will walk
through it in ASP.NET Extreme.

8.3. Application Database Design


Good database design is a topic in itself, and beyond the scope of this text. Good application
database use is a programming design exercise.

You can see a clean example of application-database design in the ASP.NET Identity system and its
use in the ASP.NET Web Site with Identity template.

In particular, there is a UserManager class that controls all changes made to the User table, and a
User class that holds instances created from rows of the table. Microsoft calls this style of use Entity

229
Framework; in the wider general design literature, it is called Object-Relational Mapping (ORM),
as objects in your application are representations of rows in the table, and the manager for them
ensures that changes are made to the underlying table.

UserManager does not expose the SQL it uses, but rather provides the user with specific actions
given a User or values that help identify a user, with methods such as:

• FindUserById(username) — returns the user from the database with the given user name

• FindUserByEmail(email address) — returns a user given an email address

• DeleteUser(user) — given a user object, removes it from the underlying table

• ChangeUserPassword(username, oldpassword, newpassword) — changes the user’s password in


the object and in the database

• CheckEmail(username, email address) — returns true if the email address is the one for the
user, or false otherwise

• CreateUser (username, email, password, …) — creates a new user and puts it into the database

The User class is a simple class with properties for each of the columns in the database.

The UserManager instance also manages connecting to the database. These connections are
expensive and must be released when database access completes. In the web universe, this can lead
to a lot of churning, since HTTP is a session-less protocol. A typical mature web application will
reuse a database connection within the session it thinks it has with a user, but will release it after a
certain length without activity, assuming the user has left the web site.

You can ensure that your database connections are closed by cleaning them up by wrapping the
connection and database access in a try block with a finally clause. The finally of a try always runs,
even if an exception is thrown.

Another way to ensure the connection is closed is to use a C# using statement. This statement
ensures that the instance held in its variable declaration is disposed of, no matter how the using
block completes.

using (var db = Database.Open("PhoneBookDB") )


{
  ... SQL operations
}

The dispose action will close the database and ensure all resources are released; it invokes the Close
operation on the database.

For more information on using, see using Statement (C# Reference, MSDN)

8.4. File Handling


Big files such as images can be stored in databases, but often are not. You can receive a file in an
HTTP request and write it out to the server’s file system; and take a file from the server’s file system

230
and include it in a HTTP response.

We are going to look at images and what is particular to them, as they are a common upload/display
item on a web page. C#'s file operations include the ability to open and read through text files, and
you can find third-party helpers that will display PDF file contents on a page as well.

8.4.1. Uploading files

HTML5 forms provide the ability to locate a file and have it sent to the server in a POST request.
The operations you need to handle are the server-side storage of the file. Most databases (including
SQL Server) have a Binary Large Object (BLOB) data type that could be used to save a file; however,
you may want to simply put the file on the server’s disk rather than loading it into the database.

When you start allowing file uploads, be aware that file size can cause serious
issues in the server (memory use) and on the server’s permanent storage. Use
caution and set limits to prevent too many uploads or uploads of large files.
WARNING
Also be careful what you do with the file contents — user files can cause
injection attacks if you use their content as HTML or SQL content or allow it to
execute in some other fashion on the server.

We will walk through the server side code shown in this example:

Listing 23. ImageUpload.cshtml

@functions {
  // validate that it is an image file
  bool isImageFile(HttpPostedFileBase file)
  {
  string mimeType = file.ContentType.ToLower();
  // image types we want to allow:
  return (mimeType == "image/jpeg" ||
  mimeType == "image/gif" ||
  mimeType == "image/png");
  // should also check file extension and
  // actual file contents to be more secure
  }
}

@{
  var fileName = "";
  bool uploadedFile = false;
  if (IsPost)
  {
  var fileSavePath = "";
  var file = Request.Files[0];
  if (file.ContentLength != 0 && isImageFile(file))
  {
  fileName = Path.GetFileName(file.FileName);
  // under App_Data protects files from access
  // this directory does not protect from access

231
  fileSavePath = Server.MapPath(@"~/uploads/" + fileName);
  file.SaveAs(fileSavePath);
  uploadedFile = true;
  }
  }
}
<!DOCTYPE html>
<html>
<head>
  <title>Image Upload</title>
</head>
<body>
  <h1>Image Upload</h1>
  <p>Choose your file image and click Upload.</p>
  <!-- use a multipart form so the file is delineated in the post -->
  <form action="" method="post" enctype="multipart/form-data">
  <label for="file">Filename:</label>
  <input type="file" name="file" id="file" />
  <input type="submit" name="submit" value="Upload" />
  </form>

  @{
  if (IsPost) {
  if (uploadedFile) {
  <p>@fileName uploaded.</p>
  } else {
  <p>No file uploaded.</p>
  }
  }
  }
</body>
</html>

Notice that at the top, I’ve defined a function isImageFile; I’ve separate this out as it is a complex
check which I may want to expand later to check for image files more thoroughly.

The files in the post are stored in the collection Request.Files; their contents are streamed within
the HTTP request (yes, all of them) — so client-side JavaScript checks for file size would be a very
good thing to add.

Before saving the file, we check that it has content and that it is an image file. Once we have that,
we look for the actual file name. The full path on the client side is provided in the file’s FileName
property, so we use the static method Path.GetFileName to get just the actual file name, stripped of
any path above it. Then we create a server-side absolute file name using Server.MapPath and
providing a target directory, ~/uploads/ and the user’s file name. The uploads directory needs to
already exist in your project - the first time you will need to create it manually. You could choose a
different location - it is not uncommon to store the files in a diretory under App_Data; App_Data is a
protected location, files in it cannot be viewed by users — attempts will get a 404.8, Not Found,
HTTP Response Code.

232
You may, actually, want to make up your own file names on the server — one user
could overwrite another user’s files by uploading a file with the same name. This type
TIP
of file management requires a database to map users' file names to the file names
you’ve used in the server-side file system.

8.4.2. Displaying Image Files

To display an image file stored on the server, you actually don’t do anything special; it appears in
an HTML <img> tag just like any other image.

The tricky part is knowing the file names, if the files were previously uploaded to the server. You
might store them in a database, or you might simply browse your image directory on the server to
display the files found there.

In our example, we will look in our UploadedFiles directory for files ending in .jpg, .png, or .gif to
display on our page.

233
@functions {
  // validate that it is an image file
  bool IsImageFile(string file)
  {
  string fileExtension = Path.GetExtension(file).ToLower();
  // image files we want to allow:
  return (fileExtension == ".jpeg" ||
  fileExtension == ".jpg" ||
  fileExtension == ".gif" ||
  fileExtension == ".png");
  // should check actual file contents to be more secure
  }
}

<!DOCTYPE html>
<html>
<head>
  <title>Display Images</title>
</head>
<body>
  <h1>Display Images</h1>

  @{
  string[] files = Directory.GetFiles(Server.MapPath(@"~/uploads/"));

  foreach (var file in files ) {

  if (IsImageFile(file)) {
  string fileURL=Href(@"~/uploads/"+Path.GetFileName(file));
  <img width="50"src="@Html.AttributeEncode(fileURL)"
  alt="@Html.AttributeEncode(Path.GetFileName(file))"/>
  }
  }
  }

</body>
</html>

First, you see a helper function, IsImageFile, which is similar to our last method. This one checks
file extensions, as the file is not embedded in a POST request with a MIME type any longer.

Then in the main body of the page, we use a system class (in the System.IO namespace) Directory.
This class contains quite a few methods helpful for listing and traversing directory structures. In
particular,

Directory.GetFiles(Server.MapPath(@"~/uploads/"));

First, you see Server.MapPath: that creates a server path, replacing the ~ with the local file system

234
path. So this provides the name of the directory on the server where we expect the files to be.

The outer call, Directory.GetFiles looks in the specified directory for files. It returns an array of file
names as strings. These names include the full path to the file.

Once we have the array of files, we can go through it and generate <img> links to the images. First,
though, instead of a server filesystem path, we need a URL. This is constructed with the builtin
helper Href, similar to the MapPath call earlier. Notice the special call Html.AttributeEncode: that
makes sure the attribute values parse correctly. We do this because the original file name may
contain characters that cannot be used in an attribute value, such as a ", <, or &. (This also prevents
filename-based injection attacks.)

There is a Helper named WebImage — this helper does a lot of useful activities on


images, including resizing, flipping, and watermarking; we could even rewrite our
NOTE pages to just use WebImage and not HttpPostedFileBase at all. However, we wanted
to give you an overview of file handling regardless of file type in this text, so we’ve
used the general form file class.

Making files downloadable is very similar to the image display code; enough that we will leave that
as an exercise. Instead of generating <img> tags that users can right-click and do "Save As" on, you
would generate file names that users could then right-click and do "Save As" on.

8.4.3. Deleting Files

If you are doing any sort of file/image upload and saving them as files on the server, you are going
to have to do some mop-up operations at some point, to remove files. You may, for example, be
storing a profile image for a user, and then when it is updated, you need to delete the old image and
save the new one.

235
Listing 24. ImageDelete.cshtml

@{
  bool deleted = false;
  var filename = "";
  if (IsPost) {
  filename = Request["filename"];
  var fullPath = Server.MapPath("~/uploads/" + filename);

  if (File.Exists(fullPath)) {
  File.Delete(fullPath);
  deleted = true;
  }
  }
}
<!DOCTYPE html>
<html>
<head>
  <title>Image Delete</title>
</head>
<body>
  <h1>Image Delete</h1>
  <form name="deletePhoto" action="" method="post">
  <p>Choose file to delete:</p>

  @{
  string[] files = Directory.GetFiles(Server.MapPath(@"~/uploads/"));

  foreach (var file in files ) {


  string justfile = Path.GetFileName(file);

  <text>
  <input type="radio" name="filename"
  value="@Html.AttributeEncode(justfile)" />
  @(Html.Encode(justfile)) <br />
  </text>
  }
  }
  <p><input type="submit" value="Submit" /></p>
  </form>

  @if(deleted) {
  <p>@filename deleted!</p>
  }
</body>
</html>

For our delete page, we’ve listed all of the files with radiobuttons; one is chosen, and when the
Submit button is pressed, it is deleted. You see many of the same calls we’ve made in our other
pages: Server.MapPath to get the file server path; Directory.GetFiles to list all of the files; and

236
Html.AttributeEncode to protext the attribute value. You will notice that we used Html.Encode on
the value next to the radio button, again to prevent an injection attack through file names.

The other new calls you will notice are File.Exists and File.Delete; these look at the local filesystem
to see if the file exists, and to remove it.

When you write code that changes files on the server disk, consider it very
carefully, and think through the potential ways your code or system could be
attack. Consider the impact of a flood of requests; of large files; of files with
malicious content; of file names. Protect carefully access to files shared among
WARNING
all of your users. Think about the models on the internet: the user who installs
a file typically has the right to remove it, while other users may see it but not
modify it. To implement such a system, we will need to add user accounts,
which we will look at in the next chapter.

8.4.4. WebImage Helper

If you are only uploading and displaying image files, there is a helper tailored to images, WebImage.
This is described in https://msdn.microsoft.com/en-
us/library/system.web.helpers.webimage(v=vs.111).aspx. In addition to basic file information, this
allows you to create images from an array of bytes, and to flip, watermark, or resize an image. It is
used in the MSDN tutorial http://www.asp.net/web-pages/overview/ui-layouts-and-themes/9-
working-with-images.

8.4.5. Deployment and file management

If you are using a PaaS such as AppHarbor, check its file management policy; many limit where
files can be uploaded to, and may not keep files persistently — they may disappear when your app
cycles off of their server, and in complex scenarios may disappear mid-way due to your app getting
relocated within their server farm.

8.5. Further Reading


• https://msdn.microsoft.com/en-us/library/webmatrix.data.database(v=vs.111).aspx

• http://www.asp.net/web-pages/overview/getting-started/introducing-aspnet-web-pages-2/form-
basics

• http://www.asp.net/web-pages/overview/getting-started/introducing-aspnet-web-pages-
2/entering-data

• http://www.asp.net/web-pages/overview/data/5-working-with-data

• http://www.mikesdotnetting.com/article/214/how-to-check-if-a-query-returns-data-in-asp-net-
web-pages

• http://www.mikesdotnetting.com/article/211/adding-a-footer-to-the-razor-webgrid

• http://www.asp.net/web-pages/overview/data/working-with-files

• http://www.asp.net/web-pages/overview/ui-layouts-and-themes/9-working-with-images

237
http://suika.fam.cx/www/manakai-core/lib/Whatpm/ContentType.html

• http://www.hanselman.com/blog/ABackToBasicsCaseStudyImplementingHTTPFileUploadWithA
SPNETMVCIncludingTestsAndMocks.aspx

• https://msdn.microsoft.com/en-us/library/system.io.path(v=vs.110).aspx

• https://msdn.microsoft.com/en-us/library/system.guid.newguid(v=vs.110).aspx

• https://msdn.microsoft.com/en-us/library/gg427611.aspx

8.6. Exercises
1. Build a 4-page phone book application that combines databases and images: start with
PhoneBookDB and its 4 pages, and enable uploading images when adding an entry. The
database row should record the image file name so that you know how to find it, or a null if
there is no image. This will require adding a column to the table.

Once you have that working, update it so that when images are uploaded, don’t use the original
file name; generate a unique name using the system class Guid (GUID is Globally Unique
Identifier) like so:

 string g = Guid.NewGuid().ToString();

You will need to save and append the original file’s file extension on the guid; Path.GetExtension
will provide this information.

Save both the original file name and the GUID-based file name in the database (yes, another
column in the table is needed) so that you can display the user’s file name to them rather than
the internal, server-side GUID-based name.

When you display the full record (on the Update page) show the current image and give the user
the ability to replace it. The replace should delete the old file and save the new one.

Modify the site to have a common layout and appearance using _SiteLayout.cshtml and
_PageStart.cshtml.

2. Rewrite the word-guessing page from the exercises in the chapter C# Methods, Classes, and
Objects. Have the words stored in a database, so that you don’t have to generate an array on
every load of the page, but rather access the database to see the list of words.

Move out common look and feel portions of the page to a _SiteLayout.cshtml file and then add
an administrative panel that also uses that layout. The Administrative panel for your game
should, in one page (not 4 separate pages) let you add, remove, or alter words all on the same
page; this is a design exercise, so consider how you would go about it in a way that fits our word
list and is clear to the user how to add, remove, or modify words.

3. One common activity on websites is to upload files and have them analyzed. Write a web page
that requests a text file upload, then performs a word count of the contents. Save the file locally
as a GUID and delete it once the count is completed. See http://www.asp.net/web-
• pages/overview/data/working-with-files for examples of how to read files and split up their lines

238
and words.

What other analysis might you do? think of one, write a specification for it, and implement it.
This is an exercise in writing a precise-enough specification, and then implement it. Consider if
you need to add more detail to the specification if you were not the implementer, but had to
hand it over to someone else to implement.

This exercise uses two skills from this chapter, collections and File I/O. Get comfortable with the
power of the foreach loop with collections, and with the variety of methods and properties on
File I/O.

4. Suppose that the user gives you a file contains information about sales figures for a company in
various cities. Each line of the file contains a city name, followed by a colon (:) followed by the
data for that city. The data is a number of type double. However, for some cities, no data was
available. In these lines, the data is replaced by a comment explaining why the data is missing.
For example, several lines from the file might look like:

San Francisco: 19887.32


Chicago: no report received
New York: 298734.12

Write a program that will compute and print the total sales from all the cities together. The
program should also report the number of cities for which data was not available. The name of
the file is "sales.dat".

To complete this program, you’ll need to save the file locally, then open the file and read from it.
C# provides a convenient File method ReadAllLines that ties file reading into collections. The
method File.ReadAllLines opens a file and makes all of the lines available as an
IEnumerable<string>. This means you can use a foreach loop to look at each line in turn, and
know that when it completes, you have reached the end of the file.

Suggestion: For each line, split it on the colon into two strings using Split with the ':' character.
See if the second string is a valid number with IsDouble(), and convert it with AsDouble().

The file class has all of the methods you need to read the file; see the .NET Class specification.
Notice that ReadAllLines opens the file, reads all of the lines, and closes it. This does use alot of
memory, since the file’s contents are held in memory.

Remember to use iterative development; you might expand the pseudocode above into
pseudocode containing the processing of the lines. Make small changes to your code so that
when you hit a problem, you have only a few things to look at to determine the cause.

How might you process the file if it was too large to hold in memory? Add a check of the file size
before opening it, and only uses your solution for small files. What do you think the line
between large and small should be?

Challenge: Implement an alternative solution for large files that avoids bringing the file into
memory at one time; this is complex, as it requires reading from the file a byte or chunk at a
time, processing that, and then continuing.

239
5. Develop a web application that provides you with a file server. It should:

• list the directory structure and files on the server under some "root" upload location

• let you create or remove a directory there

• let you upload a file to a particular remote directory

• let you download a file from a particular remote directory

• let you delete a previously uploaded file

To make this task manageable, start with just uploading/downloading/listing remote files in
a single directory, and then add directory management as a second exercise.

This isn’t very secure, since anyone with the web page can access all of these files; in a
future chapter, you will add user management, so each user has their own file server.
Consider how you might make this file server specific to one user, perhaps with a root
directory that is a GUID specific to that user; the user should not need to know the GUID to
use their files.

8.7. Project
This chapter represents a huge step forward: you can now make your data persistent, and provide
users with the ability to alter it, whether that is through the direct 4-page "CRUD" style or more
indirect, as actions taken when they move around your website.

Add a persistent backing store to your project, replacing any hard-coded arrays with database
accesses.

240
Chapter 9. Security and Accessibility
Once you start exposing pages on the internet, security becomes a huge concern. Websites suffer
from vulnerabilities if data from users is not handled carefully. With the ability for multiple users
to access a website, any that offer persistent storage need to be careful about how data sharing
between users occurs.

OWASP (Open Web Application Security Project) has developed guidelines for secure development
and testing of web applications such as ours. This chapter touches on key features of secure web
applications based on their top .NET issues. Issues for other web frameworks and languages may
present in a different manner or need different methods of handling.

The top 10 security issues collected by OWASP are:

• A1 Injection

• A2 Broken Authentication and Session Management

• A3 Cross-Site Scripting (XSS)

• A4 Insecure Direct Object References (can’t happen in HTTP)

• A5 Security Misconfiguration

• A6 Sensitive Data Exposure

• A7 Missing Function Level Access Control

• A8 Cross-Site Request Forgery (CSRF) (same as A3 in Web Pages)

• A9 Using Components with Known Vulnerabilities

• A10 Unvalidated Redirects and Forwards

Material in this section is based on .NET Security Cheat Sheet by Bill Sempf, Troy Hunt, and Jeremy
Long (CC-BY-SA-2.0)

9.1. Injection Attacks


The most common vulnerability for security remains Injection. In particular, SQL commands can
be an attack vector through SQL injection attacks.

In Collections and Databases, we issued SQL commands against a database. This is a particular
issue with web applications that base queries or results on user input, such as search values or
insert values. We showed safe programming in that chapter, using SQL parameters rather than
string concatenation to build up our SQL commands. Any time you use a user’s value, it should
come into your system as an SQL Parameter.

There are limits to where parameters are accepted in SQL; for example, they can be compared to
column values, but you cannot let a user provide you with a table name, as table names cannot be
passed in SQL parameters. If you need users to provide you with table names, have them choose
the names from a list on the client-side, and then make sure the name chosen is one of the values
from the list on the server-side, to prevent introduction of SQL injection. This is often called white-
listing, where you check a value is on a list of allowed values.

241
Never, ever, just concatenate user input into an SQL command string; whitelisting or SQL
parameter use will protect against SQL injection.

If you use enums to limit values, note that enums are still vulnerable to unexpected values. .NET
only validates a successful cast to the underlying data type, integer by default. Enum.IsDefined can
validate whether the input value is valid within the list of defined constants.

Be aware of how your application connects to the database; its connection specifies a role or user.
Apply the principle of least privilege when setting up the Database User in your database of choice.
The database user should only be able to access items that make sense for the use case.

Use of the Entity Framework (EF) is a very effective SQL injection prevention mechanism.
Remember that building your own ad hoc queries in EF is just as susceptible to SQL injection as a
plain SQL query. LINQ can reduce SQL injection even more.

When using SQL Server, prefer integrated authentication over SQL authentication. This removes
the need to define roles and users for the system, using the own user’s authentication for the
connection. This may only be possible in an intranet environment when users of the Windows OS
are those who will be accessing the database. When your database is used by those without
Windows accounts, you have to find an alternative solution. It is not unusual for a single
connection to the database to exist, tied to the application. If you take this approach, be careful to
ensure that the application’s access is limited only to data it needs to access, and that you have as
many checks in place at the database level as possible to protect each user’s data from other users.
Triggers and other SQL features may provide additional layers of protection.

9.2. Authentication and Session Management


Never, ever write your own encryption. User passwords are typical values that need encryption;
user management in general is a huge issue. To this end, Microsoft has begun supplying user login
management code within its Web Pages and MVC templates. Use their code — it undergoes more
rigorous testing than you are likely to do. However, note that as provided it does still have some
weaknesses.

The ASP.NET Membership provider and role provider is a good start, but review the password
storage. The default storage hashes the password with asingle iteration of SHA-1 which is rather
weak. The ASP.NET MVC4 template uses ASP.NET Identity instead of ASP.NET Membership, and
ASP.NET Identity uses PBKDF2 by default which is better. Review the OWASP Password Storage
Cheat Sheet for more information.

The ASP.NET Web Pages with Identity project template provided with this book also uses ASP.NET
Identity and provides a simple user account subsystem written in Web Pages.

Once you have a user-based system, implement proper access controls; compare a user-provided
username with the session’s username, and check that the user is in the appropriate role.

ASP.NET Membership uses SQL Server Compact Edition, which AppHarbor does
not support. The template provided with this book uses ASP.NET Identity, which
CAUTION
uses SQL Server. Microsoft may deprecate Membership, so using Identity is
recommended.

242
9.2.1. ASP.NET Identity

The ASP.NET Identity template is used in the ASP.NET Web Pages with Identity template, available
for download as an online template under New Project in Visual Studio, or from Github as Web-
Pages-Identity-Template. This gives you a template web site with Default, About, and Contact pages
and also a full user login/registration module with Registration, Login, Forgotten Password, and
additional pages, and a backing database for them.

This database relies on SQL Server LocalDB, and will start the database server. In VS
2015, there is often an issue with the LocalDB server not stopping when IIS Express
stops. If you are having access issues, this may be the cause. You will need to stop
and delete the LocalDB server daemon yourself. To do this, open a cmd window on
C:\Program Files\MS SQL Server\130\Tools\Binn and issue these two commands:

NOTE
  sqllocaldb stop mssqllocaldb
  sqllocaldb delete mssqllocaldb

This will shut down any active LocalDB server operating as mssqllocaldb, the
database server name used in the default Identity configuration.

You will see an Account directory which contains these files:

• ForgotPassword.cshtml - page to generate an email to reset a password

• Login.cshtml - login page (redirects to home page)

• Logout.cshtml - code processed on logout (redirects to page that invoked it)

• Manage.cshtml - change password or remove login (redirects to login page)

• PasswordReset.cshtml - get a password reset link sent

• Register.cshtml - create local account (redirects to login page)

One piece of code is in the project to provide login support, you will see it in App_Code:

• Startup.cs - configures OWIN (the Open Web Interface for .NET)

Once you have used Register or Login, there will be an App_Data directory with this file:

• Identity.mdf - the Identity database

This file (Identity.mdf) is not a project file, so you will have to click "Show All Files" in the Solution
Explorer toolbar to make it visible there. Once you can see it, if you double-click it will open in the
Server Explorer and you can explore the tables, their contents and shape, from the Server Explorer
view.

The root directory has these additional files:

• _AppStart.cshtml - first file loaded, ensures login database exists

• _PageStart.cshtml - makes _SiteLayout the default layout

243
• _SiteLayout.cshtml - puts common header on all pages with login/register links

• About.cshtml - template about page found on most websites.

• Contact.cshtml - template contact page found on most websites.

• Default.cshtml - template home page founc on most websites.

• favicon.ico - small image used in browser tab

The Web.config file’s <connectionStrings> element contains an <add> element to allow access to the
Identity database (Identity.mdf). It uses defaultConnection as the connection name.

9.2.2. Confirming Login and Password Reset

It is not uncommon to have registrations and forgotten passwords handled via email, so ASP.NET
provides these services.

The code in this section has not yet been tested. Let me know if you run into
WARNING
any issues with it.

This requires the UserManagerExtensions (which are provided through UserManager in ASP.NET),
and also that you have SMTP configured in your Web.config file. To do that, have a <mailSettings>
section in <system.net> like so:

Listing 25. in Web.config

<configuration>
  <system.net>
  <mailSettings>
  <smtp from="example@domain.com" deliveryMethod="Network">
  <network host="smtp.gmail.com" port="587"
  userName="example@domain.com" password="password"/>
  </smtp>
  </mailSettings>
  </system.net>
</configuration>

replace host, port, userName, and password with your information.

Basic SMTP services in ASP.NET send passwords in the clear. You may want to
explore SendGrid or other more secure options, or use a "burner" email that is
only used for this purpose.
CAUTION
Do not put this file in a public repository or provide it to others, as it now has
your email account information in it.

Confirming Login

The template provided sends users to the Login page upon completing Registration. To require
email registration, that needs to be replaced with code to generation a confirmation email and a

244
link to a page to confirm the registration.

In Register.cshtml, you will need to comment out the redirect call and replace it with code as
follows:

Listing 26. in Register.cshtml

  // Response.Redirect("~/Account/Login");
  string code = UserManager.GenerateEmailConfirmationToken(user.Id);
  var callbackUrl = Url.Action("ConfirmEmail", "Account",
  new { userId = user.Id, code = code },
  protocol: Request.Url.Scheme);
  manager.SendEmail(user.Id, "Confirm your account",
  "Please confirm your account by clicking <a href=\"" + callbackUrl + "
\">here</a> or entering the code " + code +
  " on the confirmation page.");
  Response.Redirect("~/Account/ConfirmEmail");

When email confirmation is used as shown above, this reroutes users to a new page, ConfirmEmail,
shown here:

Listing 27. ConfirmEmail.cshtml

@{
  Page.Title = "Registration Confirmation Page";

  string message = "";


  var confirmationToken = Request["code"];
  var userId = Request["userId"];
  var askedAgain = Request["newCode"];

  // Log out of the current user context, if any


  var authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
  authenticationManager.SignOut();

  // confirming the login, not a request for a new one


  if (!confirmationToken.IsEmpty() && !userId.IsEmpty() && askedAgain.IsEmpty()) {
  // may need a try/catch if this is the first DB hit
  var result = userManager.ConfirmEmail(userId, code);

  if (!result.Succeeded) {
  foreach (var error in result.Errors) {
  // find out what Identity thought went wrong...
  ModelState.AddFormError(error);
  }
  }
  else {
  message = "Registration Confirmed! "+
  "<a href='~/Account/Login'>Click login</a> to log in to the site.";
  }
  }

245
  // no problems and they want their code again...
  if (!askedAgain.IsEmpty()) {
  if (userId.IsEmpty() {
  ModelState.AddFormError("Username required.");
  }
  string code = userManager.GenerateEmailConfirmationToken(userId);
  var callbackUrl = Url.Action("ConfirmEmail", "Account",
  new { userId = userID, code = code }, protocol: Request.Url.Scheme);
  userManager.SendEmail(userID, subject,
  "Please confirm your account by clicking <a href=\"" +
  callbackUrl + "\">here</a>");
  }
}

<h1>@Page.Title.</h1>
<h2>Use the form below to confirm your account.</h2>

@if (!message.IsEmpty()) {
  <p>@Html.Raw(message)</p>
} else {
  <p>
  Check your email and use the link or enter your user name and
  code here to confirm your account. You must be confirmed
  before you can log in.
  </p>

  <form method="post">
  <fieldset>
  <legend>Confirm Account</legend>
  <p>
  <label for="userId">User name</label>
  <input type="text" id="userId" name="userId" />
  </p>
  <p>
  <label for="code">Confirmation code</label>
  <input type="text" id="code" name="code" />
  </p>
  <p><input type="submit" name="confirm" value="Confirm" /></p>
  <p><input type="submit" name="newCode" value="Regenerate Code" /></p>
  </fieldset>
  </form>
}

The Login page should be altered to check that email confirmation has occurred:

246
Listing 28. in Login.cshtml

  var user = userManager.Find(userName, password);

  if (user != null)
  {
  // Require the user to have a confirmed email before they can log on.
  if (!userManager.IsEmailConfirmed(user.Id)) ①
  {
  // note this tells someone there is an unconfirmed account;
  // may want to echo the "No such user or password" message instead.
  ModelState.AddFormError("You must have a confirmed email to log on.");
  } else {
  var authenticationManager = HttpContext.Current.GetOwinContext()
.Authentication;
  var userIdentity = userManager.CreateIdentity(user,
DefaultAuthenticationTypes.ApplicationCookie);

  authenticationManager.SignIn(new AuthenticationProperties() { IsPersistent


= false }, userIdentity);
  Context.RedirectLocal(returnUrl);
  }
  } else {
  ModelState.AddFormError("The user name or password provided is incorrect.");
  }

① marks the new if block to validate confirmation prior to the login. Note that the error provided
here leaks information about the account existing; you may want to instead always reroute to
the ConfirmEmail page on this failure and the login failure (so users do not know the actual
reason for the failure - bad login, bad password, or unconfirmed login).

Note that any login attempt should include a similar check, so Manage.cshtml should also validate
confirmation before allowing the password to be altered. It might decide to let the account be
deleted, but that would be up to the website designer to decide, and should be considered carefully
as a potential security weakness.

Resetting your password

This user self-management task is linked to on the Manage page, ForgotPassword.cshtml. SMTP
configuration is also needed for password resets.

You will need to uncomment the code and set smtpSetup to true in ForgotPassword.cshtml like so:

247
Listing 29. in ForgotPassword.cshtml

  if (user!=null) {
  smtpSetup = true;
  // For more information on how to enable password reset please visit
http://go.microsoft.com/fwlink/?LinkID=320771
  // Send an email with this link
  string code = userManager.GeneratePasswordResetToken(userId);
  var hostUrl = Request.Url.GetComponents(UriComponents.SchemeAndServer,
  UriFormat.Unescaped);
  var resetUrl = hostUrl +
  VirtualPathUtility.ToAbsolute(
  "~/Account/PasswordReset?resetToken=" +
  HttpUtility.UrlEncode(code) +
  "&email="+ HttpUtility.UrlEncode(email));
  userManager.SendEmail(userId, "Reset Password",
  "Please reset your password by clicking <a href=\"" +
  resetUrl + "\">here</a>");
  }

9.2.3. Other Identity Features

ASP.NET Identity also provides two-factor authentication; the asp.net site discusses this in the MVC
environment here: Two-factor authentication using SMS and email with ASP.NET Identity.

You can also enable reCaptcha authentication using Google’s recaptcha.net. Stubs for this are
present in the ASP.NET Web Pages with Identity template. This does not require any special ASP.NET
Identity features to perform.

9.2.4. Account Management Page Flow

Your site is now configured with user logins. You will notice when someone is logged in, the upper
right corner changes. Let’s step through the code that does this (in _SiteLayout.cshtml):

248
  <section id="login">
  @if (User.Identity.IsAuthenticated) { ①
  <text>
  Hello, <a class="email" href="~/Account/Manage"
  title="Manage">@User.Identity.GetUserName()</a>! ②
  <form id="logoutForm" action="~/Account/Logout" method="post">
  @AntiForgery.GetHtml() ③
  <a href="
javascript:document.getElementById('logoutForm').submit()">
  Log out ④
  </a>
  </form>
  </text>
  } else { ⑤
  <ul>
  <li><a href="~/Account/Register">Register</a></li>
  <li><a href="~/Account/Login">Log in</a></li>
  </ul>
  }
  </section>

① User.Identity.IsAuthenticated is true if there is currently a logged-in user in the session.

② User.Identity.GetUserName() is the name of the currently logged-in user. As you can see here, if
the user clicks their name, it will go to the page ~/Account/Manage.cshtml, which is for account
management. Note we don’t need the .cshtml on our link, it is assumed.

③ We see here a use of the anti-forgery token; it is the first line within the form

④ The form is "just" a Log out link — but notice that it is hooked to javascript so it actually submits
the form, which will post to ~/Account/Logout.cshtml.

⑤ When no-one is logged in, the Register and Log in links are presented, routing to their respective
pages.

Notice that much of the account management system is only found through using the login
management system; only Register and Login are visible to non-users, Manage and Logout are
presented to users, ForgotPassword is only visible from the Manage page, and ConfirmEmail is only
accessed through the email link generated by a Registration request.

[ account mgmt flow ] | images/account-mgmt-flow.png


Figure 22. Account Management Page Flow

9.2.5. Using Authentication

249
ASP.NET Identity sends credentials to the server in clear text (unencrypted). A
production site should use HTTPS (secure HTTP, using SSL) to encrypt sensitive
information between the client and the server. For more information about SSL,
CAUTION see What is SSL and How to Implement in ASP.NET Web Application and
Securing Communications with Secure Socket Layer (SSL) If you are not running
with SSL, be very clear to the user that their password is unsafe. I recommend
putting this on all pages, using _SiteLayout.cshtml.

Once you have account management and authentication, you can block off access to that portion of
your website that requires a user account; or make pages behave differently for guests than for
logged-in users.

If you want a portion of your website to not present itself until a user is logged in, you can
accomplish that with these steps:

1. Make a subdirectory, let’s call it authorized.

2. In authorized, make a _PageStart.cshtml file that contains the following code:

Listing 30. ~/authorized/_PageStart.cshtml

@using Microsoft.AspNet.Identity

@{
  if (!User.Identity.IsAuthenticated) {
  Response.Redirect("~/Account/Login?returnUrl="
  + Request.Url.LocalPath);
  }
  Layout = "~/_SiteLayout.cshtml";
}

We redirect to the login page if the user is not logged in — thus preventing the current page
from rendering. Notice also that the login will return to this page once it completes. The
returnUrl parameter is used in Login.cshtml to redirect upon a successful login.

Using _PageStart.cshtml ensures that all pages in the current directory require logging in prior
to their use. It overrides the _PageStart.cshtml file in the parent directory, so be sure to repeat
any thing needed from that starting page to this one (not exactly DRY, I know…).

9.2.6. Roles

Roles are useful when groups of users have access to specific areas of your web site that other users
do not. For example, administration is usually assigned to a role rather than a single user; or you
may have a group functionality that lets groups share files, but limit cross-group file sharing.

Roles may be fixed, or roles may be something that administrators (or, role administrators) can
create and drop.

Roles can be created through ASP.NET once a connection to the identity database is made with

250
WebSecurity.InitializeDatabaseConnection() using the Roles property of a page to access the
SimpleRoleProvider instance for the Membership database.

For example, your administrative page might have code to create an admin role if one does not
exist, and then if there are no users in the role, to put the user "admin" into that role if such a user
exists.

@using Microsoft.AspNet.Identity
@using Microsoft.AspNet.Identity.EntityFramework
@using Microsoft.Owin.Security

@{
  var userStore = new UserStore<IdentityUser>();
  var roleManager = new RoleManager(new RoleStore(userStore.Context));
  var userManager = new UserManager<IdentityUser>(userStore);

  const AdminRoleName = "admin";


  const AdminUserName = "admin";

  if (!roleManager.RoleExists(AdminRoleName)) {
  var adminRole = new IdentityRole { Name = AdminRoleName };
  roleManager.Create(adminRole);
  }

  var adminRole = roleManager.FindByName(AdminRoleName);

  if (adminRole.Users.Count == 0) {
  var adminUser = userManager.FindUserByName(AdminUserName);

  if (adminUser != null) {
  adminUser.AddToRole(adminRoleName);
  }
  }
}

This particular design decision, to make sure there is an admin user in an admin role,
is not very secure, since it is plain in our code what the login and role names are. One
improvement is to put this code, or constants for the strings, in _AppStart.cshtml.
TIP
Another would be to further isolate these values to environment variables that can
then be configured on the server completely outside of the source code and accessed
through the Request object.

Your administrative page may provide you with a list of users that allows you to add or remove
administrative privilege from them, disable or remove their accounts, or create new accounts (for
example, some sites do not have independent registration).

If there is a portion of your website that is only for administrators, you could use a similar
organization to what we did with authorization to limit access to all pages in a diretory:

251
1. Make a subdirectory, let’s call it admin.

2. In admin, make a _PageStart.cshtml file that contains the following code:

Listing 31. ~/admin/_PageStart.cshtml

@using Microsoft.AspNet.Identity

@{
  if (!User.Identity.IsAuthenticated) {
  Response.Redirect("~/Account/Login?returnUrl="
  + Request.Url.LocalPath); ①
  }
  // set AdminRole in _AppStart.cshtml
  if(!User.IsInRole(AdminRole)) { ②
  Response.Redirect("~/NotAuthorized");
  }
  Layout = "~/_SiteLayout.cshtml";
}

① As before, we redirect to the login page if the user is not logged in — thus preventing the
current page from rendering. Notice also that the login will return to this page once it
completes. The returnUrl parameter is used in Login.cshtml to redirect upon a successful
login.

② If the user is logged in, we will check to see if they are in the admin role; that value is set
elsewhere, as a constant value. If the current user is not an admin, they are sent to a page
letting them know they are not authorized. For security’s sake, you may actually want this to
route to a Not Found page.

Using _PageStart.cshtml ensures that all pages in the current directory require logging in prior
to their use.

With ASP.NET Identity, setting up roles is done through the RoleManager class; however, once you
have a user logged in, the User property of the Page instance for the current page gives you access
to its Identity instance and the IsInRole() test.

The Identity instance provides access to the Name and IsAuthenticated properties; you typically
would use Name only after checking IsAuthenticated, and then could use Name, and the
UserManager, to locate the User object and manipulate its state, as shown in our code in this
chapter.

The UserManager provides these capabilities:

Name Description

AccessFailed(TKey) Tracks access failures, and logs the user out if goes over the configured
maximum allowed.

AddLogin(TKey, UserL Associates an external login with a user.


oginInfo)

252
Name Description

AddPassword(TKey, Str Adds a user password (can’t have one already).


ing)

AddToRole(TKey, Strin Adds a user to a role.


g)

AddToRoles(TKey, Stri Adds a user to multiple roles


ng[])

ChangePassword(TKey, Changes a user password.


 String, String)

ChangePhoneNumber( Sets a user phone number with the verification token.


TKey, String, String)

CheckPassword(TUser,  Determines whether the password is valid for the user.


String)

ConfirmEmail(TKey, St Confirms the user e-mail with confirmation token.


ring)

Create(TUser) Creates a user with no password.

Create(TUser, String) Creates a user with the given password.

Delete(TUser) Deletes a user.

Find(String, String) Returns a user with the specified username and password or null if there
is no match.

Find(UserLoginInfo) Returns the user associated with this login.

FindByEmail(String) Finds a user by his e-mail.

FindById(TKey) Finds a user by ID.

FindByName(String) Finds a user by user name.

GenerateChangePhone Generates a code that the user can use to change their phone number to a
NumberToken(TKey, St specific number.
ring)

GenerateEmailConfirm Gets the e-mail confirmation token for the user.


ationToken(TKey)

GeneratePasswordRese Generates a password reset token for the user using the
tToken(TKey) UserTokenProvider.

GenerateTwoFactorTok Gets a token for a specific two factor provider.


en(TKey, String)

GetAccessFailedCount( Returns the number of failed access attempts for the user.
TKey)

GetEmail(TKey) Gets a user e-mail.

GetLockoutEnabled(TK Determines whether the lockout is enabled for the user.


ey)

253
Name Description

GetLockoutEndDate(TK Returns when the user is no longer locked out, dates in the past are
ey) considered as not being locked out.

GetLogins(TKey) Gets the external logins for a user.

GetPhoneNumber(TKey Gets a user phone number.


)

GetRoles(TKey) Returns the roles for the user.

GetTwoFactorEnabled( Determines whether two factor authentication is enabled for a user.


TKey)

GetValidTwoFactorPro Returns a list of valid two factor providers for a user.


viders(TKey)

HasPassword(TKey) Determines whether the user has a password.

IsEmailConfirmed(TKe Determines whether the user e-mail has been confirmed.


y)

IsInRole(TKey, String) Determines whether the user is in the specified role.

IsLockedOut(TKey) Determines whether the user is locked out.

IsPhoneNumberConfir Determines whether the user phone number has been confirmed.
med(TKey)

NotifyTwoFactorToken( Notifies a user with a token using a specific method of two-factor


TKey, String, String) authentication provider.

RegisterTwoFactorProv Registers a two factor authentication provider with the


ider(String, IUserToken TwoFactorProviders mapping.
Provider<TUser, TKey>
)

RemoveFromRole(TKey Removes a user from a role.


, String)

RemoveFromRoles(TKe Remove user from multiple roles


y, String[])

RemoveLogin(TKey, Us Removes a user login.


erLoginInfo)

RemovePassword(TKey Removes a user password.


)

ResetAccessFailedCoun Resets the access failed count for the user to 0.


t(TKey)

ResetPassword(TKey, S Resets a user password using a reset password token.


tring, String)

SendEmail(TKey, Strin Sends an e-mail to the user.


g, String)

SendSms(TKey, String) Sends the user a SMS message.

254
Name Description

SetEmail(TKey, String) Sets a user e-mail.

SetLockoutEnabled(TKe Sets whether lockout is enabled for this user.


y, Boolean)

SetLockoutEndDate(TK Sets the time when a user lockout ends.


ey, DateTimeOffset)

SetPhoneNumber(TKey, Sets a user phone number.


 String)

SetTwoFactorEnabled(T Sets the two factor authentication enabled property for the user.
Key, Boolean)

UpdateSecurityStamp(T Generates a new security stamp for a user, used for SignOutEverywhere
Key) functionality.

VerifyChangePhoneNu Verifies whether the code is valid for a specific user and for a specific
mberToken(TKey, Strin phone number.
g, String)

VerifyTwoFactorToken( Verifies a two factor token with the specified provider.


TKey, String, String)

As you can see, the reset/confirm password calls are all here, as are calls for setting up and using
external logins and two-factor authorization.

Although the UserManager lets us manipulate roles for a given user, sometimes you need to
manipulate the roles themselves directly.

The RoleManager provides these capabilities: FIXFIXFIX

method description

Create(TRole) Creates a role.

Delete(TRole) Deletes a role.

FindById(TKey) Finds a role by ID (a Role instance)

FindByName(String) Finds a role by name.

RoleExists(String) Determines whether the role exists.

Microsoft provides additional functionality in ASP.NET Identity including external authentication


services such as Google and Facebook, and you can integrate reCaptcha validation of human
interaction. For information on using those services, see http://www.asp.net/web-
api/overview/security/external-authentication-services. Note that the writeup is based on a MVC
project, some adjustments will be needed to use this with Web Pages.

9.3. Cross-site scripting


Next to SQL Injection, HTML injection also needs to be considered. If you allow user data to be

255
displayed as HTML, that data can create a client-side injection attack. This is usually called cross-
site scripting because its goal is to spoof the form from another site or send it to another site upon
rendering. This data need not come from a form; it can be data previously stored in a database or a
file. Consider that the database could be attacked from another source than your website and thus
the virus may not appear until you select the data. So view any source of data as suspicious, and
protect it upon display.

ASP.NET provides you with the ability to protect against user data by HTML encoding such data
before displaying it. This turns any character that could signal an injection into its named entity; <
is turned into <, & is turned into &, and so on. This is an automatic conversion when you display the
content of a variable or expression using @something in your page.

If, for some reason, you need the value not to be encoded, then be certain the value contains only
the HTML tags you expect or whatever your allowed values are before displaying it. You can stop
the automatic encoding by wrapping the expression or variable in Html.Raw() like so:

  string message = "<b>This is a test</b>";

  <p>Encoded: @message</p>
  <p>Raw: @Html.Raw(message)</p>

You might wonder why ASP.NET encodes even for data in a database. It does because
even if we clean the data going into the database, a malicious user could corrupt the
database contents. So, ASP.NET always encodes on the way to the user, rather than on
TIP the input data. Yes, you can, and should, check the incoming data to rule out injection
attacks as much as you reasonably can, but know that attacks can occur at any level in
your web stack, at any time, so ASP.NET always acts defensively unless explicitly told
not to by an Html.Raw() call.

In addition to automatic encoding of output, ASP.NET Web Pages validates incoming form data, and
rejects any that contain any HTML tags at all. There are times when this may not be the action you
want; for example, if your page allows user text that contains simple HTML tags such as <p>, <em>,
or <code>.

One way around this is to use a markup language such as markdown for comments,
TIP rather than allow HTML in forms; or to integrate a package that provides WYSIWYG
editing with HTML safety in forms such as Rich Text Editor.

To access data that would fail incoming validation requests, you have to access it through the
Request.Unvalidated method rather than through Request, Request.Form, or Request.QueryString. This
causes the user’s data to be passed to you directly without validation.

For example, instead of accessing it this way:

  string line = Request.Form["line"];

You would access it this way:

256
  string line = Request.Unvalidated().Form["line"];

If you were to try to access the data through the Form field directly, you would get an error.

It is very important that you perform whitelisting validation on this input yourself if you bypass
validation. Request Validation in ASP.NET proposes a very smooth approach:

Encode the whole input, and then only decode the tags that you want to allow.

// Encode the string input


StringBuilder sb = new StringBuilder(Html.Encode(line));
// Selectively allow <b> and <i>
sb.Replace("&lt;b&gt;", "<b>");
sb.Replace("&lt;/b&gt;", "</b>");
sb.Replace("&lt;i&gt;", "<i>");
sb.Replace("&lt;/i&gt;", "</i>");

This type of bypassing should be done with extreme caution: if you forget to check or make a
mistake in your code, then you have a security flaw that can be exploited.

You can also add checks to your forms and the processing of their contents to detect if a form
request was forged.

To do this, add to the form like so:

<form ...>
@AntiForgery.GetHtml() <!-- first line within the form -->
... continue with form
</form>

And then when you process the posted data, add a check first for forgery:

if (IsPost) {
  AntiForgery.Validate();
  ... continue with form processing
}

This adds an anti-forgery token to a form and then has the server-side validate that token after a
post. The form submission has to come from the expected client for the anti-forgery check to pass.

9.4. Security Configuration


Whenever there is a way to specify security, it must be carefully configured. This includes not only
your web application’s security configuration but also the web server’s security configuration, the
database’s security configuration, and any underlying server operating system security

257
configuration.

For your web application, you should lock down the web.config file:

• Remove all aspects of configuration that are not in use.

• Do not provide debug information in a deployed application.

• Encrypt sensitive parts of the web.config

9.5. Sensitive Data


If you put account numbers, passwords, or other sensitive data in URLs or forms, then malicious
users have access to data that they could use to compromise your web application. Never expose
sensitiive data in URLs — always use a level of indirection that keeps all sensitive data on the server
under its security.

Always use HTTPS. You may have noticed that our web sites are just using HTTP. HTTPS requires an
SSL certificate; a real SSL certificate costs money, but for testing purposes you can write your own
certificate and put it in place. There is a writeup on that here: http://www.c-
sharpcorner.com/UploadFile/225740/what-is-ssl-and-how-to-implement-in-Asp-Net-web-aaplication/

Note that since you are not using SSL on your deployed application, you should make it very clear
in your web pages that users should not use a password they use elsewhere; your site does not
provide the security that commercial sites have.

To make it less obvious to clients what software you are using:

• Remove the version header in your web.config.

  <httpRuntime enableVersionHeader="false" />

• Also remove the Server header (doing this in _PageStart.cshtml removes it in each response).

  HttpContext.Current.Response.Headers.Remove("Server");

9.6. Check at every level


Previously in this text we’ve stressed checking data both in the client and in the server. Often
developers think if the data has been checked once, that is sufficient. But because malicious users
can spoof requests and potentially even get into the database directly, we need to check at every
level.

When users are introduced, they also need to be revalidated at each level; it’s not enough to check
the user name on the client side and then let server or database access proceed; the server and
database should also check the user name against allowed permissions. That way, malicious users
going in below the client, entering the server or database directly, will be prevented from access.

258
9.7. Updating the .NET Framework
A key vulnerability (A9 Using Components with Known Vulnerabilities) is not keeping libraries up
to date, allowing known security issues to be used; this was a key issue with HeartBleed issues and
has led to the demise of Java in the browser. ASP.NET is no different, as a library it, too, needs to be
kept up to date so that security holes are quickly closed.

The .NET Framework is kept up-to-date by Microsoft with the Windows Update service. Developers
do not normally need to run seperate updates to the Framework. Windows update can be accessed
at Windows Update or from the Windows Update program on a Windows computer.

Individual frameworks can be kept up to date using NuGet. Watch the updates on your
development setup, and plan updates to your applications accordingly.

Any third party library your application might use will also need to be updated. If it does not use
Nuget, then you will need to update it explicitly through its update mechanism.

If you have a version of .NET running in a web server, it is the administrator’s role to ensure
updates are applied in a timely manner. If you are using a cloud service such as AppHarbor or
AWS, check on their update policy to be aware of what your exposure might be to exploitation of a
known bad version.

Always check the MD5 hashes of the .NET Framework assemblies to prevent the possibility of
rootkits in the framework. Altered assemblies are possible and simple to produce. Checking the
MD5 hashes will prevent using altered assemblies on a server or client machine. See
https://www.owasp.org/index.php/File%3APresentation_-.NET_Framework_Rootkits
-_Backdoors_Inside_Your_Framework.ppt (.NET Framework Rootkits (ppt))

9.8. Redirects and Forwards


The tenth issue in the OWASP Top 10 is unvalidated redirects and forwards. These occur in C# when
your page does a Response.Redirect call to change the page you land on when a form is processed.
You may also do redirects in JavaScript, consult OWASP’s information sheet on redirects and
forwards.

ASP.NET provides you with the ability to redirect to another URL. A form of attack is to take over
the redirect or forward with a phishing URL rather than the intended one. So, whenever you code a
redirect or forward in your web page that may have come from a user’s choice or input, you should
use a white-list test to ensure the URL is value.

One check you can make in ASP.NET MVC is to validate that the URL is local, that is, remains on the
same domain. For more information on MVC’s approach to this see Preventing Open Redirection
Attacks (C#).

9.9. Accessibility
On the one hand, security aims at coding your pages to keep out users who are being malicious.
Web accessibility is about coding your pages to allow users who want to view your page but have

259
limitations in vision, mobility, hearing, or otherwise have difficulty accessing a web site.

WebAIM.org compiled a set of guidelines for web pages. These are primarily at the HTML level, and
are relatively straight-forward to implement, but can be extensive if not considered up front for a
large site. Here are their guidelines:

1. Perceivable

• Provide text alternatives for any non-text content such as images, buttons, and videos

• Provide alternatives for time-based media, such as transcripts for videos

• Content can be presented in different ways without losing information or structure

• Make it easier for users to see and hear content including separating foreground from
background, consider the impact of color-blindness

2. Operable

• Make all functionality available from a keyboard

• Provide users enough time to read and use content

• Do not design content in a way that is known to cause seizures

• Provide ways to help users navigate, find content, and determine where they are

3. Understandable

• Make text content readable and understandable

• Make Web pages appear and operate in predictable ways

• Help users avoid and correct mistakes

4. Robust

• Maximize compatibility with current and future user agents, including assistive
technologies

Many of these can be achieved by actions such as: * use alt attributes to describe images * use
HTML tags semantically; that means the tag is used correctly, i.e.: use table column and row
headers to mark column and row headers, not to style the table use headers (<h1>, … <h6>)
appropriately, not to get certain styles use headers, don’t just use styles to present text as if it
was a headers forms use appropriately tagged labels for fields * videos/audio tracks have
transcripts and subtitles * use a logical layout that reacts well to screen readers and re-sizing and
doesn’t rely on colors, shapes, or sizes of items * do not require a mouse; for example, provide
keyboard alternatives

In addition to WebAIM’s general guidelines, some organizations have to satisfy regulations such as
Section 508 of the Rehabilitation Act, §1194.22. These check even more deeply into page layout,
content, and use.

With ASP.NET’s Web Pages, accessibility is driven by the HTML and the content; if you use the
HTML Helpers to generate HTML, provide argument values for alt tags and others appropriate to
provide accessibility.

260
9.10. Further Reading
• .NET Security Cheat Sheet

• OWASP Top 10 Proactive Controls 2016

• THE most basic way to implement ASP.NET Razor security (uses the older Membership method)

• Adding Security and Membership to an ASP.NET Web Pages (Razor) Site (the old way, with
Membership)

• Using ASP.NET Identity with Razor Web Pages

• Account Confirmation and Password Recovery with ASP.NET Identity (C#)

• Create a secure ASP.NET MVC 5 web app with log in, email confirmation and password reset
(C#)

• SmtpClient.UseDefaultCredentials Property

• <mailSettings> Element (Network Settings)

• ASP.NET MVC 5 Security And Creating User Role

• UserManager<TUser, TKey> Class

• RoleManager<TRole, TKey> Class

• HttpUtility Class

• Request Validation in ASP.NET

• Securing Web Communications: Certificates, SSL, and https:// (via the internet archive)

• What is SSL and How to Implement in ASP.Net Web Application

• Configuring an ASPNET project for development with SSL

• WebAIM’s WCAG 2.0 Checklist for HTML documents

• WebAIM’s Section 508 Checklist for HTML documents

9.11. Exercises
1. Time for another round of "Stump the Newbie". Design a page with a security hole, and have a
peer try to find the hole. You might do this by providing them source, or by providing them with
a deployed application to "hack".

2. Take the template Web Site’s user management functionality and add an admin role to it along
with management for that role.

The management of the admin role should include:

• the ability to make a user an admin

• the ability to take away admin privilege from a user

• the requirement that there be at least one user in the admin role

• the ability to delete a user

• the ability to lock a user’s account (so they can log in, but get sent to an 'Account Locked'

261
page).

• the ability to unlock a user’s account

• the ability to take on admin privilege outside of being given it in some manner (you design
and document the manner), such as one of these:

• the very first account created gets admin

• a hard-coded user name gets admin given when the account is created

• the database is seeded with an admin account

In all cases, that specially-granted admin can be taken away if/when admin is given to
another user, and won’t re-occur unless explicitly handed admin privilege through the
admin management page.

Note, this is in part a web site design exercise; we have at least two "management"
activiities: user management and admin management. Consider how you want to lay this
out and present it to the user.

3. Pick an earlier exercise and check it against the WebAIM or Section 508 check-lists; make
appropriate changes to satisfy those checklists. Have someone review your work to see if you
overlooked any of the items, and review their page to see if they overlooked any of the items.

4. Research the availability of tools to probe a website for security holes. Run them against your
admin page web site.

9.12. Project
Review your project for attack vectors. Identify its weaknesses and apply appropriate hardening.

Add user management to your project using the provided ASP.NET Membership set-up from the
template Web Site. Note that since you are not using SSL on your deployed application, you should
make it very clear in your web pages that users should not use a password they use elsewhere; your
site does not provide the security that commercial sites have.

Consider if your site needs an admin role that has more permissions, and if so implement an admin
role and add checks to adminstrative functions so they are only carried out by users in the admin
role.

Also do a review of your project against the WebAIM checklist and make any needed adjustments.

262
Chapter 10. Validation and Helpers
It’s considered good design in web sites to check for valid data early — before the data goes to the
server. Note that you still have to check for valid data on the server, since HTTP requests may not
come from your page but be manually created and issued (even form post requests).

HTML5 has some check for client-side validation; ASP.NET provides validators for ensuring the
values are good at the server, and providing helpful messages when they are not. These will check
for values you specify are valid, and will generate appropriate messages when a request’s values
are not valid.

This requires that we look at how data comes from the user, and at the ASP.NET utilities supplied
for Validation, the Validation class and the Html.ValidationSummary and Html.ValidationMessage
methods. These three work in conjunction with each other.

10.1. Input values


Values can come in from several places: they can be submitted in a form, present in the query
string of the URL, or part of the url route request.

10.1.1. ASP.NET routes

A URL has these distinct parts:

Figure 23. Parts of a URL from What is a URL? CC-BY-SA-2.5

The protocol, domain name, and port identify the web server. The path to the file is used by
ASP.NET Routing and may become part of the input values. We will see how to access the
parameters in the next section.

So far in this material, I’ve always had the URL path lead directly to a file, including the .cshtml
extension. However, a key issue in Search Engine Optimization (SEO) is how pages are located and
bookmarked. It is harder to get a high ranking with parameters on your URL.

ASP.NET provides an alternative interpretation of the path to allow for parameter values to be
encoded in the path rather than supplied as separate parameters. Here is its path interpretation
algorithm:

1. If there is a .cshtml extension on the last value in the path, locate the file and run it (this will get
a 404 if there is no file).

263
2. Otherwise, if there is no file extension on the last value, look for one with a .cshtml extention in
that directory, and if found, run it.

3. Otherwise, look at the parent "directory" name as if it were a file with no extension and see if
there is a .cshtml file at that path; if there is such a file, run that page and pass the last value to
it.

4. Otherwise continue this check up the path until you find a match or root is reached; if a match
is found, pass the unused part of the path as values in UrlData.

5. If no file is found and root is reached, go back to the full path and look for Default.cshtml and
then Index.cshtml in that directory (all cases of those two names are used, so default and index
will also be found).

So we could construct URLs for a page collecting social data like so:

If my URL is http://www.myserver.com/SocialData/argoc/42 then:

1. It doesn’t end in .cshtml so rule 1 is skipped.

2. Look for SocialData/argoc/42.cshtml - it won’t be found as that is data for the Social Data page.

3. Look for SocialData/argoc.cshtml and be ready to pass 42 to it. It won’t be found, as this is still
data for my page.

4. Look for SocialData.cshtml. This one is found, so argoc/42 is passed to it in the UrlData and it is
run.

5. There was no need to return to the full URL and look for /SocialData/argoc/42/Default.cshtml or
/SocialData/argoc/42/Index.cshtml.

Once the page is running, it can access the path that came after it in the URL through the UrlData
property available on the page. UrlData is a simple array of strings, with UrlData[0] holding the first
(on the left) unused name in the path, and UrlData[1] holding the second one, and so on; all of the /-
separated names are in the UrlData array.

This code would display all that were available to you; try passing "long" URLs to this page to see
what shows up.

264
Listing 32. UrlDataDemo.cshtml

<!DOCTYPE html>
<html>
  <head>
  <title>URL Data Demo</title>
  </head>
  <body>
  @if (UrlData.Count == 0)
  {
  <p>Enter this page with a URL such as
  <a href="@((Request.Url).ToString())/a/b/c/1/2/3 ">
  @((Request.Url).ToString())/a/b/c/1/2/3</a>
  (and drop the .cshtml if you used it) to see what is displayed.</p>
  } else
  {
  <p>The URL you entered was @Request.Url</p>
  }

  <p>Number of items in UrlData: @UrlData.Count</p>


  <ul>
  @for (int i = 0; i < UrlData.Count; i++)
  {
  <li>[@i]: @UrlData[i]</li>
  }
  </ul>
  </body>
</html>

10.1.2. URL parameters

A URL has these distinct partsLooking at our URL again:

Figure 24. Parts of a URL from What is a URL? CC-BY-SA-2.5

The protocol, domain name, and port identify the web server. The path to the file is used by
ASP.NET Routing and may become part of the input values.

The parameters in the URL are key-value pairs; if you submit your form with method="get", you will
see the form fields as parameters, with the form name as the key and the form field value as the
value.

265
These URL parameters are available to you in ASP.NET using the Query property of the page. The
Query property is a dictionary index like Request; you index into it with the key, and the value is
returned to you, like so:

  // if the url has ?screenName=argoc&faveNum=42:


  string screenName=Request.Query["screenName"]; // argoc
  int num = Request.Query["faveNum"].AsInt(); // 42, convert into int

The values are all strings, so any integers or other information will need to be converted back to
their types. Note that the URL-encoding you see in your browser bar will be turned back into
characters in the Query values (spaces will be spaces, not the three charaters "%20").

10.1.3. Form fields

We have been getting form fields directly from the Request, like so: Request["field-name"]. The \[]'s
look like an array index operation, and they are, but to a special array with string indexes rather
than numeric ones. These are usually referred to as dictionaries — the string key is used to look up
the value.

The .NET class behind dictionaries is called System.Collections.Generic.Dictionary.


NOTE It is a generic type, meaning you can say what the types are for both the key and the
index. Request is a Dictionary from a string key to a string value.

When we use Request as the dictionary, it is actually searching 4 different parts of the HTTP request
for keys (from HTML name attributes), in this order:

1. parameters

2. form fields

3. cookies

4. client certificate

5. server variables

If you want to ensure you are only looking at one of those 5 areas' available keys, and not the other
4, then look at its particular property in request, which is also available as a dictionary with key
indexing:

HTTP request portion Property name

parameters QueryString

form fields Form

cookies Cookies

client certificate ClientCertificate

server variables ServerVariables

We will disuss using the other three later in this chapter.

266
10.2. Check if user’s input matches validation
The ASP.NET class Validator class provides static methods that let you say what fields you want to
test, and how to test them. Typical checks include:

• ensuring a value was specified

• ensuring the value is the right type (int, date, string…)

• ensuring the value is in the appropriate range or matches the appropriate pattern

You should validate all portions of the form, as the user may be manually generating the post
request, so select list values are not guaranteed to match those supplied.

Validation check Description

Validation.RequireField(field-name, optional- provide the form field name (from your form’s
error-message) name attribute) as a string value and, if desired,
the error to display when no value is provided
for that field.

Validation.RequireFields(field1-name, field2- provide the required fields in a single call.


name, …)

Validation.Add(field-name, validation-type) add a check on the named field. The validation-


type can be: * Validator.DateTime(optional-
error-message) * Validator.Decimal(optional-
error-message) * Validator.EqualsTo(otherField ,
optional-error-message) *
Validator.Float(optional-error-message) *
Validator.Integer(optional-error-message) *
Validator.Range(min, max, optional-error-
message) * Validator.RegEx(pattern, optional-
error-message) * Validator.Required(optional-
error-message) * Validator.StringLength(length)
* Validator.Url([error message])

These checks would be defined at the start of your page.

10.3. Check if all validation tests pass


You check if the validation checks succeeded before doing any processing by calling
Validation.IsValid() and checking the result, a boolean value. Since the form had to be submitted,
this typically foes with the IsPost check like so:

if(IsPost && Validation.IsValid()){


  // Process form submit
}

If IsValid returns false, you typically skip normal page processing and re-present the form to the
user with the bad values.

267
10.4. Display validation errors
The two methods Html.ValidationMessage and Html.ValidationSummary can be used to inform the
user what checks did not pass. Html.ValidationMessage must be given the form field name; it checks
the result for that particular field, and if any failed, provides their error messages. These are the
messages you provided, or defaults if you did not provide any.

Typically you put Html.ValidationMessage(field-name) by each form field, so the message shows up
when there is an issue with the value. You might put Html.ValidationSummary at the top of your form
or by the Submit button.

Here is an example showing the Validation setup and checks:

Listing 33. ValidationDemo.cshtml

@{
  var message="";
  // Specify validation requirements for different fields.
  Validation.RequireField("screenName", "Screen name is required");
  Validation.RequireField("faveNum", "Favorite number is required");
  Validation.Add("screenName", Validator.StringLength(10));
  Validation.Add("faveNum", Validator.Integer("Favorite number must be an
integer"));
  Validation.Add("faveNum", Validator.Range(1, 100, "Favorite number must be between
1 and 100"));
  Validation.Add("faveUrl", Validator.Url("Favorite site must be a URL"));

  if (IsPost) {
  // Before processing anything, make sure that all user input is valid.
  if (Validation.IsValid()) {
  var screenName = Request["screenName"];
  var faveNum = Request["faveNum"].AsInt();
  var faveUrl = Request["faveUrl"];
  message += @"For screen name, you entered " + screenName;
  message += @"<br/>For favorite number, you entered " + faveNum;
  message += @"<br/>For favorite site, you entered " + faveUrl;

  // Further processing here


  }
  }
}
<!DOCTYPE html>
<html lang="en">
<head>
  <title>Validation Demo</title>
  <style>
  body {margin: 10%; font-family: 'Verdana, Arial'; font-size: medium; }
  </style>
</head>
<body>
  <h1>Validation Demo</h1>

268
  <p>Enter information, see if you can break the form.</p>
  <form method="post">
  @Html.ValidationSummary()
  <div>
  <label for="screenName">Your screen name (up to 10 characters): </label>
  <input type="text" name="screenName" value="@Request["screenName"]" />
  @Html.ValidationMessage("screenName")
  </div>

  <div>
  <label for="faveNum">Your favorite number (1-100): </label>
  <input type="text" name="faveNum" value="@Request["faveNum"]" />
  @Html.ValidationMessage("faveNum")
  </div>

  <div>
  <label for="faveUrl">Favorite website (URL): </label>
  <input type="text" name="faveUrl" value="@Request["faveUrl"]" />
  @Html.ValidationMessage("faveUrl")
  </div>

  <div>
  <input type="submit" value="Submit" class="submit" />
  </div>

  <div>
  @if(IsPost){
  <p>@Html.Raw(message)</p>
  }
  </div>
  </form>
</body>
</html>

10.5. Client-side validation


All of our checks so far are server-side checks. Rather than require you to hand-code client-side
checks in HTML5 and JavaScript, ASP.NET Web Pages provides hooks to have most checks made on
the client-side as well.

You must check values on the server, as that is the point at which the values
impact potential persistent data. Checking on the client has become popular as
it avoids the round-trip to the server before reporting a failure.
WARNING
Server-side checking is mandatory for a secure system; client-side checking is a
nice-to-have that improves the user’s experience.

To make these checks function on the client-side, you must register three JavaScript libraries in
your page:

269
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>

If you created your site from a template, all three files will be in your Scripts directory and can be
directly referenced (the version number on jquery may differ; change the src value to match your
file). If you are not already working with a non-empty Web Pages template (like Starter Site) that
includes the library, create a Web Pages site that’s based on Starter Site. Then copy these three .js
file to your current site.

In each form field, add a call to Validation.For(field-name) to get the client-side check; this will put
attributes in the form field to match the required validations.

Validation.For is a Razor helper, so it is replaced by attributes that are used by client-side


validation. jQuery uses these to do unobtrusive validation (thus the third script’s name).

Here is our example with these two changes made:

Listing 34. ValidationDemoClient.cshtml

@{
  var message="";
  // Specify validation requirements for different fields.
  Validation.RequireField("screenName", "Screen name is required");
  Validation.RequireField("faveNum", "Favorite number is required");
  Validation.Add("screenName", Validator.StringLength(10));
  Validation.Add("faveNum", Validator.Integer("Favorite number must be an
integer"));
  Validation.Add("faveNum", Validator.Range(1, 100, "Favorite number must be between
1 and 100"));
  Validation.Add("faveUrl", Validator.Url("Favorite site must be a URL"));

  if (IsPost) {
  // Before processing anything, make sure that all user input is valid.
  if (Validation.IsValid()) {
  var screenName = Request["screenName"];
  var faveNum = Request["faveNum"].AsInt();
  var faveUrl = Request["faveUrl"];
  message += @"For screen name, you entered " + screenName;
  message += @"<br/>For favorite number, you entered " + faveNum;
  message += @"<br/>For favorite site, you entered " + faveUrl;

  // Further processing here


  }
  }
}
<!DOCTYPE html>
<html lang="en">
<head>
  <title>Validation Demo</title>

270
  <style>
  body {margin: 10%; font-family: 'Verdana, Arial'; font-size: medium; }
  </style>
  <script src="~/Scripts/jquery-1.10.2.js"></script>
  <script src="~/Scripts/jquery.validate.js"></script>
  <script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
</head>
<body>
  <h1>Validation Demo</h1>
  <p>Enter information, see if you can break the form.</p>
  <form method="post">
  @Html.ValidationSummary()
  <div>
  <label for="screenName">Your screen name (up to 10 characters): </label>
  <input type="text" name="screenName"
  value="@Request["screenName"]"
  @Validation.For("screenName") />
  @Html.ValidationMessage("screenName")
  </div>

  <div>
  <label for="faveNum">Your favorite number (1-100): </label>
  <input type="number" name="faveNum"
  value="@Request["faveNum"]"
  @Validation.For("faveNum") />
  @Html.ValidationMessage("faveNum")
  </div>

  <div>
  <label for="faveUrl">Favorite website (URL): </label>
  <input type="text" name="faveUrl"
  value="@Request["faveUrl"]"
  @Validation.For("faveUrl") />
  @Html.ValidationMessage("faveUrl")
  </div>

  <div>
  <input type="submit" value="Submit" class="submit" />
  </div>

  <div>
  @if(IsPost){
  <p>@Html.Raw(message)</p>
  }
  </div>
  </form>
</body>
</html>

Some checks will not be made on the client: data type validation is not done. You could choose to

271
add some of these checks, as HTML5 forms added values to the type attribute that would permit
direct client-side checks of them.

These checks are made on the client (as well as the server):

• Required
• Range(min,max)
• StringLength(max-length, optional-min-length])
• Regex(pattern)
• EqualsTo(otherField)

In this example, the test for a valid URL won’t work in client code. However, the test will be
performed in server code.

Note that validation checks will be applied to form data regardless of whether it is submitted with
GET or POST; however, our IsValid check only occurs if the form has been submitted via a POST
request, given how we’ve coded the page (which, since the form is submitted POST, works just fine).

When would you want to submit form data with GET? Hint: google.com does this.

Submitting form data with GET is useful if you want to let the user bookmark the
results.
TIP
In fully-fledged web sites, if bookmarking form results is expected, usually more
advanced methods are used so that the bookmark looks like a URL with no parameters
- which is one key reason why ASP.NET includes routing and ways to redefine it. This
can be important in Search Engine Optimization (SEO).

10.6. HTML5 validation tools


HTML5 provides several new form attributes for client-side validation of form contents. It also has
CSS selectors to enable highlighting bad form values; these are not fully integrated with
Validation.For, so be sure to test them carefully.

Css has a :invalid and a :valid selector that can be useful in providing visual cues to the user:

input:invalid {
  border: 1px solid red;
}
input:valid {
  border: 1px solid green;
}

These attributes can be used on form fields (<input>, <select>, <textarea>, and the other items
active in a field):

272
attribute values description

required presence field cannot be blank when


submitted

maxLength integer limits the numer of characters


in the field

pattern regex requires the input match the


regular expression supplied

min and max integers limit the range of values in the


field

disabled - value cannot be changed from


what is shown

The type value can be set to something other than text for more complete checking of types on the
client. The recognized values are:

type value notes

text constrained by maxLength

number can be decimal; constrained by min and max

email not validated in all browsers yet

tel semantic type for telephone numbers, but not


validated due to the large variety of formats
around the world

url valid URL

password not displayed to the user; however, clear-text in


the POST value

search text field, but set up as a search

In addition you can provide <datalist>s to suggest appropriate values to the user; they can type in
any value, but the datalist will be used for autocomplete if the user’s input matches a prefix of any
of the values.

<label for="faveUrl">What's your favorite web site?</label>


<input type="url" id="faveUrl" list="suggUrl" />
<datalist id="suggUrl">
  <option>http://google.com/</option>
  <option>http://stackoverflow.com/</option>
  <option>http://slack.net/</option>
  <option>http://wired.com.</option>
</datalist>

Another type of example you can provide is a "placeholder" attribute value, which puts a value in
the text box that disappears as soon as the user types. The internet community has not decided

273
whether it likes these or not, see if you think they add value to your site.

<label for="faveNum">What's your favorite number?</label>


<input type="number" id="faveNum" placeholder="42" />

Note that even with type=number in the form, the value provided to you on the server is still a string.

There are no built-in checks for dates; however there is a datepicke available in jquery-ui. This
helps the user enter the date correctly, and also gives them a clear visual to improve data entry
accuracy. See https://jqueryui.com/datepicker/ for details on its use.

10.7. Helpers
The Validation class is a Razor Helper; it is there to make generating validating web pages easier,
and it does its job well.

There are several other Helper classes provided in ASP.NET to aid in generating solid web pages.

We already discussed HTML encoding issues, and the use of Html.Raw and Html.Encode to protect
your site against HTML/JavaScript injection attacks.

We also covered the WebGrid and Map Helpers when we discussed collections and databases.

However, the HtmlHelper class contains quite a variety of methods that can be very useful in
generating a variety of HTML structures.

Porting happens
It’s up to you to use the form helpers or not — if you use them, you are tieing your code
very tightly to the ASP.NET section of the universe. If you write out the HTML yourself,
then at least the client-side code for your website is easier to port to another web
TIP
stack. Porting is the act of taking your code from one framework or language and
rewriting it to work under a different framework or language. HTML5 has come a long
way, so it is not as important to use the HtmlHelpers in ASP.NET as it was prior to
HTML5.

Html Helper method description

Html.CheckBox generate a checkbox field

Html.DropDownList generate a select list field

Html.Hidden generate a hidden field

Html.Label generate a label for a given field

Html.ListBox generate a select list field

Html.Password generate a password field

Html.Radio generate a radio-button field

274
Html Helper method description

Html.TextArea generate a textarea field

Html.TextBox generate a text field

Each of these methods has several different implementations (it is overloaded).

For example, TextBox has these signatures:

signature use

TextBox(string) generates the field with the given string as name


and id attribute values.

TextBox(string, object) as above; the object specifies the initial value (its
ToString will be used)

TextBox(String, Object, IDictionary<String, as above, and pass additional attributes as


Object>) key/value pairs

TextBox(String, Object, Object) same as the previous one, using an anonymous


object rather than a dictionary

You can see details of these with examples on the MSDN ASP.NET Web Pages 2 Reference page on
HtmlHelper Methods

The following sample creates a drop down list using the helper. Helpers like this are especially
useful when you are displaying a form based on values in a database (the SelectListItem can be
constructed when you return values from the database).

275
Listing 35. DropDownListHtmlHelperDemo.cshtml

<!DOCTYPE html>
<html>
<head>
  <title>Drop Down List Demo</title>
</head>
<body>
  <h1>Drop Down List Demo</h1>

  @{
  // build the list for the drop down list manually or
  // pull a list of name/value pairs from a database.
  List<SelectListItem> items = new List<SelectListItem>();

  items.Add(new SelectListItem { Text = "Ford", Value = "ford" });


  items.Add(new SelectListItem { Text = "Chevrolet", Value = "chevrolet" });
  items.Add(new SelectListItem { Text = "GMC", Value = "gmc", Selected = true
});
  items.Add(new SelectListItem { Text = "Lincoln", Value = "lincoln" });

  }

  <form method="get"> <!-- choice visible in URL on submit -->


  @Html.Label("Choose one:","choiceList")
  @Html.DropDownList("choiceList", @items)
  <input type="submit" />
  </form>

</body>
</html>

Notice that the DropDownList requires a collection of SelectItem`s to provide the name/value pairs
needed for the list. `ListBox behaves similarly.

The generated form looks like this on the page:

<form method="get"> <!-- choice visible in URL on submit -->


  <label for="choiceList">Choose one:</label>
  <select id="choiceList" name="choiceList">
<option value="ford">Ford</option>
<option value="chevrolet">Chevrolet</option>
<option selected="selected" value="gmc">GMC</option>
<option value="lincoln">Lincoln</option>
</select>
  <input type="submit" />
</form>

276
These Helpers become more useful in ASP.NET MVC, when Model class attributes also
TIP
impact the HTML they generate.

10.8. Other helpers


ASP.NET provides several other helpers you might find useful to explore, see the
System.Web.Helpers namespace for links to their specifications. Here are a few you may be
interested in exploring further:

Class Description

AntiForgery helps prevent forged requests and cross-site scripting attacks

Chart generates charts from data (see tutorial)

Crypto encryption capabilities for keys and passwords

Json manipulates data in JavaScript Object Notation (JSON) format.

WebCache helps improve performance by caching client-side data (see tutorial)

WebGrid generates a HTML table from data

WebImage image display and management

WebMail email using Simple Mail Transfer Protocol (SMTP)

10.9. Other HTTP request data sources


As we mentioned earlier, there are 5 sources of data in an HTTP Request:

• QueryString

• Form

• Cookies

• ClientCertificate

• ServerVariables

When you access the Form fields, you usually know the names of the fields; however that may not
be the case with the final three.

All five are actually collections, and so could be accessed with foreach loops, iterating through their
contents.

10.9.1. Cookies

In the Cookies collection, each cookie is an element in the collection; it is an instance of


System.Web.HttpCookie, with several cookie properties:

277
HttpCookie property description

Domain the domain the cookie is associated with

HasKeys true if the cookie has subkeys

HttpOnly false if the cookie is accessible by client-side script

Item[String] a shortcut to the Values property (for backward compatibility)

Name the name of the cookie (its key)

Path the virtual path of the cookie

Secure indicates whether to transmit using HTTPS only or not

Shareable if true, the cookie can participate in output caching

Value the cookie’s value

Values the cookie’s key/value pairs if they are embedded within the cookie

It’s not likely we will be using cookies with our simple applications, but there are some Helpers for
Security that will be making use of them. Cookies are one way to maintain session state if you need
to retain information for a user session.

Name and Value are the two properties you would be most likely to want to read, as they represent
the key/value pair of the cookie.

The European Union has strict regulations on the use of cookies, so it’s best to pop
NOTE up a warning to inform the user you are using cookies to satisfy their regulations,
regardless of the source of the HTTP request you are processing.

Be careful about what you put in cookies; they travel between client and server, and so you risk
exposing information in a live web site that could compromise security.

10.9.2. ClientCertificate

The ClientCertificate property holds an HttpClientCertificate object, which contains information


about the client’s security certificate, if one was provided in the HttpRequest. This class has several
fields, and it is likely you would want to print them all out to get a complete view of the certificate.

ClientCertificate properties

Certificate

Cookie

Flags

IsPresent

Issuer

IsValid

278
ClientCertificate properties

KeySize

SecretKeySize

SerialNumber

ServerIssuer

ServerSubject

Subject

ValidFrom

ValidUntil

You may find that a ToString or ObjectInfo.Print call will give you sufficient information should you
need to debug a certificate. Be careful exposing this information in a live web site, as it could
compromise security.

10.9.3. ServerVariables

The web server runs within an operating system itself. At the operating system level, it is possible to
set environment variables. This is often done as a way to configure servers with sensitive
information such as passwords - putting them in _AppStart.cshtml is not secure if your source code
is Open Source, as then anyone who finds your Open Source repository can see the contents of that
file.

The variables can be browsed with the ServerVariables property. This is often quite a long list, so be
prepared for output if you print them all out.

The ServerVariables property holds a NameValueCollection, so is accessed like other dictionaries,


getting the AllKeys property, which provides an array of strings, with each entry in the array being
a key from the collection. Then the code needs to iterate through the keys to get the values
associated with each key in turn. A NameValueCollection can map one key to several values, so once
the values are retrieved with the GetValues(key-value) method as an array of strings, an embedded
for loop (or foreach loop) is needed to print out that array’s contents in turn.

Be careful exposing this information in a live web site, as it could compromise security.

10.10. Further Reading


• http://www.asp.net/web-pages/overview/ui-layouts-and-themes/validating-user-input-in-aspnet-
web-pages-sites

• https://msdn.microsoft.com/en-us/library/ms972961.aspx

• https://msdn.microsoft.com/en-us/library/7kh55542.aspx

• https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Forms/Data_form_validation

• https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Forms

279
• https://jqueryui.com/datepicker/

• https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_is_a_URL

• https://msdn.microsoft.com/en-us/library/ms524948(v=vs.90).aspx

• http://www.asp.net/web-pages/overview/routing/creating-readable-urls-in-aspnet-web-pages-
sites

• http://www.mikesdotnetting.com/Article/165/WebMatrix-URLs-UrlData-and-Routing-for-SEO

• http://www.mikesdotnetting.com/article/187/more-flexible-routing-for-asp-net-web-pages

• https://msdn.microsoft.com/en-us/library/system.web.httprequest.cookies(v=vs.110).aspx

• https://msdn.microsoft.com/en-
us/library/system.web.httprequest.clientcertificate(v=vs.110).aspx

• https://msdn.microsoft.com/en-
us/library/system.web.httprequest.servervariables(v=vs.110).aspx

• http://www.mikesdotnetting.com/article/184/html-helpers-for-forms-in-razor-web-pages

• https://msdn.microsoft.com/en-us/library/system.web.webpages.html.htmlhelper(v=vs.111).aspx

10.11. Exercises
1. SEO is a big topic and very important to those attempting to "go viral" on the internet. Consider
some of your past exercises. What improvements can you make to improve their SEO rating?
Choose one to update to use UrlData (a path) rather than a Form submission. This may require
JavaScript skills — the submit button needs to craft the target URL based on form values.

2. Make your own URL testing page: start with UrlDataDemo.cshtml and add loops to print out any
Form data, Query data, and the Anchor as well. It should print each group of data out separately
and label them to say where they are from.

See the MSDN documentation for System.Web.HttpRequest, the class behind the Request object,
to identify the properties they are stored in. Use loops on the collections, locating the keys and
values. Your page should work even if a form is submitted. Don’t put a form on your
page — make a small form that targets your UrlDataDemo.cshtml to test it.

10.12. Lab
It is not uncommon within a project to complete one task and then move on to another. So, it’s time
to review your project with an eye to adding validation and helpers.

Add validation to your web site’s forms, and if appropriate, make use of some of the HtmlHelpers.
Do any of them make it useful for you to create page-local functions or helpers of your own? If so,
do it. Development is just that — the iteration of the process of coding, striving for better code.

280
Chapter 11. ASP.NET MVC 5
Eventually, you will work on a web site that is just a little too big and complex for Razor Web Pages.
That is where MVC comes in; MVC is "Model-View-Controller", and is a nod to a famous Design
Pattern in OO programming that is very useful for applications with heavy user interaction (like
web sites!).

Figure 25. Model View Controller Architecture by BlueSky23 CC BY-SA 3.0

TODO summary of MVC

Could do the blog one: https://github.com/madskristensen/MiniBlog

11.1. Further Reading


Here is another transformation of a Web Pages application into an MVc application. It starts from
the "Bakery" template available in WebMatrix (but not in Visual Studio).

• http://www.mikesdotnetting.com/article/262/migrating-from-razor-web-pages-to-asp-net-mvc-5-
views-and-controllers

• http://www.mikesdotnetting.com/article/263/migrating-from-razor-web-pages-to-asp-net-mvc-5-
data-access-and-view-models

281
http://www.mikesdotnetting.com/article/264/migrating-from-razor-web-pages-to-asp-net-mvc-5-
model-binding-and-forms

• http://www.mikesdotnetting.com/article/210/razor-web-pages-e-commerce-adding-a-shopping-
cart-to-the-bakery-template-site a post about adding a shopping cart to the bakery website
(related, but expanding rather than converting)

282
Addendum A
Razor Quick-Reference
Syntax/Sample Razor remarks

Code Block @{ C# inside the block: case-sensitive, strings


int x = 123; require double quotes, and comments
string y = "because."; are C#-style. Variables have to be
} declared before they are used in code
(variables can be used in a later code
block on the same page).

Inline Expression (Html <span>@message</span> Razor "knows" where expressions end.


Encoded) Local variables from earlier on the page
are visible, as are helpers and system
objects. So Hello @title. @name. knows
the variables are title and name since
there is whitespace after the .'s

Expression (Unencoded) <span>@Html.Raw(message)</ Html is a Razor Helper (utility that


span> provides methods)

Combining Control and @foreach(var item in You can "break out" of Razor with a
Text items) { simple HTML tag, as long as it is closed to
<span>@item.Prop</span> end the HTML block. Within that, use @
} to go back into Razor. All of the C#
control structures can be used this way:
for, foreach, else, while, do..while, and
switch.

Mixing code and Plain text @if (test) { if you don’t have HTML tags, you can use
<text>Hello <text> … </text>
There</text>
}

Mixing code and plain text @if (test) { Same as <text> but can only be one line.
(alternate) @:num’s value is @num Notice you can slip back into Razor with
} an embedded @ inline expression.

Using block @using (Html.BeginForm()) makes Html.BeginForm’s returned HTML


{ form element embed the contents of the
<input type="text" block. That is, the <form> and </form>
value="input here"> will wrap completely around the HTML
} generated within the block.

Email Addresses Hi you@example.com Razor recognizes basic email format and


is smart enough not to treat the @ as a
code delimiter

283
Syntax/Sample Razor remarks

Explicit Expression <span>ISBN@(isbnNumber)</s In this case, we need to be explicit about


pan> the expression by using parentheses,
since otherwise Razor may think it is part
of an email address (notice there is no
space before the @).

Escaping the @ sign <span>tag me as @@ renders a single @ in the response.


@@argoc</span>

Server side Comment @* These comments do not appear on the


This is a server side generated HTML; they can be done in a
multiline comment single line as well.
*@

Calling a method @MyClass.MyMethod(arg1,arg Notice the arguments can be expressions,


2) and do not need @'s before them.

Calling a generic method @(MyClass.MyMethod<AType>( Use parentheses so that the <AType> is


)) not seen as an HTML tag. Generic
methods are advanced C#.

Adding to the page class @functions { the functions and properties defined this
(functions and properties) // put class variable, way are available anywhere on the page
property, and method (they can be used on the page before they
definitions here. are defined). They cannot contain
} embedded HTML (use a helper for that)

Creating a Helper @helper Generates a helper that you can call from
DoSomethingRepetitive(stri within Razor as an inline expression.
ng content, int num) { Helpers don’t return values, but generate
<li> @num. @content</li> HTML for the resulting HTML page.
}

Conditional attributes <div When className = null this generates


class="@className"></div> <div></div> When className = "" this
generates <div class=""></div> When
className = "my-class" this generates
<div class="my-class"></div> There can
be other values in the class value as well.
Any non-null will still appear, so <div
class="@className foo bar"></div> will
be <div class="foo bar"></div> when
className is null or the empty string.
Attributes with data- prefixes are always
rendered even if their values are
variables that are null. data- is a special
attribute name prefix used to hold data
attributes in HTML pages.

Boolean attributes <input type="checkbox" When isChecked is true, generates <input


checked="@isChecked" /> type="checkbox" checked="checked" />
When isChecked is false, generates <input
type="checkbox" />

284
Syntax/Sample Razor remarks

URL Resolution with tilde <script When the app is at / generates <script
src="~/myscript.js"> src="/myscript.js">
</script> </script> When running in a virtual
application named MyApp generates
<script src="/MyApp/myscript.js">
</script> The tilde can be used in any
string value that is interpretted as a file
path; it resolves to the physical location
where the web site is located.

API see There are ASP.NET classes to help with


http://www.asp.net/web- Validation, Databases, Forms, E-Mail, and
pages/overview/api- more.
reference/asp-net-web-
pages-api-reference

Further Reading

• http://razorcheatsheet.com/

• http://www.mikesdotnetting.com/article/173/the-difference-between-helpers-and-functions-in-
webmatrix

• http://www.codeproject.com/Articles/787320/An-Absolute-Beginners-Tutorial-on-HTML-Helpers-
and

• http://haacked.com/archive/2011/01/06/razor-syntax-quick-reference.aspx/

285
Addendum B
C# Quick Reference
Further Reading

• http://www.thecodingguys.net/resources/cs-cheat-sheet.pdf covers basic, core C#

• http://www.digilife.be/quickreferences/qrc/core%20csharp%20and%20.net%20quick%20referen
ce.pdf more in depth, notice format is left column → right column → center column

• https://dzone.com/storage/assets/4471-rc16-010d-csharp_1.pdf good advice for programming


(not a language cheat sheet)

• http://www.tutorialspoint.com/csharp/pdf/csharp_quick_guide.pdf at 111 pages, not really


"quick"; captures the entire tutorialspoint tutorial on C#.

286
Colophon
Produced using AsciiDocFX, AsciiDoctor, Vim, Google Drive, GitHub, Portable Git, Visual Studio
2015, ASP.NET 4.6.1, and AppHarbor. Using material from other Open Educational Resources noted
in the bibliography.

287
Bibliography
These references were key in completing this work. Others are cited in the text where they were
used.

• http://skillcrush.com/2014/10/21/advice-for-web-designers/

• AsciidocFX - used to write the book.

• http://asciidoctor.org/ - used to generate the HTML and PDF.

• http://commons.wikimedia.org - source of several book images

• Think Python 2e by Allen Downey. Green Tea Press. June 2014. Think Python 2e is a Free Book. It
is available under the Creative Commons Attribution-NonCommercial 3.0 Unported License,
which means that you are free to copy, distribute, and modify it, as long as you attribute the
work and don’t use it for commercial purposes. I have used Appendix A and the book overall as
a model in this work.

• Think Java v6 also CC-BY-NC-3.0. I have used Appendix C, Chapter 2, and the book overall as a
model in this work.

• Introduction to Programming Using Java v7 by David J. Eck. Hobart and William Smith Colleges.
August 2014. CC-BY-NC-SA-3.0. I have used several chapters in this work.

• Images of Visual Studio 2015 Community Edition Update 3 used with permission of Microsoft
per their licensing.

• http://www.w3schools.com/aspnet/razor_syntax.asp reference material

• Wikiversity Web Design CC-BY-SA-3.0 Material from this contributed to chapter 2’s material on
web design.

• http://www.asp.net/web-pages/overview/getting-started/introducing-razor-syntax-c Chapter 3
benefited from this amazing tutorial on Razor.

• https://appharbor.com/ a PaaS ASP.NET cloud service with a usable free tier for deployment of
the applications in this text.

• http://blog.slaks.net/2011/01/dissecting-razor-part-1-pieces-of.html - this and the later parts give


insight into the inner workings of Razor: how it does what it does.

• http://www.csharpcourse.com/ reference material

• https://code.msdn.microsoft.com/Introducing-ASPNET-Web-cad79534 licensed under the Apache


License (code located here https://github.com/joinabhimanyu/WebPagesMovies )

• https://code.msdn.microsoft.com/CSASPNETSearchEngine-3eb92010 licensed under MS-LPL

• https://code.msdn.microsoft.com/Search-SQL-Server-database-21d70eaa licensed under MS-LPL

• https://developer.mozilla.org/en-US/ an in-depth repository of HTML, CSS, and JavaScript


information in particular the parts that are Creative Commons Attribution-ShareAlike license
(CC-BY-SA), v2.5 as described by MDN’s License Terms

288

You might also like