这个类主要是针对WEB请求响应的一个工具类,它封装了WEB请求出来的很多方法,功能非常强大
Code
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Security;
using System.Collections.Specialized;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Net.Cache;
using System.Web;
using System.Reflection;
using System.Web.Compilation;
using System.CodeDom.Compiler;
using System.Configuration;
using mshtml;
using System.DirectoryServices;
namespace CSharpRecipes
{
public class Web
{
private static string GetWebAppPath()
{
// get the path for this app
string path = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
#region Code to make it work in debug
// figure out where the web code is, should be in an adjacent directory
// to the console app code
string cscbWebPath = path;
int index = -1;
// keep backing up directories till we find it
while (!Directory.Exists(cscbWebPath + @"\CSCBWeb"))
{
index = cscbWebPath.LastIndexOf('\\');
if (index == -1)
{
cscbWebPath = "";
break;
}
cscbWebPath = cscbWebPath.Substring(0, index);
}
#endregion
// make sure we have a web path
if (cscbWebPath.Length > 0)
{
// append webdir name
cscbWebPath += @"\CSCBWeb";
}
return cscbWebPath;
}
#region 14.1 Converting an IP Address to a Host Name
public static void ConvertIPToHostName()
{
// use the dns class to resolve from the address to the iphostentry
try
{
IPHostEntry iphost = Dns.GetHostEntry("90.0.0.47");
// HostName property holds the host name
string hostName = iphost.HostName;
// print out name
Console.WriteLine(hostName);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
#endregion
#region 14.2 Converting a Host Name to an IP Address
public static void ConvertingHostNameToIP()
{
// writes "IP Address: 208.201.239.37;IP Address: 208.201.239.36;"
Console.WriteLine(HostName2IP("www.oreilly.com"));
}
public static string HostName2IP(string hostname)
{
// resolve the hostname into an iphost entry using the dns class
IPHostEntry iphost = System.Net.Dns.GetHostEntry(hostname);
// get all of the possible IP addresses for this hostname
IPAddress[] addresses = iphost.AddressList;
// make a text representation of the list
StringBuilder addressList = new StringBuilder();
// get each ip address
foreach (IPAddress address in addresses)
{
// append it to the list
addressList.AppendFormat("IP Address: {0};", address.ToString());
}
return addressList.ToString();
}
#endregion
#region 14.3 Parsing a URI
public static void ParsingURI()
{
Web.ParseUri("http://user:password@localhost:8080/www.abc.com/home%20page.htm?item=1233#stuff");
}
public static void ParseUri(string uriString)
{
try
{
// just use one of the constructors for the System.Net.Uri class
// this will parse it for us.
Uri uri = new Uri(uriString);
// Look at the information we can get at now
StringBuilder uriParts = new StringBuilder();
uriParts.AppendFormat("AbsoluteURI: {0}{1}",
uri.AbsoluteUri,Environment.NewLine);
uriParts.AppendFormat("AbsolutePath: {0}{1}",
uri.AbsolutePath,Environment.NewLine);
uriParts.AppendFormat("Scheme: {0}{1}",
uri.Scheme,Environment.NewLine);
uriParts.AppendFormat("UserInfo: {0}{1}",
uri.UserInfo,Environment.NewLine);
uriParts.AppendFormat("Authority: {0}{1}",
uri.Authority,Environment.NewLine);
uriParts.AppendFormat("DnsSafeHost: {0}{1}",
uri.DnsSafeHost,Environment.NewLine);
uriParts.AppendFormat("Host: {0}{1}",
uri.Host,Environment.NewLine);
uriParts.AppendFormat("HostNameType: {0}{1}",
uri.HostNameType.ToString(),Environment.NewLine);
uriParts.AppendFormat("Port: {0}{1}",uri.Port,Environment.NewLine);
uriParts.AppendFormat("Path: {0}{1}",uri.LocalPath,Environment.NewLine);
uriParts.AppendFormat("QueryString: {0}{1}",uri.Query,Environment.NewLine);
uriParts.AppendFormat("Path and QueryString: {0}{1}",
uri.PathAndQuery,Environment.NewLine);
uriParts.AppendFormat("Fragment: {0}{1}",uri.Fragment,Environment.NewLine);
uriParts.AppendFormat("Original String: {0}{1}",
uri.OriginalString,Environment.NewLine);
uriParts.AppendFormat("Segments: {0}",Environment.NewLine);
for (int i = 0; i < uri.Segments.Length; i++)
uriParts.AppendFormat(" Segment {0}:{1}{2}",
i, uri.Segments[i], Environment.NewLine);
// GetComponents can be used to get commonly used combinations
// of Uri information
uriParts.AppendFormat("GetComponents for specialized combinations: {0}",
Environment.NewLine);
uriParts.AppendFormat("Host and Port (unescaped): {0}{1}",
uri.GetComponents(UriComponents.HostAndPort,
UriFormat.Unescaped),Environment.NewLine);
uriParts.AppendFormat("HttpRequestUrl (unescaped): {0}{1}",
uri.GetComponents(UriComponents.HttpRequestUrl,
UriFormat.Unescaped),Environment.NewLine);
uriParts.AppendFormat("HttpRequestUrl (escaped): {0}{1}",
uri.GetComponents(UriComponents.HttpRequestUrl,
UriFormat.UriEscaped),Environment.NewLine);
uriParts.AppendFormat("HttpRequestUrl (safeunescaped): {0}{1}",
uri.GetComponents(UriComponents.HttpRequestUrl,
UriFormat.SafeUnescaped),Environment.NewLine);
uriParts.AppendFormat("Scheme And Server (unescaped): {0}{1}",
uri.GetComponents(UriComponents.SchemeAndServer,
UriFormat.Unescaped),Environment.NewLine);
uriParts.AppendFormat("SerializationInfo String (unescaped): {0}{1}",
uri.GetComponents(UriComponents.SerializationInfoString,
UriFormat.Unescaped),Environment.NewLine);
uriParts.AppendFormat("StrongAuthority (unescaped): {0}{1}",
uri.GetComponents(UriComponents.StrongAuthority,
UriFormat.Unescaped),Environment.NewLine);
uriParts.AppendFormat("StrongPort (unescaped): {0}{1}",
uri.GetComponents(UriComponents.StrongPort,
UriFormat.Unescaped),Environment.NewLine);
// write out our summary
Console.WriteLine(uriParts.ToString());
}
catch (ArgumentNullException e)
{
// uriString is a null reference (Nothing in Visual Basic).
Console.WriteLine("URI string object is a null reference: {0}", e);
}
catch (UriFormatException e)
{
Console.WriteLine("URI formatting error: {0}", e);
}
}
#endregion
#region 14.4 Forming an Absolute URI
public static void FormingAbsoluteURI()
{
Uri myUri = CreateAndVerifyAbsoluteUri("http://www.oreilly.com",
"hello%20world.htm");
// displays http://www.oreilly.com/hello world.htm
Console.WriteLine(myUri.AbsoluteUri);
}
public static Uri CreateAndVerifyAbsoluteUri(string uriBaseString, string uriRelativeString)
{
try
{
// make the base uri
Uri baseUri = new Uri(uriBaseString,UriKind.Absolute);
// Make the relative Uri
Uri relativeUri = new Uri(uriRelativeString, UriKind.Relative);
// create the full uri by combining the base and relative
Uri absoluteUri = new Uri(baseUri, relativeUri);
// verify we did make an absolute uri
if(absoluteUri.IsAbsoluteUri==false)
throw new UriFormatException(
"Could not form absolute Uri from " +
baseUri.OriginalString + " and " +
relativeUri.OriginalString);
// make sure our original base Uri is a base uri for the new
// absolute Uri
if(baseUri.IsBaseOf(absoluteUri)==false)
throw new UriFormatException(
"Base Uri was invalid for newly formed Absolute Uri: " +
baseUri.OriginalString + " and " +
absoluteUri.OriginalString);
// get the relative uri from the difference between the base
// and the absolute uris
Uri relCheckUri = baseUri.MakeRelativeUri(absoluteUri);
// this new relative uri should equal our previous uri
if(relCheckUri != relativeUri)
throw new UriFormatException(
"Could not make equivalent relative Uri from new Absolute Uri: " +
relCheckUri.OriginalString + " and " +
absoluteUri.OriginalString);
Uri newAbsoluteUri = new Uri(baseUri, relCheckUri);
// check that the new and the original match
if(Uri.Compare(absoluteUri, newAbsoluteUri,
UriComponents.AbsoluteUri, UriFormat.Unescaped,
StringComparison.InvariantCulture) != 0)
{
throw new UriFormatException(
"New Absolute Uri did not equal originally formed Absolute Uri: " +
baseUri.OriginalString + " and " +
absoluteUri.OriginalString);
}
// it's ok, send it
return absoluteUri;
}
catch (ArgumentNullException e)
{
// uriString is a null reference (Nothing in Visual Basic).
Console.WriteLine("URI string object is a null reference: {0}", e);
}
catch (UriFormatException e)
{
Console.WriteLine("URI formatting error: {0}", e);
}
return null;
}
#endregion
#region 14.5 Handling Web Server Errors
public enum ResponseCategories
{
Unknown = 0, // unknown code ( < 100 or > 599)
Informational = 1, // informational codes (100 <= 199)
Success = 2, // success codes (200 <= 299)
Redirected = 3, // redirection code (300 <= 399)
ClientError = 4, // client error code (400 <= 499)
ServerError = 5 // server error code (500 <= 599)
}
public static void HandlingWebServerErrors()
{
HttpWebRequest httpRequest = null;
// get a URI object
Uri uri = new Uri("http://localhost");
// create the initial request
httpRequest = (HttpWebRequest)WebRequest.Create(uri);
HttpWebResponse httpResponse = null;
try
{
httpResponse = (HttpWebResponse)httpRequest.GetResponse();
}
catch (WebException we)
{
Console.WriteLine(we.ToString());
return;
}
switch (VerifyResponse(httpResponse))
{
case ResponseCategories.Unknown:
Console.WriteLine("Unknown");
break;
case ResponseCategories.Informational:
Console.WriteLine("Informational");
break;
case ResponseCategories.Success:
Console.WriteLine("Success");
break;
case ResponseCategories.Redirected:
Console.WriteLine("Redirected");
break;
case ResponseCategories.ClientError:
Console.WriteLine("ClientError");
break;
case ResponseCategories.ServerError:
Console.WriteLine("ServerError");
break;
}
}
public static ResponseCategories VerifyResponse(HttpWebResponse httpResponse)
{
// Just in case there are more success codes defined in the future
// by HttpStatusCode, we will check here for the "success" ranges
// instead of using the HttpStatusCode enum as it overloads some
// values
int statusCode = (int)httpResponse.StatusCode;
if ((statusCode >= 100) && (statusCode <= 199))
{
return ResponseCategories.Informational;
}
else if ((statusCode >= 200) && (statusCode <= 299))
{
return ResponseCategories.Success;
}
else if ((statusCode >= 300) && (statusCode <= 399))
{
return ResponseCategories.Redirected;
}
else if ((statusCode >= 400) && (statusCode <= 499))
{
return ResponseCategories.ClientError;
}
else if ((statusCode >= 500) && (statusCode <= 599))
{
return ResponseCategories.ServerError;
}
return ResponseCategories.Unknown;
}
#endregion
#region 14.6 Communicating with a Web Server
public static void CommunicatingWithWebServer()
{
HttpWebRequest request =
GenerateHttpWebRequest("http://localhost/mysite/index.aspx");
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
// This next line uses VerifyResponse from Recipe 14.5
if (VerifyResponse(response) == ResponseCategories.Success)
{
Console.WriteLine("Request succeeded");
}
}
}
// GET overload
public static HttpWebRequest GenerateHttpWebRequest(string uriString)
{
// get a URI object
Uri uri = new Uri(uriString);
// create the initial request
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(uri);
// return the request
return httpRequest;
}
// POST overload
public static HttpWebRequest GenerateHttpWebRequest(string uriString,
string postData,
string contentType)
{
// get a URI object
Uri uri = new Uri(uriString);
// create the initial request
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(uri);
// Get the bytes for the request, should be pre-escaped
byte[] bytes = Encoding.UTF8.GetBytes(postData);
// Set the content type of the data being posted.
httpRequest.ContentType = contentType;
//"application/x-www-form-urlencoded"; for forms
// Set the content length of the string being posted.
httpRequest.ContentLength = postData.Length;
// Get the request stream and write the post data in
using (Stream requestStream = httpRequest.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
}
// return the request
return httpRequest;
}
#endregion
#region 14.7 Going Through a Proxy
public static void GoingThroughProxy()
{
HttpWebRequest request =
GenerateHttpWebRequest("http://internethost/mysite/index.aspx");
// add the proxy info
AddProxyInfoToRequest(request, "http://webproxy:80", "user", "pwd", "domain");
// or set it up to go through the same proxy for all responses
Uri proxyURI = new Uri("http://webproxy:80");
// in 1.1 you used to do this:
//GlobalProxySelection.Select = new WebProxy(proxyURI);
// Now in 2.0 you do this:
WebRequest.DefaultWebProxy = new WebProxy(proxyURI);
}
public static HttpWebRequest AddProxyInfoToRequest(HttpWebRequest httpRequest,
string proxyUri,
string proxyID,
string proxyPwd,
string proxyDomain)
{
if (httpRequest != null)
{
// create the proxy object
WebProxy proxyInfo = new WebProxy();
// add the address of the proxy server to use
proxyInfo.Address = new Uri(proxyUri);
// tell it to bypass the proxy server for local addresses
proxyInfo.BypassProxyOnLocal = true;
// add any credential information to present to the proxy server
proxyInfo.Credentials = new NetworkCredential(proxyID,
proxyPwd,
proxyDomain);
// assign the proxy information to the request
httpRequest.Proxy = proxyInfo;
}
// return the request
return httpRequest;
}
#endregion
#region 14.8 Obtaining the HTML from a URL
public static void ObtainingHTMLFromURL()
{
try
{
string html = GetHtmlFromUrl("http://www.oreilly.com");
}
catch (WebException e)
{
Console.WriteLine(e);
}
}
public static string GetHtmlFromUrl(string url)
{
if (string.IsNullOrEmpty(url))
throw new ArgumentNullException("url","Parameter is null or empty");
string html = "";
HttpWebRequest request = GenerateHttpWebRequest(url);
using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
if (VerifyResponse(response) == ResponseCategories.Success)
{
// get the response stream.
Stream responseStream = response.GetResponseStream();
// use a stream reader that understands UTF8
using(StreamReader reader = new StreamReader(responseStream, Encoding.UTF8))
{
html = reader.ReadToEnd();
}
}
}
return html;
}
#endregion
#region "14.9 Using the new web browser control"
// See the WebBrowser project
#endregion
#region "14.10 Tying your database code to the cache"
// See the CSCBWeb project for this code
#endregion
#region "14.11 Caching data with multiple dependencies"
// See the CSCBWeb project for this code
#endregion
#region "14.12 Pre-building an ASP.NET web site programmatically"
public class MyClientBuildManagerCallback : ClientBuildManagerCallback
{
public MyClientBuildManagerCallback()
: base()
{
}
public override void ReportCompilerError(CompilerError error)
{
string msg = "Report Compiler Error: " + error.ToString();
Debug.WriteLine(msg);
Console.WriteLine(msg);
}
public override void ReportParseError(ParserError error)
{
string msg = "Report Parse Error: " + error.ToString();
Debug.WriteLine(msg);
Console.WriteLine(msg);
}
public override void ReportProgress(string message)
{
string msg = "Report Progress: " + message;
Debug.WriteLine(msg);
Console.WriteLine(msg);
}
}
public static void TestBuildASPNETPages()
{
try
{
// get the path to the web app shipping with this code
string cscbWebPath = GetWebAppPath();
// make sure we have a web path
if(cscbWebPath.Length>0)
{
string appVirtualDir = @"CSCBWeb";
string appPhysicalSourceDir = cscbWebPath;
// make the target an adjacent directory as it cannot be in the same tree
// or the buildmanager screams
string appPhysicalTargetDir = Path.GetDirectoryName(cscbWebPath) + @"\BuildCSCB";
// check flags again in Beta2, more options
//AllowPartiallyTrustedCallers
//Clean
//CodeAnalysis
//Default
//DelaySign
//FixedNames
//ForceDebug
//OverwriteTarget
//Updatable
// Report Progress: Building directory '/CSCBWeb/App_Data'.
//Report Progress: Building directory '/CSCBWeb/Role_Database'.
//Report Progress: Building directory '/CSCBWeb'.
//Report Compiler Error: c:\PRJ32\Book_2_0\C#Cookbook2\Code\CSCBWeb\Default.aspx.cs(14,7) : warning CS0105: The using directive for 'System.Configuration' appeared previously in this namespace
// Report Progress: Building directory '/CSCBWeb/App_Data'.
//Report Progress: Building directory '/CSCBWeb/Role_Database'.
//Report Progress: Building directory '/CSCBWeb'.
PrecompilationFlags flags = PrecompilationFlags.ForceDebug |
PrecompilationFlags.OverwriteTarget;
ClientBuildManagerParameter cbmp = new ClientBuildManagerParameter();
cbmp.PrecompilationFlags = flags;
ClientBuildManager cbm =
new ClientBuildManager(appVirtualDir,
appPhysicalSourceDir,
appPhysicalTargetDir,
cbmp);
MyClientBuildManagerCallback myCallback = new MyClientBuildManagerCallback();
cbm.PrecompileApplication(myCallback);
}
}
catch (Exception e)
{
Debug.WriteLine(e.ToString());
}
}
#endregion
#region "14.13 Escaping and Unescaping data for the web"
public static void TestEscapeUnescape()
{
string data = "
Console.WriteLine("Original Data: {0}",data);
Console.WriteLine();
// public static string EscapeDataString(string stringToEscape);
string escapedData = Uri.EscapeDataString(data);
Console.WriteLine("escaped Data: {0}",escapedData);
Console.WriteLine();
// public static string UnescapeDataString( string stringToUnescape);
string unescapedData = Uri.UnescapeDataString(escapedData);
Console.WriteLine("unescaped Data: {0}",data);
Console.WriteLine();
string uriString = "http://user:password@localhost:8080/www.abc.com/" +
"home page.htm?item=1233;html=
Console.WriteLine("Original Uri string: {0}",uriString);
Console.WriteLine();
// public static string EscapeUriString(string stringToEscape);
string escapedUriString = Uri.EscapeUriString(uriString);
Console.WriteLine("Escaped Uri string: {0}",escapedUriString);
Console.WriteLine();
// Why not just use EscapeDataString to escape a Uri? It's not picky enough
string escapedUriData = Uri.EscapeDataString(uriString);
Console.WriteLine("Escaped Uri data: {0}",escapedUriData);
Console.WriteLine();
Console.WriteLine(Uri.UnescapeDataString(escapedUriString));
}
#endregion
#region "14.14 Bulletproof creating a Uri"
public class UriBuilderFix : UriBuilder
{
public UriBuilderFix() : base()
{
}
public new string Query
{
get
{
return base.Query;
}
set
{
if (!string.IsNullOrEmpty(value))
{
if (value[0] == '?')
// trim off the leading ? as the underlying
// UriBuilder class will add one to the
// querystring. Also prepend ; for additional items
base.Query = value.Substring(1);
else
base.Query = value;
}
else
base.Query = string.Empty;
}
}
}
public static void TestUriBuilder()
{
//string uriString = "http://user:password@localhost:8080/www.abc.com/" +
// "home page.htm?item=1233;html=
//[scheme]://[user]:[password]@[host/authority]:[port]/[path];[params]?
//[query string]#[fragment]
try
{
UriBuilderFix ubf = new UriBuilderFix();
ubf.Scheme = "http";
ubf.UserName = "user";
ubf.Password = "password";
ubf.Host = "localhost";
ubf.Port = 8080;
ubf.Path = "www.abc.com/home page.htm";
//The Query property contains any query information included in the URI.
//Query information is separated from the path information by a question mark (?) and continues
//to the end of the URI. The query information returned includes the leading question mark.
//The query information is escaped according to RFC 2396.
//Setting the Query property to null or to System.String.Empty clears the property.
//Note: Do not append a string directly to this property.
//Instead retrieve the property value as a string, remove the leading question mark,
//append the new query string, and set the property with the combined string.
// Don't Do This, too many ? marks, one for every append
ubf.Query = "item=1233";
ubf.Query += ";html=
ubf.Fragment = "stuff";
Console.WriteLine("Absolute Composed Uri: " + ubf.Uri.AbsoluteUri);
Console.WriteLine("Composed Uri: " + ubf.ToString());
UriBuilder ub = new UriBuilder();
ub.Query = "item=1233";
ub.Query += ";html=
}
catch (Exception e)
{
Console.WriteLine("Exception thrown building Uri: " + e.ToString());
}
}
#endregion
#region "14.15 Inspect and change your web application configuration (System.Web.Configuration)"
// see the CSCBWeb project for code
#endregion
#region "14.16 Working with HTML"
public static void TestHTMLParser()
{
HTMLDocument htmlDoc = new HTMLDocument();
IHTMLDocument2 iHtmlDoc2 = null;
string html =
""-//W3C//DTD XHTML 1.1//EN\"" +
"\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">" +
""http://www.w3.org/1999/xhtml\" >" +
"Test Page " +
"";
// get the IHTMLDocument2 interface
iHtmlDoc2 = (IHTMLDocument2)htmlDoc;
// Put the document in design mode so we don't execute scripts
// while loading
iHtmlDoc2.designMode = "On";
// Have to put some HTML in the DOM before using it
iHtmlDoc2.write(html);
// close it
iHtmlDoc2.close();
//roll over every element in the html
foreach (IHTMLElement htmlElem in (IHTMLElementCollection)iHtmlDoc2.body.all)
{
// Note: every time we do the is and as, it does a COM call to the
// MSHTML object. This can be rather expensive so you would want to cache
// the results elsewhere once you have them, don't just keep calling
// properties on it as those end up making a round trip as well.
if (htmlElem is IHTMLAnchorElement)
{
HTMLAnchorElementClass anchor = htmlElem as HTMLAnchorElementClass;
if (anchor != null)
Console.WriteLine("Anchor element found: " + anchor.href);
continue;
}
else if (htmlElem is IHTMLFormElement)
{
HTMLFormElementClass form = htmlElem as HTMLFormElementClass;
if (form != null)
Console.WriteLine("Form element found: " + form.id);
continue;
}
else if (htmlElem is IHTMLInputElement)
{
HTMLInputElementClass input = htmlElem as HTMLInputElementClass;
if (input != null)
Console.WriteLine("Input Element found: " + input.name);
continue;
}
else if (htmlElem is IHTMLTextAreaElement)
{
HTMLTextAreaElementClass text = htmlElem as HTMLTextAreaElementClass;
if (text != null)
Console.WriteLine("Text Area Element found: " + text.name);
continue;
}
}
}
#endregion
#region "14.17 Using cached results when working with HTTP for faster performance"
public static void TestCache()
{
// 14.6 has generategetorpostrequest
string html = "";
string url = "http://www.oreilly.com";
// set up the request
HttpWebRequest request = GenerateHttpWebRequest(url);
// make a cache policy to use cached results if available
// the default is to Bypass the cache in machine.config.
RequestCachePolicy rcpCheckCache =
new RequestCachePolicy(RequestCacheLevel.CacheIfAvailable);
// assign the new policy to the request
request.CachePolicy = rcpCheckCache;
// execute the request
HttpWebResponse response = null;
try
{
response = (HttpWebResponse)request.GetResponse();
// check if we hit the cache
if(response.IsFromCache==false)
{
Console.WriteLine("Didn't hit the cache");
}
// get the response stream.
Stream responseStream = response.GetResponseStream();
// use a stream reader that understands UTF8
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
try
{
html = reader.ReadToEnd();
}
finally
{
// close the reader
reader.Close();
}
Console.WriteLine("Html retrieved: " + html);
}
catch (WebException we)
{
Console.WriteLine(we.ToString());
}
}
#endregion
#region "14.18 Checking out a web server's custom error pages
public static void GetCustomErrorPageLocations()
{
// MetaEdit can be gotten here: http://support.microsoft.com/kb/q232068/
// Find metabase properties here
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/iissdk/html/4930f687-3a39-4f7d-9bc7-56dbb013d2b5.asp
// Sometimes the COM world is a rough place
UInt32 E_RPC_SERVER_UNAVAILABLE = 0x800706BA;
try
{
// This is a case sensitive entry in the metabase
// You'd think it was misspelled but you would be mistaken
const string WebServerSchema = "IIsWebServer";
// set up to talk to the local IIS server
string server = "localhost";
// Create a dictionary entry for the IIS server with a fake
// user and password. Credentials would have to be provided
// if you are running as a regular user
using (DirectoryEntry w3svc =
new DirectoryEntry(
string.Format("IIS://{0}/w3svc", server),
"Domain/UserCode", "Password"))
{
// can't talk to the metabase for some reason, bail
if (w3svc != null)
{
foreach (DirectoryEntry site in w3svc.Children)
{
if (site != null)
{
using (site)
{
// check all web servers on this box
if (site.SchemaClassName == WebServerSchema)
{
// get the metabase entry for this server
string metabaseDir =
string.Format("/w3svc/{0}/ROOT", site.Name);
if (site.Children != null)
{
// find the ROOT directory for each server
foreach (DirectoryEntry root in site.Children)
{
using (root)
{
// did we find the root dir for this site?
if (root != null &&
root.Name.Equals("ROOT",
StringComparison.OrdinalIgnoreCase))
{
// get the HttpErrors
if (root.Properties.Contains("HttpErrors") == true)
{
// write them out
PropertyValueCollection httpErrors = root.Properties["HttpErrors"];
if (httpErrors != null)
{
for (int i = 0; i < httpErrors.Count; i++)
{
//400,*,FILE,C:\WINDOWS\help\iisHelp\common\400.htm
string[] errorParts = httpErrors[i].ToString().Split(',');
Console.WriteLine("Error Mapping Entry:");
Console.WriteLine("\tHTTP error code: {0}", errorParts[0]);
Console.WriteLine("\tHTTP sub-error code: {0}", errorParts[1]);
Console.WriteLine("\tMessage Type: {0}", errorParts[2]);
Console.WriteLine("\tPath to error HTML file: {0}", errorParts[3]);
}
}
}
}
}
}
}
}
}
}
}
}
}
}
catch (COMException e)
{
// apparently it won't talk to us right now
// this could be set up in a loop to retry.
if (e.ErrorCode != (Int32)E_RPC_SERVER_UNAVAILABLE)
{
throw;
}
}
}
#endregion
#region "14.19 Determining the application mappings for ASP.NET set up on IIS
public static void DumpASPNETAppMappings()
{
// MetaEdit can be gotten here: http://support.microsoft.com/kb/q232068/
// Find metabase properties here
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/iissdk/html/4930f687-3a39-4f7d-9bc7-56dbb013d2b5.asp
// Sometimes the COM world is a rough place
UInt32 E_RPC_SERVER_UNAVAILABLE = 0x800706BA;
try
{
// This is a case sensitive entry in the metabase
// You'd think it was misspelled but you would be mistaken
const string WebServerSchema = "IIsWebServer";
// set up to talk to the local IIS server
string server = "localhost";
// Create a dictionary entry for the IIS server with a fake
// user and password. Credentials would have to be provided
// if you are running as a regular user
using (DirectoryEntry w3svc = new DirectoryEntry(string.Format("IIS://{0}/w3svc", server), "Domain/UserCode", "Password"))
{
// can't talk to the metabase for some reason, bail
if (w3svc != null)
{
foreach (DirectoryEntry site in w3svc.Children)
{
using (site)
{
if (site != null)
{
// check all web servers on this box
if (site.SchemaClassName == WebServerSchema)
{
// get the metabase entry for this server
string metabaseDir =
string.Format("/w3svc/{0}/ROOT", site.Name);
if (site.Children != null)
{
// find the ROOT directory for each server
foreach (DirectoryEntry root in site.Children)
{
using (root)
{
// did we find the root dir for this site?
if (root != null &&
root.Name.Equals("ROOT", StringComparison.OrdinalIgnoreCase))
{
// get the Application Mappings in the ScriptMaps property
if (root.Properties.Contains("ScriptMaps") == true)
{
// write them out
PropertyValueCollection scriptMaps = root.Properties["ScriptMaps"];
if (scriptMaps != null)
{
for (int i = 0; i < scriptMaps.Count; i++)
{
//.aspx,C:\WINDOWS\Microsoft.NET\Framework\v2.0.50110\aspnet_isapi.dll,1,GET,HEAD,POST,DEBUG
string[] mappingParts = scriptMaps[i].ToString().Split(',');
// The ASP.NET redirector is implemented in the
// aspnet_isapi.dll file so any extensions mapped to it
// will be processed by asp.net
if (mappingParts[1].ToUpper().IndexOf("ASPNET_ISAPI") != -1)
{
// write out details for the ASP.NET mappings
Console.WriteLine("Extension Mappings:");
Console.WriteLine("\tMapped Extension: {0}", mappingParts[0]);
Console.WriteLine("\tHandler: {0}", mappingParts[1]);
for (int j = 3; j < mappingParts.Length; j++)
Console.WriteLine("\tHTTP VERB: {0}", mappingParts[j]);
}
else
{
// write out those unmapped items
Console.WriteLine("Skipping {0} as it is not processed by ASP.NET", mappingParts[0]);
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
catch (COMException e)
{
// apparently it won't talk to us right now
// this could be set up in a loop to retry.
if (e.ErrorCode != (Int32)E_RPC_SERVER_UNAVAILABLE)
{
throw;
}
}
}
#endregion
}
}
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Security;
using System.Collections.Specialized;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Net.Cache;
using System.Web;
using System.Reflection;
using System.Web.Compilation;
using System.CodeDom.Compiler;
using System.Configuration;
using mshtml;
using System.DirectoryServices;
namespace CSharpRecipes
{
public class Web
{
private static string GetWebAppPath()
{
// get the path for this app
string path = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
#region Code to make it work in debug
// figure out where the web code is, should be in an adjacent directory
// to the console app code
string cscbWebPath = path;
int index = -1;
// keep backing up directories till we find it
while (!Directory.Exists(cscbWebPath + @"\CSCBWeb"))
{
index = cscbWebPath.LastIndexOf('\\');
if (index == -1)
{
cscbWebPath = "";
break;
}
cscbWebPath = cscbWebPath.Substring(0, index);
}
#endregion
// make sure we have a web path
if (cscbWebPath.Length > 0)
{
// append webdir name
cscbWebPath += @"\CSCBWeb";
}
return cscbWebPath;
}
#region 14.1 Converting an IP Address to a Host Name
public static void ConvertIPToHostName()
{
// use the dns class to resolve from the address to the iphostentry
try
{
IPHostEntry iphost = Dns.GetHostEntry("90.0.0.47");
// HostName property holds the host name
string hostName = iphost.HostName;
// print out name
Console.WriteLine(hostName);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
#endregion
#region 14.2 Converting a Host Name to an IP Address
public static void ConvertingHostNameToIP()
{
// writes "IP Address: 208.201.239.37;IP Address: 208.201.239.36;"
Console.WriteLine(HostName2IP("www.oreilly.com"));
}
public static string HostName2IP(string hostname)
{
// resolve the hostname into an iphost entry using the dns class
IPHostEntry iphost = System.Net.Dns.GetHostEntry(hostname);
// get all of the possible IP addresses for this hostname
IPAddress[] addresses = iphost.AddressList;
// make a text representation of the list
StringBuilder addressList = new StringBuilder();
// get each ip address
foreach (IPAddress address in addresses)
{
// append it to the list
addressList.AppendFormat("IP Address: {0};", address.ToString());
}
return addressList.ToString();
}
#endregion
#region 14.3 Parsing a URI
public static void ParsingURI()
{
Web.ParseUri("http://user:password@localhost:8080/www.abc.com/home%20page.htm?item=1233#stuff");
}
public static void ParseUri(string uriString)
{
try
{
// just use one of the constructors for the System.Net.Uri class
// this will parse it for us.
Uri uri = new Uri(uriString);
// Look at the information we can get at now
StringBuilder uriParts = new StringBuilder();
uriParts.AppendFormat("AbsoluteURI: {0}{1}",
uri.AbsoluteUri,Environment.NewLine);
uriParts.AppendFormat("AbsolutePath: {0}{1}",
uri.AbsolutePath,Environment.NewLine);
uriParts.AppendFormat("Scheme: {0}{1}",
uri.Scheme,Environment.NewLine);
uriParts.AppendFormat("UserInfo: {0}{1}",
uri.UserInfo,Environment.NewLine);
uriParts.AppendFormat("Authority: {0}{1}",
uri.Authority,Environment.NewLine);
uriParts.AppendFormat("DnsSafeHost: {0}{1}",
uri.DnsSafeHost,Environment.NewLine);
uriParts.AppendFormat("Host: {0}{1}",
uri.Host,Environment.NewLine);
uriParts.AppendFormat("HostNameType: {0}{1}",
uri.HostNameType.ToString(),Environment.NewLine);
uriParts.AppendFormat("Port: {0}{1}",uri.Port,Environment.NewLine);
uriParts.AppendFormat("Path: {0}{1}",uri.LocalPath,Environment.NewLine);
uriParts.AppendFormat("QueryString: {0}{1}",uri.Query,Environment.NewLine);
uriParts.AppendFormat("Path and QueryString: {0}{1}",
uri.PathAndQuery,Environment.NewLine);
uriParts.AppendFormat("Fragment: {0}{1}",uri.Fragment,Environment.NewLine);
uriParts.AppendFormat("Original String: {0}{1}",
uri.OriginalString,Environment.NewLine);
uriParts.AppendFormat("Segments: {0}",Environment.NewLine);
for (int i = 0; i < uri.Segments.Length; i++)
uriParts.AppendFormat(" Segment {0}:{1}{2}",
i, uri.Segments[i], Environment.NewLine);
// GetComponents can be used to get commonly used combinations
// of Uri information
uriParts.AppendFormat("GetComponents for specialized combinations: {0}",
Environment.NewLine);
uriParts.AppendFormat("Host and Port (unescaped): {0}{1}",
uri.GetComponents(UriComponents.HostAndPort,
UriFormat.Unescaped),Environment.NewLine);
uriParts.AppendFormat("HttpRequestUrl (unescaped): {0}{1}",
uri.GetComponents(UriComponents.HttpRequestUrl,
UriFormat.Unescaped),Environment.NewLine);
uriParts.AppendFormat("HttpRequestUrl (escaped): {0}{1}",
uri.GetComponents(UriComponents.HttpRequestUrl,
UriFormat.UriEscaped),Environment.NewLine);
uriParts.AppendFormat("HttpRequestUrl (safeunescaped): {0}{1}",
uri.GetComponents(UriComponents.HttpRequestUrl,
UriFormat.SafeUnescaped),Environment.NewLine);
uriParts.AppendFormat("Scheme And Server (unescaped): {0}{1}",
uri.GetComponents(UriComponents.SchemeAndServer,
UriFormat.Unescaped),Environment.NewLine);
uriParts.AppendFormat("SerializationInfo String (unescaped): {0}{1}",
uri.GetComponents(UriComponents.SerializationInfoString,
UriFormat.Unescaped),Environment.NewLine);
uriParts.AppendFormat("StrongAuthority (unescaped): {0}{1}",
uri.GetComponents(UriComponents.StrongAuthority,
UriFormat.Unescaped),Environment.NewLine);
uriParts.AppendFormat("StrongPort (unescaped): {0}{1}",
uri.GetComponents(UriComponents.StrongPort,
UriFormat.Unescaped),Environment.NewLine);
// write out our summary
Console.WriteLine(uriParts.ToString());
}
catch (ArgumentNullException e)
{
// uriString is a null reference (Nothing in Visual Basic).
Console.WriteLine("URI string object is a null reference: {0}", e);
}
catch (UriFormatException e)
{
Console.WriteLine("URI formatting error: {0}", e);
}
}
#endregion
#region 14.4 Forming an Absolute URI
public static void FormingAbsoluteURI()
{
Uri myUri = CreateAndVerifyAbsoluteUri("http://www.oreilly.com",
"hello%20world.htm");
// displays http://www.oreilly.com/hello world.htm
Console.WriteLine(myUri.AbsoluteUri);
}
public static Uri CreateAndVerifyAbsoluteUri(string uriBaseString, string uriRelativeString)
{
try
{
// make the base uri
Uri baseUri = new Uri(uriBaseString,UriKind.Absolute);
// Make the relative Uri
Uri relativeUri = new Uri(uriRelativeString, UriKind.Relative);
// create the full uri by combining the base and relative
Uri absoluteUri = new Uri(baseUri, relativeUri);
// verify we did make an absolute uri
if(absoluteUri.IsAbsoluteUri==false)
throw new UriFormatException(
"Could not form absolute Uri from " +
baseUri.OriginalString + " and " +
relativeUri.OriginalString);
// make sure our original base Uri is a base uri for the new
// absolute Uri
if(baseUri.IsBaseOf(absoluteUri)==false)
throw new UriFormatException(
"Base Uri was invalid for newly formed Absolute Uri: " +
baseUri.OriginalString + " and " +
absoluteUri.OriginalString);
// get the relative uri from the difference between the base
// and the absolute uris
Uri relCheckUri = baseUri.MakeRelativeUri(absoluteUri);
// this new relative uri should equal our previous uri
if(relCheckUri != relativeUri)
throw new UriFormatException(
"Could not make equivalent relative Uri from new Absolute Uri: " +
relCheckUri.OriginalString + " and " +
absoluteUri.OriginalString);
Uri newAbsoluteUri = new Uri(baseUri, relCheckUri);
// check that the new and the original match
if(Uri.Compare(absoluteUri, newAbsoluteUri,
UriComponents.AbsoluteUri, UriFormat.Unescaped,
StringComparison.InvariantCulture) != 0)
{
throw new UriFormatException(
"New Absolute Uri did not equal originally formed Absolute Uri: " +
baseUri.OriginalString + " and " +
absoluteUri.OriginalString);
}
// it's ok, send it
return absoluteUri;
}
catch (ArgumentNullException e)
{
// uriString is a null reference (Nothing in Visual Basic).
Console.WriteLine("URI string object is a null reference: {0}", e);
}
catch (UriFormatException e)
{
Console.WriteLine("URI formatting error: {0}", e);
}
return null;
}
#endregion
#region 14.5 Handling Web Server Errors
public enum ResponseCategories
{
Unknown = 0, // unknown code ( < 100 or > 599)
Informational = 1, // informational codes (100 <= 199)
Success = 2, // success codes (200 <= 299)
Redirected = 3, // redirection code (300 <= 399)
ClientError = 4, // client error code (400 <= 499)
ServerError = 5 // server error code (500 <= 599)
}
public static void HandlingWebServerErrors()
{
HttpWebRequest httpRequest = null;
// get a URI object
Uri uri = new Uri("http://localhost");
// create the initial request
httpRequest = (HttpWebRequest)WebRequest.Create(uri);
HttpWebResponse httpResponse = null;
try
{
httpResponse = (HttpWebResponse)httpRequest.GetResponse();
}
catch (WebException we)
{
Console.WriteLine(we.ToString());
return;
}
switch (VerifyResponse(httpResponse))
{
case ResponseCategories.Unknown:
Console.WriteLine("Unknown");
break;
case ResponseCategories.Informational:
Console.WriteLine("Informational");
break;
case ResponseCategories.Success:
Console.WriteLine("Success");
break;
case ResponseCategories.Redirected:
Console.WriteLine("Redirected");
break;
case ResponseCategories.ClientError:
Console.WriteLine("ClientError");
break;
case ResponseCategories.ServerError:
Console.WriteLine("ServerError");
break;
}
}
public static ResponseCategories VerifyResponse(HttpWebResponse httpResponse)
{
// Just in case there are more success codes defined in the future
// by HttpStatusCode, we will check here for the "success" ranges
// instead of using the HttpStatusCode enum as it overloads some
// values
int statusCode = (int)httpResponse.StatusCode;
if ((statusCode >= 100) && (statusCode <= 199))
{
return ResponseCategories.Informational;
}
else if ((statusCode >= 200) && (statusCode <= 299))
{
return ResponseCategories.Success;
}
else if ((statusCode >= 300) && (statusCode <= 399))
{
return ResponseCategories.Redirected;
}
else if ((statusCode >= 400) && (statusCode <= 499))
{
return ResponseCategories.ClientError;
}
else if ((statusCode >= 500) && (statusCode <= 599))
{
return ResponseCategories.ServerError;
}
return ResponseCategories.Unknown;
}
#endregion
#region 14.6 Communicating with a Web Server
public static void CommunicatingWithWebServer()
{
HttpWebRequest request =
GenerateHttpWebRequest("http://localhost/mysite/index.aspx");
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
// This next line uses VerifyResponse from Recipe 14.5
if (VerifyResponse(response) == ResponseCategories.Success)
{
Console.WriteLine("Request succeeded");
}
}
}
// GET overload
public static HttpWebRequest GenerateHttpWebRequest(string uriString)
{
// get a URI object
Uri uri = new Uri(uriString);
// create the initial request
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(uri);
// return the request
return httpRequest;
}
// POST overload
public static HttpWebRequest GenerateHttpWebRequest(string uriString,
string postData,
string contentType)
{
// get a URI object
Uri uri = new Uri(uriString);
// create the initial request
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(uri);
// Get the bytes for the request, should be pre-escaped
byte[] bytes = Encoding.UTF8.GetBytes(postData);
// Set the content type of the data being posted.
httpRequest.ContentType = contentType;
//"application/x-www-form-urlencoded"; for forms
// Set the content length of the string being posted.
httpRequest.ContentLength = postData.Length;
// Get the request stream and write the post data in
using (Stream requestStream = httpRequest.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
}
// return the request
return httpRequest;
}
#endregion
#region 14.7 Going Through a Proxy
public static void GoingThroughProxy()
{
HttpWebRequest request =
GenerateHttpWebRequest("http://internethost/mysite/index.aspx");
// add the proxy info
AddProxyInfoToRequest(request, "http://webproxy:80", "user", "pwd", "domain");
// or set it up to go through the same proxy for all responses
Uri proxyURI = new Uri("http://webproxy:80");
// in 1.1 you used to do this:
//GlobalProxySelection.Select = new WebProxy(proxyURI);
// Now in 2.0 you do this:
WebRequest.DefaultWebProxy = new WebProxy(proxyURI);
}
public static HttpWebRequest AddProxyInfoToRequest(HttpWebRequest httpRequest,
string proxyUri,
string proxyID,
string proxyPwd,
string proxyDomain)
{
if (httpRequest != null)
{
// create the proxy object
WebProxy proxyInfo = new WebProxy();
// add the address of the proxy server to use
proxyInfo.Address = new Uri(proxyUri);
// tell it to bypass the proxy server for local addresses
proxyInfo.BypassProxyOnLocal = true;
// add any credential information to present to the proxy server
proxyInfo.Credentials = new NetworkCredential(proxyID,
proxyPwd,
proxyDomain);
// assign the proxy information to the request
httpRequest.Proxy = proxyInfo;
}
// return the request
return httpRequest;
}
#endregion
#region 14.8 Obtaining the HTML from a URL
public static void ObtainingHTMLFromURL()
{
try
{
string html = GetHtmlFromUrl("http://www.oreilly.com");
}
catch (WebException e)
{
Console.WriteLine(e);
}
}
public static string GetHtmlFromUrl(string url)
{
if (string.IsNullOrEmpty(url))
throw new ArgumentNullException("url","Parameter is null or empty");
string html = "";
HttpWebRequest request = GenerateHttpWebRequest(url);
using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
if (VerifyResponse(response) == ResponseCategories.Success)
{
// get the response stream.
Stream responseStream = response.GetResponseStream();
// use a stream reader that understands UTF8
using(StreamReader reader = new StreamReader(responseStream, Encoding.UTF8))
{
html = reader.ReadToEnd();
}
}
}
return html;
}
#endregion
#region "14.9 Using the new web browser control"
// See the WebBrowser project
#endregion
#region "14.10 Tying your database code to the cache"
// See the CSCBWeb project for this code
#endregion
#region "14.11 Caching data with multiple dependencies"
// See the CSCBWeb project for this code
#endregion
#region "14.12 Pre-building an ASP.NET web site programmatically"
public class MyClientBuildManagerCallback : ClientBuildManagerCallback
{
public MyClientBuildManagerCallback()
: base()
{
}
public override void ReportCompilerError(CompilerError error)
{
string msg = "Report Compiler Error: " + error.ToString();
Debug.WriteLine(msg);
Console.WriteLine(msg);
}
public override void ReportParseError(ParserError error)
{
string msg = "Report Parse Error: " + error.ToString();
Debug.WriteLine(msg);
Console.WriteLine(msg);
}
public override void ReportProgress(string message)
{
string msg = "Report Progress: " + message;
Debug.WriteLine(msg);
Console.WriteLine(msg);
}
}
public static void TestBuildASPNETPages()
{
try
{
// get the path to the web app shipping with this code
string cscbWebPath = GetWebAppPath();
// make sure we have a web path
if(cscbWebPath.Length>0)
{
string appVirtualDir = @"CSCBWeb";
string appPhysicalSourceDir = cscbWebPath;
// make the target an adjacent directory as it cannot be in the same tree
// or the buildmanager screams
string appPhysicalTargetDir = Path.GetDirectoryName(cscbWebPath) + @"\BuildCSCB";
// check flags again in Beta2, more options
//AllowPartiallyTrustedCallers
//Clean
//CodeAnalysis
//Default
//DelaySign
//FixedNames
//ForceDebug
//OverwriteTarget
//Updatable
// Report Progress: Building directory '/CSCBWeb/App_Data'.
//Report Progress: Building directory '/CSCBWeb/Role_Database'.
//Report Progress: Building directory '/CSCBWeb'.
//Report Compiler Error: c:\PRJ32\Book_2_0\C#Cookbook2\Code\CSCBWeb\Default.aspx.cs(14,7) : warning CS0105: The using directive for 'System.Configuration' appeared previously in this namespace
// Report Progress: Building directory '/CSCBWeb/App_Data'.
//Report Progress: Building directory '/CSCBWeb/Role_Database'.
//Report Progress: Building directory '/CSCBWeb'.
PrecompilationFlags flags = PrecompilationFlags.ForceDebug |
PrecompilationFlags.OverwriteTarget;
ClientBuildManagerParameter cbmp = new ClientBuildManagerParameter();
cbmp.PrecompilationFlags = flags;
ClientBuildManager cbm =
new ClientBuildManager(appVirtualDir,
appPhysicalSourceDir,
appPhysicalTargetDir,
cbmp);
MyClientBuildManagerCallback myCallback = new MyClientBuildManagerCallback();
cbm.PrecompileApplication(myCallback);
}
}
catch (Exception e)
{
Debug.WriteLine(e.ToString());
}
}
#endregion
#region "14.13 Escaping and Unescaping data for the web"
public static void TestEscapeUnescape()
{
string data = "
My html
";Console.WriteLine("Original Data: {0}",data);
Console.WriteLine();
// public static string EscapeDataString(string stringToEscape);
string escapedData = Uri.EscapeDataString(data);
Console.WriteLine("escaped Data: {0}",escapedData);
Console.WriteLine();
// public static string UnescapeDataString( string stringToUnescape);
string unescapedData = Uri.UnescapeDataString(escapedData);
Console.WriteLine("unescaped Data: {0}",data);
Console.WriteLine();
string uriString = "http://user:password@localhost:8080/www.abc.com/" +
"home page.htm?item=1233;html=
Heading
#stuff";Console.WriteLine("Original Uri string: {0}",uriString);
Console.WriteLine();
// public static string EscapeUriString(string stringToEscape);
string escapedUriString = Uri.EscapeUriString(uriString);
Console.WriteLine("Escaped Uri string: {0}",escapedUriString);
Console.WriteLine();
// Why not just use EscapeDataString to escape a Uri? It's not picky enough
string escapedUriData = Uri.EscapeDataString(uriString);
Console.WriteLine("Escaped Uri data: {0}",escapedUriData);
Console.WriteLine();
Console.WriteLine(Uri.UnescapeDataString(escapedUriString));
}
#endregion
#region "14.14 Bulletproof creating a Uri"
public class UriBuilderFix : UriBuilder
{
public UriBuilderFix() : base()
{
}
public new string Query
{
get
{
return base.Query;
}
set
{
if (!string.IsNullOrEmpty(value))
{
if (value[0] == '?')
// trim off the leading ? as the underlying
// UriBuilder class will add one to the
// querystring. Also prepend ; for additional items
base.Query = value.Substring(1);
else
base.Query = value;
}
else
base.Query = string.Empty;
}
}
}
public static void TestUriBuilder()
{
//string uriString = "http://user:password@localhost:8080/www.abc.com/" +
// "home page.htm?item=1233;html=
Heading
#stuff";//[scheme]://[user]:[password]@[host/authority]:[port]/[path];[params]?
//[query string]#[fragment]
try
{
UriBuilderFix ubf = new UriBuilderFix();
ubf.Scheme = "http";
ubf.UserName = "user";
ubf.Password = "password";
ubf.Host = "localhost";
ubf.Port = 8080;
ubf.Path = "www.abc.com/home page.htm";
//The Query property contains any query information included in the URI.
//Query information is separated from the path information by a question mark (?) and continues
//to the end of the URI. The query information returned includes the leading question mark.
//The query information is escaped according to RFC 2396.
//Setting the Query property to null or to System.String.Empty clears the property.
//Note: Do not append a string directly to this property.
//Instead retrieve the property value as a string, remove the leading question mark,
//append the new query string, and set the property with the combined string.
// Don't Do This, too many ? marks, one for every append
ubf.Query = "item=1233";
ubf.Query += ";html=
heading
";ubf.Fragment = "stuff";
Console.WriteLine("Absolute Composed Uri: " + ubf.Uri.AbsoluteUri);
Console.WriteLine("Composed Uri: " + ubf.ToString());
UriBuilder ub = new UriBuilder();
ub.Query = "item=1233";
ub.Query += ";html=
heading
";}
catch (Exception e)
{
Console.WriteLine("Exception thrown building Uri: " + e.ToString());
}
}
#endregion
#region "14.15 Inspect and change your web application configuration (System.Web.Configuration)"
// see the CSCBWeb project for code
#endregion
#region "14.16 Working with HTML"
public static void TestHTMLParser()
{
HTMLDocument htmlDoc = new HTMLDocument();
IHTMLDocument2 iHtmlDoc2 = null;
string html =
""-//W3C//DTD XHTML 1.1//EN\"" +
"\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">" +
""http://www.w3.org/1999/xhtml\" >" +
"
"";
// get the IHTMLDocument2 interface
iHtmlDoc2 = (IHTMLDocument2)htmlDoc;
// Put the document in design mode so we don't execute scripts
// while loading
iHtmlDoc2.designMode = "On";
// Have to put some HTML in the DOM before using it
iHtmlDoc2.write(html);
// close it
iHtmlDoc2.close();
//roll over every element in the html
foreach (IHTMLElement htmlElem in (IHTMLElementCollection)iHtmlDoc2.body.all)
{
// Note: every time we do the is and as, it does a COM call to the
// MSHTML object. This can be rather expensive so you would want to cache
// the results elsewhere once you have them, don't just keep calling
// properties on it as those end up making a round trip as well.
if (htmlElem is IHTMLAnchorElement)
{
HTMLAnchorElementClass anchor = htmlElem as HTMLAnchorElementClass;
if (anchor != null)
Console.WriteLine("Anchor element found: " + anchor.href);
continue;
}
else if (htmlElem is IHTMLFormElement)
{
HTMLFormElementClass form = htmlElem as HTMLFormElementClass;
if (form != null)
Console.WriteLine("Form element found: " + form.id);
continue;
}
else if (htmlElem is IHTMLInputElement)
{
HTMLInputElementClass input = htmlElem as HTMLInputElementClass;
if (input != null)
Console.WriteLine("Input Element found: " + input.name);
continue;
}
else if (htmlElem is IHTMLTextAreaElement)
{
HTMLTextAreaElementClass text = htmlElem as HTMLTextAreaElementClass;
if (text != null)
Console.WriteLine("Text Area Element found: " + text.name);
continue;
}
}
}
#endregion
#region "14.17 Using cached results when working with HTTP for faster performance"
public static void TestCache()
{
// 14.6 has generategetorpostrequest
string html = "";
string url = "http://www.oreilly.com";
// set up the request
HttpWebRequest request = GenerateHttpWebRequest(url);
// make a cache policy to use cached results if available
// the default is to Bypass the cache in machine.config.
RequestCachePolicy rcpCheckCache =
new RequestCachePolicy(RequestCacheLevel.CacheIfAvailable);
// assign the new policy to the request
request.CachePolicy = rcpCheckCache;
// execute the request
HttpWebResponse response = null;
try
{
response = (HttpWebResponse)request.GetResponse();
// check if we hit the cache
if(response.IsFromCache==false)
{
Console.WriteLine("Didn't hit the cache");
}
// get the response stream.
Stream responseStream = response.GetResponseStream();
// use a stream reader that understands UTF8
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
try
{
html = reader.ReadToEnd();
}
finally
{
// close the reader
reader.Close();
}
Console.WriteLine("Html retrieved: " + html);
}
catch (WebException we)
{
Console.WriteLine(we.ToString());
}
}
#endregion
#region "14.18 Checking out a web server's custom error pages
public static void GetCustomErrorPageLocations()
{
// MetaEdit can be gotten here: http://support.microsoft.com/kb/q232068/
// Find metabase properties here
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/iissdk/html/4930f687-3a39-4f7d-9bc7-56dbb013d2b5.asp
// Sometimes the COM world is a rough place
UInt32 E_RPC_SERVER_UNAVAILABLE = 0x800706BA;
try
{
// This is a case sensitive entry in the metabase
// You'd think it was misspelled but you would be mistaken
const string WebServerSchema = "IIsWebServer";
// set up to talk to the local IIS server
string server = "localhost";
// Create a dictionary entry for the IIS server with a fake
// user and password. Credentials would have to be provided
// if you are running as a regular user
using (DirectoryEntry w3svc =
new DirectoryEntry(
string.Format("IIS://{0}/w3svc", server),
"Domain/UserCode", "Password"))
{
// can't talk to the metabase for some reason, bail
if (w3svc != null)
{
foreach (DirectoryEntry site in w3svc.Children)
{
if (site != null)
{
using (site)
{
// check all web servers on this box
if (site.SchemaClassName == WebServerSchema)
{
// get the metabase entry for this server
string metabaseDir =
string.Format("/w3svc/{0}/ROOT", site.Name);
if (site.Children != null)
{
// find the ROOT directory for each server
foreach (DirectoryEntry root in site.Children)
{
using (root)
{
// did we find the root dir for this site?
if (root != null &&
root.Name.Equals("ROOT",
StringComparison.OrdinalIgnoreCase))
{
// get the HttpErrors
if (root.Properties.Contains("HttpErrors") == true)
{
// write them out
PropertyValueCollection httpErrors = root.Properties["HttpErrors"];
if (httpErrors != null)
{
for (int i = 0; i < httpErrors.Count; i++)
{
//400,*,FILE,C:\WINDOWS\help\iisHelp\common\400.htm
string[] errorParts = httpErrors[i].ToString().Split(',');
Console.WriteLine("Error Mapping Entry:");
Console.WriteLine("\tHTTP error code: {0}", errorParts[0]);
Console.WriteLine("\tHTTP sub-error code: {0}", errorParts[1]);
Console.WriteLine("\tMessage Type: {0}", errorParts[2]);
Console.WriteLine("\tPath to error HTML file: {0}", errorParts[3]);
}
}
}
}
}
}
}
}
}
}
}
}
}
}
catch (COMException e)
{
// apparently it won't talk to us right now
// this could be set up in a loop to retry.
if (e.ErrorCode != (Int32)E_RPC_SERVER_UNAVAILABLE)
{
throw;
}
}
}
#endregion
#region "14.19 Determining the application mappings for ASP.NET set up on IIS
public static void DumpASPNETAppMappings()
{
// MetaEdit can be gotten here: http://support.microsoft.com/kb/q232068/
// Find metabase properties here
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/iissdk/html/4930f687-3a39-4f7d-9bc7-56dbb013d2b5.asp
// Sometimes the COM world is a rough place
UInt32 E_RPC_SERVER_UNAVAILABLE = 0x800706BA;
try
{
// This is a case sensitive entry in the metabase
// You'd think it was misspelled but you would be mistaken
const string WebServerSchema = "IIsWebServer";
// set up to talk to the local IIS server
string server = "localhost";
// Create a dictionary entry for the IIS server with a fake
// user and password. Credentials would have to be provided
// if you are running as a regular user
using (DirectoryEntry w3svc = new DirectoryEntry(string.Format("IIS://{0}/w3svc", server), "Domain/UserCode", "Password"))
{
// can't talk to the metabase for some reason, bail
if (w3svc != null)
{
foreach (DirectoryEntry site in w3svc.Children)
{
using (site)
{
if (site != null)
{
// check all web servers on this box
if (site.SchemaClassName == WebServerSchema)
{
// get the metabase entry for this server
string metabaseDir =
string.Format("/w3svc/{0}/ROOT", site.Name);
if (site.Children != null)
{
// find the ROOT directory for each server
foreach (DirectoryEntry root in site.Children)
{
using (root)
{
// did we find the root dir for this site?
if (root != null &&
root.Name.Equals("ROOT", StringComparison.OrdinalIgnoreCase))
{
// get the Application Mappings in the ScriptMaps property
if (root.Properties.Contains("ScriptMaps") == true)
{
// write them out
PropertyValueCollection scriptMaps = root.Properties["ScriptMaps"];
if (scriptMaps != null)
{
for (int i = 0; i < scriptMaps.Count; i++)
{
//.aspx,C:\WINDOWS\Microsoft.NET\Framework\v2.0.50110\aspnet_isapi.dll,1,GET,HEAD,POST,DEBUG
string[] mappingParts = scriptMaps[i].ToString().Split(',');
// The ASP.NET redirector is implemented in the
// aspnet_isapi.dll file so any extensions mapped to it
// will be processed by asp.net
if (mappingParts[1].ToUpper().IndexOf("ASPNET_ISAPI") != -1)
{
// write out details for the ASP.NET mappings
Console.WriteLine("Extension Mappings:");
Console.WriteLine("\tMapped Extension: {0}", mappingParts[0]);
Console.WriteLine("\tHandler: {0}", mappingParts[1]);
for (int j = 3; j < mappingParts.Length; j++)
Console.WriteLine("\tHTTP VERB: {0}", mappingParts[j]);
}
else
{
// write out those unmapped items
Console.WriteLine("Skipping {0} as it is not processed by ASP.NET", mappingParts[0]);
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
catch (COMException e)
{
// apparently it won't talk to us right now
// this could be set up in a loop to retry.
if (e.ErrorCode != (Int32)E_RPC_SERVER_UNAVAILABLE)
{
throw;
}
}
}
#endregion
}
}