< C# & VB .NET HTTP Protocol Examples | Main | C#, VB .NET & C++ .NET Request-Response Web Examples >

 


 

Chapter 6 Part 7:

Introduction to System.Net

 

 

What do we have in this chapter 6 Part 7?

  1. Request-Response Model

  2. Resolving URIs with WebRequest and WebResponse

  3. Request-Response Model Helper Classes

  4. Deciding When to Use System.Net

  5. Common Scenarios for Using System.Net

  6. Accessing an Existing Service or Protocol Provided by System.Net

  7. Implementing a Protocol Not Provided by System.Net

  8. Extending a Higher Layer of the Stack That Uses System.Net

  9. System.Net vs. Web Services or .NET Remoting

  10. C++ Request and Response Program Example

 

 

Request-Response Model

 

The request-response model in System.Net is defined by the WebRequest and WebResponse classes. These abstract base classes provide an implementation pattern that’s used by protocol-specific implementations such as the FILE and HTTP handlers described in the previous section. This common pattern for request-response enables developers to resolve resources containing different URI schemes in a consistent and protocol-independent manner. For example, this common model enables a developer to write the same code to download a resource on an FTP server as that needed to download a resource on an HTTP server. This model is extensible, so third-party implementers can plug in their own protocol handlers as well. There are also a number of helper classes that work with this model and apply to the various supported protocols. Figure 6-5 highlights the request-response model, including the key methods and properties of WebRequest and WebResponse, as well as the helper classes that work with the model.

 

The System.Net request-response model

 

Figure 6-5: The System.Net request-response model

 

Resolving URIs with WebRequest and WebResponse

 

The WebRequest and WebResponse classes contain methods and properties that apply generically across the different supported protocols and enable applications to download and upload data given a specific URI and to specify authentication details, proxy information, and content details such as the type and size of the content. An asynchronous pattern is also provided for any operation that could be blocking on network activity. Extensibility is achieved through the WebRequest.RegisterPrefix method or through entries in the System.Net section of the application-specific or machine-wide configuration file. The following example demonstrates how to download a file using the request-response model. You’ll notice that this example is very similar to the example shown earlier in the section on HTTP, with the exception that this example resolves URIs with differing protocol schemes.

 

C#

 

static void Main()

{

    ResolveResource("http://www.contoso.com/file.htm");

    ResolveResource("file://c:\\temp\\file.htm");

}

 

static void ResolveResource(string address)

{

    try

    {

        // Create the request object

        WebRequest request = WebRequest.Create(address);

 

        // Issue the request

        WebResponse response = request.GetResponse();

 

        // Read the content

        StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.ASCII);

 

        string content = reader.ReadToEnd();

 

        // Display the content to the console

        Console.WriteLine(content);

 

        // Close the response

        response.Close();

    }

    catch(WebException wex)

    {

        // Display the exception details

        Console.WriteLine(wex.ToString());

    }

}

 

Visual Basic .NET

 

Sub Main()

    ResolveResource("http://www.contoso.com/file.htm")

    ResolveResource("file://c:\\temp\\file.htm")

End Sub

 

Sub ResolveResource(ByVal address As String)

    Try

        ' Create the request object

        Dim request As WebRequest = WebRequest.Create(address)

 

        ' Issue the request

        Dim response As WebResponse = request.GetResponse()

 

        ' Read the content

        Dim reader As New StreamReader(response.GetResponseStream(), Encoding.ASCII)

 

        Dim content As String = reader.ReadToEnd()

 

        ' Display the content to the console

        Console.WriteLine(content)

 

        ' Close the response

        response.Close()

 

    Catch wex As WebException

        ' Display the exception details

        Console.WriteLine(wex.ToString())

    End Try

End Sub

 

Request-Response Model Helper Classes

 

Request-response model helper classes perform a specific function that’s usually common to the different protocols that implement WebRequest and WebResponse. WebProxy and WebException are both examples of such helper classes.

Another example of a request-response model helper is the WebPermission class. WebPermission is used to define code access security privileges for classes that implement the WebRequest and WebResponse base classes. Privileges that are controlled through WebPermission include the ability to access a specific URI, a wildcard set of URIs as supplied by a regular expression, or all URIs as identified by the System.Security.Permissions.PermissionState enumeration.

Finally, the WebClient class provides a number of task-focused methods that perform operations that are commonly useful to applications that deal with resources on the Web. Here are the operations available as one-line method calls with WebClient:

 

  1. Download a URI-based resource to memory.
  2. Download a URI-based resource and save it to a file.
  3. Given a URI, return a readable stream.
  4. Given a URI, return a writable stream.
  5. Upload data from memory to a URI-based resource.
  6. Upload data from a file to a URI-based resource.
  7. Post a name-value collection to a Web form.

 

