What is the world?
There are different types of software you'll need to write, from small utilities to enterprise software. Despite the size, they will rarely be stand-alone applications functioning within their own environment. More likely, they will be working with local storage (a local hard drive), communicating with other applications locally, or using remote services over the network.
In this chapter, we will cover three kinds of interactions:
Getting input from the user.
Fetching data on the internet.
Writing to a file.
For this, we will ask for a URL (a web page address), make sure it is correct, fetch the content addressed by the URL, and write it to a file.
Get and validate input from the user
User input can be gathered either when the program is started using command-line arguments, or by prompting the user at any point during the program execution.
Checking for a command-line input
The following code is located inside a UserInput
class which is part of a Communication
namespace.
When user-defined elements are provided at program startup, they are made available in the args
array of the Main
function. Here is the code for the class with a Main function that:
Checks whether an argument has been provided.
Prompts the user for a URL if not provided.
Displays whether the URL is formatted correctly or not.
using System;
namespace Communication
{
/// <summary>
/// Demo of getting and checking User input
/// </summary>
/// <remarks>Created by the OpenClassrooms Education Team</remarks>
public class UserInput
{
/// <summary>
/// Check if user has provided a URL from the command line
/// If not prompt for one
/// In both cases make sure the URL is well-formed!
/// </summary>
/// <param name="args">Either nothing or a URL string</param>
public static void Main(string[] args)
{
string urlString = "";
int numberOfArguments;
if (args == null)
{
numberOfArguments = 0;
}
else
{
numberOfArguments = args.Length;
}
// Assign a value to urlString or exit
switch (numberOfArguments)
{
case 0:
urlString = AskForUrl();
break;
case 1:
urlString = args[0];
break;
default:
Console.WriteLine("Please run the program with the desired URL or no argument at all");
Environment.Exit(-1);
break;
}
Console.WriteLine("Checking URL " + urlString);
if (ValidURL(urlString))
{
Console.WriteLine(urlString + " is a well-formed URL");
}
else
{
Console.WriteLine(urlString + " is not a well-formed URL");
}
}
}
}
Since we are making a decision based on the different possible values of an expression (the args.Length
property), we use a switch
statement:
If the user has not provided any argument on the command line, this length is 0. Therefore, call the
AskForUrl()
function and assign its result to the urlString variable.If the user has provided one argument, assume it is the URL she wants to provide. Therefore, directly assign this value to the
urlString
variable.If the user has provided more than one argument, you don't know what to do! Therefore, exit with the
Environment.Exit(-1)
statement.
It works! Let's check the implementation of the AskforUrl
function.
Asking for an input
/// <summary>
/// Prompt user for URL
/// </summary>
/// <returns>A string representation of the URL entered by the user</returns>
public static string AskForUrl()
{
Console.WriteLine("Please enter a valid URL");
string url = Console.ReadLine();
return url;
}
Let's complete this section on user input by checking the validity of the input.
Checking the validity of the provided URL
Getting user input is a terrific first step. There is one rule that is essential both for practical and security reasons: always validate user input.
Some users will make mistakes. Others will try to find ways around your application's security. To check that the user-provided string actually represents a URL, C# offers a URI class that has a method that will throw an exception if the provided string representation is not a properly formatted URL.
Here is the code for the IsValidUrl
function that uses the URL class:
/// <summary>
/// Check if a string is a well-formed URL
/// </summary>
/// <param name="urlString"></param>
/// <returns>true if the URL is well formed, else false</returns>
private static bool IsValidURL(string urlString)
{
if (Uri.IsWellFormedUriString(urlString, UriKind.Absolute))
{
return true;
}
else
{
return false;
}
}
The gist of this code is the Uri.IsWellFormedUriString(urlString, UriKind.Absolute)
statement.
If the URL is formatted correctly, the instantiation works, and it returns
true
.If the URL is an absolute path and not a relative path, it returns
true
.If the URL is not formatted correctly, it return
false
.
Now that you have all the pieces, let's run the code.
Try it out for yourself!
Ready to get started? To access the exercise, click this link.
Great! Now that we are able to get some input, and check that it consists of a well-formed URL, let's grab the content the URL refers to!
Get the content from a URL with networking
Networking consists of managing a request-response combination over a network; typically the internet.
Your code needs to do the following:
Send a request to the server and wait for a response, or handle the no-network situation.
Wait for response, and process the response/or no response.
Why would there be no response?
A no response situation can occur for various reasons:
You sent request to an incorrect URL.
The server is not available (temporarily or permanently).
Processing of the request took too long.
And more.
For the request-response code, you'll need to:
Connect to the resource identified by the URL.
Fetch the content and put it in a list.
Connecting to a resource
Let's create a RemoteContent
class inside the same Communication
namespace as the UserInput
class. This allows you to reuse functions created in the UserInput
class.
In the Main
function of the RemoteContent
class, we'll prompt the user for a URL. Then we'll connect to the resource it links to. Finally, we'll fetch the content of the resource and store it in memory as a list of strings:
using System;
using System.Net;
namespace Communication
{
/// <summary>
/// Demo of a connection to a remote resource
/// </summary>
/// <remarks>Created by the OpenClassrooms Education Team</remarks>
public class RemoteContent
{
/// <summary>
/// Connect to a resource from a URL and display its content
/// </summary>
/// <param name="args">not used in this example</param>
public static void Main(string[] args)
{
// Define the string representation of the URL to connect to
string urlString = UserInput.AskForUrl();
Console.WriteLine(GetContent(urlString));
}
}
}
The first statement of the Main
method is string urlString = UserInput.AskForUrl();
. It calls the AskForUrl()
function from the UserInput
class and assigns the user input string into the urlString
variable.
Let's see how the GetContent
method can fetch the content by receiving this instance as an argument.
Fetch the content from the resource
In the GetContent
method, we create a new WebClient
and download the contents of the given url
into a string. This is the code:
/// <summary>
/// Return the content from the URL
/// </summary>
/// <param name="url">The web address of the network resource</param>
public static string GetContent(string url)
{
string content = "";
try
{
using (WebClient webClient = new WebClient())
{
content = webClient.DownloadString(url);
}
}
catch(WebException e)
{
Console.WriteLine("Cannot establish connection - " + e.ToString());
}
return content;
}
This is what's happening in GetContent
:
Define a
string
variable namedcontent
to store the response from the URL.The
using
statement wraps the creation aWebClient
instance namedwebClient
. TheWebClient
class provides methods for communicating with a URL.Call the
webClient
'sDownloadString
method passingurl
as a parameter. Assign the result of this call to thecontent
variable.If a
WebException
is thrown, write the error description to the console.Finally, return
content
.
We can now run the program and see it in action.
Try it out for yourself!
Ready to get started? To access the exercise, click this link.
Generate a text file
In the last section of this chapter, we will save the resource content into a file, create another class that will use our RemoteContent class, and add the functionality.
The Main function is similar to the last program. Just add a call to a function that will write to a file. Here is the code:
using System;
using System.Net;
using System.IO;
namespace Communication
{
/// <summary>
/// Demo of a connection to a remote resource
/// </summary>
/// <remarks>Created by the OpenClassrooms Education Team</remarks>
public class RemoteContent
{
/// <summary>
/// Connect to a resource from a URL and write its content to a file
/// </summary>
/// <param name="args">not used in this example</param>
public static void Main(string[] args)
{
// define the string representation of the URL to connect to
string urlString = UserInput.AskForUrl();
string content = GetContent(urlString));
try
{
WriteToFile(content,"output.txt");
}
catch(IOException e)
{
Console.WriteLine("Could not write file - " + e.ToString());
}
}
}
}
The file writing takes place if the connection works, thanks to a call to the WriteToFile
method. Here is the code:
/// <summary>
/// Writes the contents of a string to a file
/// </summary>
/// <param name="content">The content to write to a file</param>
/// <param name="fileName">The name of the output file</param>
public static void WriteToFile(string content, string fileName)
{
try
{
File.WriteAllText(fileName, content);
Console.WriteLine("Content written to " + fileName);
}
catch(IOException e)
{
Console.WriteLine("Could not write file to " + fileName);
}
}
The File.WriteAllText
method creates a new file, write the contents to the file, and then closes the file. If the target file already exists, it is overwritten.
Try it out for yourself!
Ready to get started? To access the exercise, click this link.
Let's recap!
In this chapter, you've learned the following:
Networking is managing a request-response combination over the network which is typically the internet and works with URLs.
In C#, the following components are used to implement the URL connection:
URI
- Provides an object representation of a uniform resource identifier (URI), and easy access to its parts.WebClient
- Provides common methods for sending data to and from a resource identified by a URI.File
- Provides static methods for creating, copying, deleting, moving, and opening a single file.