Request 和 Response 的.NET技术应用

摘要:Request 和 Response 的.NET技术应用


一、

一个典型的Request与Response应用就是“网络机器人”

System.Net 命名空间提供开发 windows form 应用于网络之工具,

System.Net 命名空间底下有 WebRequest 与 WebResponse 可以使用;

而 System.Web 命名空间提供开发 web form 应用于网络之工具。

System.Web 命名空间底下有 HttpRequest 与 HttpResponse 类可以使用。

本文特别针对 System.Web 命名空间作说明。

WebRequest 与 WebResponse 皆为基础的抽象类,

还有更丰富的应用为 HttpWebRequest 与 HttpWebResponse 类,

其两者继承了 WebRequest 与 WebResponse 类。

1、列出部分 WebRequest 类相关方法与属性:

    a、Method 属性:通常其值为字符串 GET 或 POST。

    b、Create(String)、Create(Uri)、CreateHttp(String)、CreateHttp(Uri) 方法:

Create 与 CreateHttp 方法两者差在一个为 Create WebRequest 执行个体,另外一个为Create HttpWebRequest执行个体。

    c、GetRequestStream 方法:在子代类中覆写时,返回 Stream,以便将数据写入至互联网资源。

    d、GetResponse 方法:在子代类中覆写时,返回对互联网要求的响应。

2、列出部分 WebResponse 相关方法与属性:

    a、ContentLength 属性:在子代类中覆写时,取得或设定正在接收数据的内容长度。

    b、ContentType 属性:在衍生类中覆写时,取得或设定正在接收数据的内容类型。

    c、Headers 属性:在衍生类中覆写时,取得与这个要求相关联的标头名称值配对集合。

    d、ResponseUri 属性:取得Uri

    e、GetResponseStream 方法:在子代类中覆写时,返回来自互联网资源的数据流。

二、范例

以下为 httprequest 与 HttpResponse 技术的 VB.NET 语法范例

Imports System.IO
Imports System.Net

Public Class Form1

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        '1.webreq = WebRequest.CreateHttp("http://www.yahoo.com.tw") 效果一样?
        Dim webreq As HttpWebRequest = HttpWebRequest.Create("http://www.yahoo.com.tw")

        '2.HttpWebRequest继承自WebRequest
        Dim resp As HttpWebResponse = webreq.GetResponse

        '取出该网页文字档
        Dim sr As StreamReader = New StreamReader(resp.GetResponseStream)
        TextBox1.Text = sr.ReadToEnd
        sr.Close()

        '将html倒给webBrowser
        WebBrowser1.DocumentText = TextBox1.Text
        'WebBrowser1.Navigate("http://www.yahoo.com.tw") 使用WebBrowser1.Navigate所显示的内容比WebBrowser1.DocumentText = TextBox1.Text还正确

    End Sub
End Class

以下为 httprequest 与 HttpResponse 技术的 C# 语法范例

using System;
using System.IO;
using System.Net;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string myUri = "http://www.dotblogs.com.tw/brooke/Default.aspx";

            HttpWebRequest webreq = HttpWebRequest.CreateHttp(myUri);

            //2.WebResponse不能隐含转成HttpWebResponse
            WebResponse resp = webreq.GetResponse();

            //取出该网页文字档
            StreamReader sr = new StreamReader(resp.GetResponseStream());
            String s2 = sr.ReadToEnd();
            sr.Close();

            Console.WriteLine(s2);

            Console.ReadLine();
        }
    }
}

说明:

一开始Request一般都会先借由Create(uri)来初始化一个Request,

然后再使用Response去接Request回来的Response(响应),

最后再对已接收到Response的Response对象做处理,例如取得网页源代码。

三、实践简单的POST方法

我们借由一个MVC会员登入范例来实践简单的POST方法

http://localhost:55715/

http://localhost:55715/Account/Login

为了focus在核心项目我把AntiForgeryToken拿掉了,减化复杂度。

我们从Fiddler来观察,

Header

TextView

SyntaxView

WebForms

由此可知我们要POST的项目有三项分别是Email、Password、RememberMe

注意POST到server端的字符串要经过UrlEnode编码才行传送,如上图SyntaxView

一个使用 POST 方法到 server 的程序框架如下

using System;
using System.Net;
using System.Text;
using System.Web;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string Email = "aaa@aaa.aaa.aa";
            string Password = "a";
            Boolean RememberMe = false;

            Email = HttpUtility.UrlEncode(Email);
            Password = HttpUtility.UrlEncode(Password);

            string formatString = "Email={0}&Password={1}&RememberMe={2}";
            string postString = string.Format(formatString, Email, Password, RememberMe);

            byte[] postData = Encoding.UTF8.GetBytes(postString);

            string myUri = "http://localhost:56306/Home/About";
            HttpWebRequest request = WebRequest.Create(myUri) as HttpWebRequest;
            request.Method = "POST";
            request.KeepAlive = false;
            request.ContentType = "application/x-www-form-urlencoded";
            CookieContainer cookieContainer = new CookieContainer();
            request.CookieContainer = cookieContainer;
            request.ContentLength = postData.Length;

            // 提交请求数据
            System.IO.Stream outputStream = request.GetRequestStream();
            outputStream.Write(postData, 0, postData.Length);
            outputStream.Close();

            // 接收返回的页面
            HttpWebResponse response = request.GetResponse() as HttpWebResponse;
            System.IO.Stream responseStream = response.GetResponseStream();
            System.IO.StreamReader reader = new System.IO.StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
            string srcString = reader.ReadToEnd();

            Console.ReadLine();
        }
    }
}

另外我也试了一下,如果网站加上了AntiForgeryToken用来防止CSRF(Cross-Site Request Forgery),

我在我的Console也因为网站使用了防CSRF技术,所以我POST参数再加上__RequestVerificationToken的值,

但很可惜的,server端回传一个“远端服务器返回一个错误: (500) 内部服务器错误。”的错误消息,

实验结果,当网站使用了AntiForgeryToken之后,

就算你知道了__RequestVerificationToken的值并且也依样画葫芦将值送到了server端,

server端也会把你档下来。我个人认为AntiForgeryToken的技术会做类似checkSum动作,

算出来的结果有异就挡下来。

参考数据:

使用HttpWebRequest 登入网站并POST查询

使用HttpWebRequest提交ASP.NET表单并保持Session和Cookie

ASP.NET MVC - ValidateAntiForgeryToken 与 自定 HandleError 处理显示客制的错误消息页

如何使用 WebRequest,HttpWebRequest 来存取 (GET,POST,PUT,DELETE,PATCH) 网络资源

[C#/.net] 使用HttpWebRequest来Post数据

WebClient 类 (System.Net)

使用 WebClient 来存取 GET,POST,PUT,DELETE,PATCH 网络资源