Because the WebClient class uses the WebRequest and WebResponse classes in its implementation, it works with any protocol handler that has been registered into the request-response model. The following code demonstrates a version of the DownloadWebPage sample considered in the section on WebRequest and WebResponse that has been modified to use WebClient.

 

C#

 

static void Main()

{

    ResolveResource("http://www.contoso.com/file.htm");

    ResolveResource("file://c:\\temp\\file.htm");

}

 

static void ResolveResource(string address)

{

    try

    {

        // Download the content

        WebClient client = new WebClient();

        byte[ ] contentBytes = client.DownloadData(address);

 

        // Convert the content bytes to a string

        string content = Encoding.ASCII.GetString(contentBytes);

 

        // Display the content to the console

        Console.WriteLine(content);

    }

    catch(WebException wex)

    {

        // Display the exception details

        Console.WriteLine(wex.ToString());

    }

}

 

Visual Basic .NET

 

Sub Main()

    ResolveResource("http://www.contoso.com/file.htm")

    ResolveResource("file://c:\\temp\\file.htm")

End Sub

 

Sub ResolveResource(ByVal address As String)

    Try

        ' Download the content

 

        Dim client As New WebClient

        Dim contentBytes() As Byte = client.DownloadData(address)

 

        ' Convert the content bytes to a string

        Dim content As String = Encoding.ASCII.GetString(contentBytes)

 

        ' Display the content to the console

        Console.WriteLine(content)

 

    Catch wex As WebException

        ' Display the exception details

        Console.WriteLine(wex.ToString())

    End Try

End Sub

 

Notice that the networking code in this example has been reduced to two lines, where one of the lines is simply creating the class and the other is performing the download operation. Consider further a comparison of the size of this sample to the socket sample at the beginning of this chapter that performed roughly the same operation of downloading a file. WebClient offers the simplest way in System.Net to accomplish some of the most common network tasks. Similar to the UdpClient and TcpClient classes introduced earlier in this chapter, WebClient does not contain asynchronous methods. Applications requiring asynchronous functionality should use the WebRequest and WebResponse classes instead of WebClient.

 

Deciding When to Use System.Net

 

The .NET Framework contains a number of classes that can come into play when building a distributed application. The usage scenarios for these classes range from connecting to a database to calling a method on a remote object, with a significant number of options in between. Given this broad range, it can be difficult to know exactly which set of classes will be best suited to your scenarios. This section briefly covers the most commonly considered options when building a distributed application on the .NET Framework and provides guidance that can help you determine which layer is most appropriate for the needs of your application.

 

Common Scenarios for Using System.Net

 

Let’s begin this exercise by covering the most common scenarios for using the layers in System.Net. These scenarios can be divided into the three categories shown on the following page.

 

  1. Accessing an existing service or protocol provided by System.Net.
  2. Implementing a protocol not provided by System.Net.
  3. Extending a higher layer of the stack that uses System.Net.

 

Seems pretty easy, right? Well, let’s spend a bit more time going through each of the categories to talk about why they make sense.

 

Accessing an Existing Service or Protocol Provided by System.Net

 

Application services that make sense for System.Net are demonstrated in the samples throughout this book. The most common case by far is that of accessing resources that are available on an HTTP server. If your program needs download or upload resources over HTTP or HTTPS, System.Net should be an easy choice. Likewise, if your application needs to access the name resolution services available in DNS, System.Net.Dns is the best choice. Going forward, FTP and access to other standard protocols will fit into this category as well.

 

Implementing a Protocol Not Provided by System.Net

 

Perhaps your application needs to interact with a service that supports some well-known protocol that’s not supported directly in System.Net. For example, consider the Network Time Protocol (NTP). RFC 1305 provides the following description of NTP:

 

"NTP provides the mechanisms to synchronize time and coordinate time distribution in a large, diverse internet operating at rates from mundane to lightwave."

 

An application wanting to interact with another service that supports the desired protocol would need to implement the NTP protocol in this example. NTP is layered on top of UDP, which is accessible in System.Net through the socket layer classes. The application would then call the socket layer classes to construct a UDP socket and emit the NTP protocol. Other examples that commonly fit well into this category of protocols that are built using the socket-level classes are the Network News Transfer Protocol (NNTP), the Post Office Protocol (POP3), and the Simple Mail Transfer Protocol (SMTP).

Applications might also be implementing a custom protocol that’s only well known within a specific organization. Although this approach is discouraged when architecting new applications, it’s often required in cases where the new application must interoperate with a legacy system. Often, a good approach in these cases is to use System.Net to write the custom protocol that consumes the data from the legacy system and then use a more interoperable solution, such as XML-based Web services, to expose the data or service to other applications within the organization.

 

