• 20 hours
  • Easy

Free online content available in this course.

course.header.alt.is_video

course.header.alt.is_certifying

Got it!

Last updated on 10/31/23

Communicate with the world: user input and networking

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:

  1. Getting input from the user.

  2. Fetching data on the internet.

  3. 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:

  1. Checks whether an argument has been provided.

  2. Prompts the user for a URL if not provided.

  3. 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:

  1. Connect to the resource identified by the URL.

  2. 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 named content to store the response from the URL.

  • The using statement wraps the creation a WebClient instance named webClient. The WebClient class provides methods for communicating with a URL.

  • Call the webClient 's DownloadString method passing url as a parameter. Assign the result of this call to the content 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.

Example of certificate of achievement
Example of certificate of achievement