HttpLib,一个基于C#语言的http协议的开源类库,让异步交互处理数据更容易。
官方下载地址:http://httplib.codeplex.com/
本文作用演示的例子的源代码:源代码下载
一:HttpLib
HttpLib类库中包含三个主要类文件:HttpVerb.cs, NamedFileStream.cs, Request.cs,另外有一个辅助类Utils.cs
基于http协议的异步操作是定义在Request.cs中。包括Get,Head,Post,Delete,Put,Patch,Upload等,而NamedFileStream.cs是在上传文件到服务器时会用到一个容器类,用于描述上传的文件。Utils.cs则是对于Url参数的处理工具类。
对于HttpLib类库实现异步操作是基于WebHttpRequest对象的异步委托实现的,具体的实现代码可以到官网下载源代码,本文接下来更多是演示以及说明HttpLib类库是怎么来运作的,不会涉及到底层采用什么机制或者相关多线程的问题。
二:用于测试的准备工作
为了更好的测试HttpLib异步调用的结果,我首先创建一个Server服务器对象,并且架设在IIS中启动起来。
Server包含两个一般处理程序一个.aspx页面,一个HttpHandler.ashx,另一个是FileHandler.ashx。还有WebForm.aspx页面。
namespace YZR.Server { /// <summary> /// HttpHandler 的摘要说明 /// </summary> public class HttpHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { string method = context.Request.HttpMethod.ToString(); if (method.ToLower() == "get") { string Name = context.Request["Name"]; if (string.IsNullOrEmpty(Name)) { context.Response.Write("YZR.Get(No Parameters)"); } else { context.Response.Write("YZR.Get(Name:" + Name + ",Create By " + DateTime.Now.ToString("yyyy-MM-dd") + ")"); } } else { string LYF = context.Request["LYF"]; if (string.IsNullOrEmpty(LYF)) { context.Response.Write("YZR.Post(No Parameters)"); } else { context.Response.Write("YZR.Post(你好,大人:" + LYF + ",Create By " + DateTime.Now.ToString("yyyy-MM-dd") + ")"); } } } public bool IsReusable { get { return false; } } } }
namespace YZR.Server { /// <summary> /// FileHandler 的摘要说明 /// </summary> public class FileHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { HttpFileCollection files = HttpContext.Current.Request.Files; if (files.Count > 0) { HttpPostedFile _upfile = files[0]; string fileName = _upfile.FileName;/*获取文件名: C:\Documents and Settings\Administrator\桌面\123.jpg*/ string suffix = fileName.Substring(fileName.LastIndexOf(".") + 1).ToLower();/*获取后缀名并转为小写: jpg*/ int bytes = _upfile.ContentLength;//获取文件的字节大小 if (suffix != "jpg") ResponseWriteEnd(context, "2"); //只能上传JPG格式图片 if (bytes > 1024 * 1024) ResponseWriteEnd(context, "3"); //图片不能大于1M _upfile.SaveAs(HttpContext.Current.Server.MapPath("~/images/logo.jpg"));//保存图片 context.Response.Write("上传成功"); } else { context.Response.Write("请选择上传文件"); } } private void ResponseWriteEnd(HttpContext context, string msg) { context.Response.Write(msg); context.Response.End(); } public bool IsReusable { get { return false; } } } }
namespace YZR.Server { public partial class WebForm : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { string Name = Request["Name"]; if (!String.IsNullOrEmpty(Name)) { Response.Write("Hello " + Name + ",Create By " + DateTime.Now.ToString("yyyy-MM-dd")); } } } } }
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm.aspx.cs" Inherits="YZR.Server.WebForm" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> </head> <body> <form id="form1" runat="server"> <div> WebForm </div> </form> </body> </html>
本文接下来都是基于这个Server对象使用HttpLib类库进行异步调用。
接下来创建两个客户端Client对象,YZR.Client这是一个控制台程序,YZR.JSClient是WebForm程序。在这两个程序都添加对HttpLib类库的引用,并且将在这两个客户端中测试从服务器异步调用的结果。
三:Get异步
我们先来看一下控制台程序(YZR.Client):
namespace YZR.Client { using Redslide.HttpLib; using System.IO; class Program { static void Main(string[] args) { //Get 无参数 //Request.Get("http://localhost:9876/HttpHandler.ashx", result => { Func(result); }); //Request.Get("http://localhost:9876/WebForm.aspx", result => { Func(result); }); //Get 带参数 //Request.Get("http://localhost:9876/HttpHandler.ashx?Name=YZR", result => { Func(result); }); //Request.Get("http://localhost:9876/HttpHandler.ashx", new { Name = "YZR" }, result => { Func(result); }); //Request.Get("http://localhost:9876/WebForm.aspx", new { Name = "YZR" }, result => { Func(result); }); Console.WriteLine("This another work");
Console.ReadKey(); } static void Func(String result) { String Test = result; Console.WriteLine(result); } } }
运行控制台之后,当异步访问ashx文件是将会显示一般处理程序返回来的结果。
而对于aspx页面来说则是一整个页面的html字符串。
在webform程序中,结果也是一样的,下面我们将从服务器获取页面数据,然后将获取到的页面数据输出在我们自己定义的Test.aspx页面中:
namespace YZR.JSClient { using Redslide.HttpLib; public partial class Test : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if(!IsPostBack) { Redslide.HttpLib.Request.Get("http://localhost:9876/WebForm.aspx", new { Name = "YZR" }, result => { Func(result); }); System.Threading.Thread.Sleep(1000); } } void Func(String result) { String Test = result; Response.Write(Test); } } }
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Test.aspx.cs" Inherits="YZR.JSClient.Test" %>
四:Post异步
Post的书写方式是相似于Get方式的:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace YZR.Client { using Redslide.HttpLib; using System.IO; class Program { static void Main(string[] args) { //Get 无参数 //Request.Get("http://localhost:9876/HttpHandler.ashx", result => { Func(result); }); Request.Get("http://localhost:9876/WebForm.aspx", result => { Func(result); }); //Get 带参数 //Request.Get("http://localhost:9876/HttpHandler.ashx?Name=YZR", result => { Func(result); }); //Request.Get("http://localhost:9876/HttpHandler.ashx", new { Name = "YZR" }, result => { Func(result); }); //Request.Get("http://localhost:9876/WebForm.aspx", new { Name = "YZR" }, result => { Func(result); }); //Post 无参数 //Request.Post("http://localhost:9876/HttpHandler.ashx", new { }, action => Func(action)); //Post 带参数 //Request.Post("http://localhost:9876/WebForm.aspx", new { Name = "LYF" }, result => { Func(result); }); Console.ReadKey(); } static void Func(String result) { String Test = result; Console.WriteLine(result); } } }
五:浏览器端的异步Ajax
Js不具有异步功能,但通过浏览器Js+Xml可以实现Ajax技术异步操作:
var AjaxHelp = { GetXhr: function () { //创建异步对象 var xhr= false; var xmlhttpObj = ["MSXML2.XmlHttp.5.0","MSXML2.XmlHttp.4.0","MSXML2.XmlHttp.3.0","MSXML2.XmlHttp","Microsoft.XmlHttp"]; if(window.XMLHttpRequest){ xhr = new XMLHttpRequest(); } else if(window.ActiveXObject){ for(i=0;i<xmlhttpObj.length;i++) { xhr = new ActiveXObject(xmlhttpObj[i]); if(xhr){ break; } } } else{ alert("暂时不能创建XMLHttpRequest对象"); } return xhr ? xhr:false; }, //处理ajax的get请求 ProcessGet: function (url, callback) { this.ProcessAjax("get", url, null, callback); }, ProcessPost: function (url, params, callback) { this.ProcessAjax("post", url, params, callback); }, //统一处理的方法 ProcessAjax: function (method, url, params, callback) { //1.0创建异步对象 var xhr = this.GetXhr(); if (method == "get") { //2.0打开链接 xhr.open("get", url, true); //3.0不使用缓存 xhr.setRequestHeader("if-modified-since", "0"); } else { //2.0打开链接 xhr.open("post", url, true); //3.0将参数放在form data属性中 xhr.setRequestHeader("content-type", "application/x-www-form-urlencoded"); } //4.0设置回调函数 xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) { //得到从服务器里得到的数据 var content = JSON.parse(xhr.responseText);//---->转成js对象 //调用回调函数(执行自己的业务逻辑) callback(content); } } //5.0发送请求 xhr.send(params); } };
在代码上,他们的书写方式我觉得是极为的相似,而且他们都是进行异步操作。
六:上传
使用HttpLib类库还有一个上传的异步操作,文章一开始说的NamedFileStream就是为了上传文件而定义的。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace YZR.Client { using Redslide.HttpLib; using System.IO; class Program { static void Main(string[] args) { //Get 无参数 //Request.Get("http://localhost:9876/HttpHandler.ashx", result => { Func(result); }); Request.Get("http://localhost:9876/WebForm.aspx", result => { Func(result); }); //Get 带参数 //Request.Get("http://localhost:9876/HttpHandler.ashx?Name=YZR", result => { Func(result); }); //Request.Get("http://localhost:9876/HttpHandler.ashx", new { Name = "YZR" }, result => { Func(result); }); //Request.Get("http://localhost:9876/WebForm.aspx", new { Name = "YZR" }, result => { Func(result); }); //Post 无参数 //Request.Post("http://localhost:9876/HttpHandler.ashx", new { }, action => Func(action)); //Post 带参数 //Request.Post("http://localhost:9876/WebForm.aspx", new { Name = "LYF" }, result => { Func(result); }); //上传 //NamedFileStream file = new NamedFileStream("file", "1.jpg", "image/jpeg", new FileStream(@"C:\1.jpg", FileMode.Open)); //Request.Upload("http://localhost:9876/FileHandler.ashx", new { }, new[] { new NamedFileStream("file", "1.jpg", "image/jpeg", new FileStream(@"C:\1.jpg", FileMode.Open)) }, action => Func(action)); Console.ReadKey(); } static void Func(String result) { String Test = result; Console.WriteLine(result); } } }
在服务端Server下images文件夹下就会保存从客户端上传上来的文件。
总而言之,HttpLib类库可以让我们在后台中更轻松的完成异步调用,当你在程序中需要使用异步时,HttpLib也许能帮得上忙。