Extending a Higher Layer of the Stack That Uses System.Net

 

As we’ll discuss at length in Chapters 11 and 12, System.Net provides the underlying transport implementation for the Web services and the .NET Remoting technologies in the .NET Framework. Accessing elements of System.Net to extend and customize the behavior of these higher layers can be a very useful tool for enhancing the performance, interoperability, scalability, and functionality of your application.

 

System.Net vs. Web Services or .NET Remoting

 

The .NET Remoting and Web services technologies in the .NET Framework provide rich and extensible frameworks for accessing objects and services that live outside of your application. In some cases, the boundary between the application and a remote object is simply an application domain. In other cases, it might be across a process, and in other cases, it might be across a network.

It’s often much easier for applications to interact at an object level rather than deal directly with protocols. Therefore, it’s recommended that applications use the .NET Remoting and Web services wherever possible. Even when the .NET Remoting and Web services are viable options, System.Net is a better choice in some cases. For example, suppose that your application needs to download a large amount of data, such as a 10 megabyte (MB) file, and it wants the ability to selectively request portions of that data or the ability to cache the download and retrieve only the portions not downloaded in cases of a failure. In this case, using a Web server and the HTTP layer exposed through System.Net might be a more appropriate architecture than exposing the data through a Web service or a .NET Remoting object. The transport and encoding semantics associated with HTTP are more amenable to this scenario than those provided by the higher layers.

It’s expected that over time these higher layers will continue to evolve until they are almost always the right choice when you control both the client and the server. However, this transformation will take a significant number of years to achieve. Once we reach that point, System.Net will be most useful for extending and enhancing these higher layers and interacting with legacy services to expose them up through the higher layers.

 

C++ Request and Response Program Example

 

Create a new CLR console application and you can use RequestResponseChap6CP as the project and solution names if you want.

 

C++ Request and Response Program Example - a new CLR console application project creation  

 

Add the following code.

 

// RequestResponseChap6Cp.cpp : main project file.

/// <summary>

/// Demonstrates the use of WebRequest and WebResponse by

/// downloading the contents of a URL and displaying them on the console.

/// </summary>

 

#include "stdafx.h"

 

using namespace System;

using namespace System::IO;

using namespace System::Net;

using namespace System::Text;

 

static void ResolveResource(String^ address)

{

    try

    {

        // Create the request object

        Console::WriteLine("Creating the request object...");

        WebRequest^ request = WebRequest::Create(address);

        Console::WriteLine("Create() is OK...");

 

        // Issue the request

        Console::WriteLine("Issuing the request...");

        WebResponse^ response = request->GetResponse();

 

        // Read the content

        Console::WriteLine("Reading the content using StreamReader()...");

        StreamReader^ reader = gcnew StreamReader(response->GetResponseStream(), Encoding::ASCII);

        String^ content = reader->ReadToEnd();

        Console::WriteLine("ReadToEnd() is OK...");

 

        // Display the content to the console

        Console::WriteLine("Displaying the content to the console...\n");

        Console::WriteLine(content);

        Console::WriteLine("WriteLine() is OK...");

 

        // Close the response

        Console::WriteLine("Closing the response..");

        response->Close();

        Console::WriteLine("Close() is OK...");

    }

    catch (WebException^ wex)

    {

        // Display the exception details

        Console::WriteLine("Error: " + wex->Message);

    }

}

 

[STAThread]

int main(array<System::String ^> ^args)

{

    // Validating the input values

    if (args->Length < 1)

    {

        // Console::WriteLine("Usage: {0} URL", Environment::CommandLine);

        Console::WriteLine("Usage: Executable_file_name URI");

        Console::WriteLine("Example: Executable_file_name http://wordpress.org/index.php");

        // If you want to test the local page, make sure the file is there...

        // in this case it is file.htm

        Console::WriteLine("Example: Executable_file_name file://c:\\temp\\MyTestFile.txt");

        // Return to OS

        return 0;

    }

 

    String^ URI = args[0];

    Console::WriteLine("Read content of " + URI);

    ResolveResource(URI);

    return 0;

}

 

Build and run the project. The following are the output samples.

 

C++ Request and Response Program Example - a sample output

 

C++ Request and Response Program Example - a sample output with argument

 

C++ Request and Response Program Example - another sample output with argument

 

C++ Request and Response Program Example - more output sample

 

The following is the sample content of the local text file which this program tries to read. It was created manually.

 

C++ Request and Response Program Example - a sample output, opening the generated text file

 

C++ Request and Response Program Example - a sample output reading the local text file

 

 

 


 

< C# & VB .NET HTTP Protocol Examples | Main | C#, VB .NET & C++ .NET Request-Response Web Examples >