四川北大青鸟|成都名流北大青鸟电脑培训学校,专业计算机软件开发培训,学士后课程专为大学生开设
四川北大青鸟|成都名流北大青鸟电脑培训学校,专业计算机软件开发培训,学士后课程专为大学生开设 网站地图 成都北大青鸟培训学校 北大青鸟培训 成都北大青鸟

首 页
新闻 青鸟 热点 大学生就业
学习 JAVA .NET 网站建设
学校 总部 学校地址 荣誉
招生 问答集 学费 课程
课程 学士后 java课程 .net课程
就业 就业学员 就业企业 职业规划
师资 高级讲师 就业专员
实训 学员作品 创业中心
高中生学什么 大学生就业
视频 青鸟视频 课程视频
成都北大青鸟名流培训学校介绍北大青鸟学士后课程成都北大青鸟项目实训成都北大青鸟培训中心学员就业成都北大青鸟培训中心在线咨询成都北大青鸟官网报名

全国免费电话:4007-028-222
在线咨询QQ:923597100
成都北大青鸟学生交流群①:94507684
当前位置: 主页 > 学习社区 > .NET学习 >

北大青鸟:asp.net获取Get和Post请求的参数

时间:2012-02-10 10:12来源:成都北大青鸟 作者:朱老师 点击:
关于获取Get和Post请求的参数,。net类库提供了相关的方法: Request.QueryString 常见的获取Url参数。Request.Form 常见的获取提交表单项。

       关于获取Get和Post请求的参数,。net类库提供了相关的方法:
  Request.QueryString  常见的获取Url参数。
  Request.Form 常见的获取提交表单项。
  这两个方法在获取的时候都会进行解码,并且不是使用者可以控制的。这样可能就会导致一些问题,比如不想对获取到的参数进行解码,或者解码的时候需要特殊的编码而不是系统默认的编码。当然也可以从请求的数据流中读取字节进行解析,这样就增加了处理的复杂度,并且不便于快速多处应用。
  这篇文章将提供一些方法,在获取参数的时候指定是否解码以及编码的类型。
  一、首先看Url方式提交的参数
  查看源代码打印?
  /// <summary> /// 获取以Url方式提交的参数集合。
  /// </summary> /// <param name="isUrlDecode">是否要进行Url解码</param> /// <param name="encoding">Url解码时用的编码</param> /// <returns>参数集合。</returns> /// <example> /// string paras = string.Empty;/// System.Collections.Specialized.NameValueCollection paraCollection = RequestHelper.GetQueryStrings(true, Encoding.UTF8);/// /// foreach (string key in paraCollection.AllKeys)
  /// { ///     paras += key + ":" + paraCollection[key] + "\r\n";/// } /// </example> public static NameValueCollection GetQueryStrings(bool isUrlDecode, Encoding encoding)
  { // 获取查询字符串string query = HttpContext.Current.Request.Url.Query;if (query.StartsWith("?"))
  { if (query.Length > 1)
  { query = query.Substring(1, query.Length - 1);} else { query = string.Empty;}
  // 处理查询字符串NameValueCollection collection = FillFromString(query, isUrlDecode, encoding);return collection;}
  /// <summary> /// 从参数字符串获取参数集合/// </summary> /// <param name="s">参数字符串</param> /// <param name="isUrlDecode">是否要进行Url解码</param> /// <param name="encoding">Url解码时用的编码</param> /// <returns>Url参数集合</returns> private static NameValueCollection FillFromString(string s, bool isUrlDecode, Encoding encoding)
  { NameValueCollection parametersCollection = new NameValueCollection();
  // 参数字符串长度int sLen = (s != null) ? s.Length : 0;
  // 遍历每个字符for (int i = 0; i < sLen; i++)
  { // 参数名开始位置int startIndex = i;
  // 参数名结束位置int endIndex = -1;
  // 字符索引前进,直到遇到等号,更新结束的索引位置// 如果遇到&符号,则参数结束,退出循环while (i < sLen)
  { char ch = s[i];if (ch == '=')
  { if (endIndex < 0)
  { endIndex = i;} else if (ch == '&')
  { break;}
  // 字符索引前进i++;}
  string parameterName = null;string parameterValue = null;
  // 存在等号,可以获取到参数名和参数值if (endIndex >= 0)
  { parameterName = s.Substring(startIndex, endIndex - startIndex);parameterValue = s.Substring(endIndex + 1, (i - endIndex) - 1);} else { parameterValue = s.Substring(startIndex, i - startIndex);}
  // 需要解码if (isUrlDecode)
  { parametersCollection.Add(HttpUtility.UrlDecode(parameterName, encoding), HttpUtility.UrlDecode(parameterValue, encoding));} else { parametersCollection.Add(parameterName, parameterValue);}
  // 最后一个字符是 &,则添加一个参数为null的NameValue对。
  if ((i == (sLen - 1)) && (s[i] == '&'))
  { parametersCollection.Add(null, string.Empty);}
  return parametersCollection;}
  FillFromString方法是通过反编译微软的类库,然后经过简单修改而来的。处理方式严谨可靠,学习了下。
  使用的时候调用GetQueryStrings方法获取全部Get参数的集合。
  二、获取Post方式提交的参数
  相比获取通过Url方式提交的参数,获取通过Post方式提交的参数要复杂一些。
  要区分两种表单的类型:application/x-www-form-urlencoded 和 multipart/form-data,前者只能提交一般参数,后者还可以提交文件。
  因为通过这种方式提交的数据,是先从流中读取字节数据,然后解码的,所以解码是必须的,但是可以提供特殊的编码类型。
  这里专门定义了一个类来解析这些数据,当然这个方法也是按照微软的思路来做的。
  查看源代码打印?
  using System;using System.Collections.Generic;using System.Collections.Specialized;using System.Linq;using System.Text;using System.Web;using System.Globalization;
  namespace VeryCodes.Web { /// <summary> /// 以Post方式提交的变量的集合。
  /// </summary> /// <remarks> /// 不包含提交的文件。
  /// </remarks> internal class PostVariableCollection : NameValueCollection { /// <summary> /// Content Type /// </summary> private string contentType = string.Empty;
  /// <summary> /// 分界符/// </summary> private byte[] boundary;
  /// <summary> /// 初始化类 PostVariableCollection 的一个新实例/// </summary> public PostVariableCollection()
  { FillFormStream(Encoding.Default);}
  /// <summary> /// 初始化类 PostVariableCollection 的一个新实例/// </summary> /// <param name="isUrlDecode">是否进行Url解码</param> /// <param name="encoding">编码类型</param> public PostVariableCollection(Encoding encoding)
  { FillFormStream(encoding);}
  /// <summary> /// 使用HTTP实体主体内容填充集合/// </summary> /// <param name="isUrlDecode"></param> /// <param name="encoding"></param> private void FillFormStream(Encoding encoding)
  { contentType = HttpContext.Current.Request.ContentType;
  if (!string.IsNullOrEmpty(contentType))
  { System.IO.Stream entityStream = HttpContext.Current.Request.InputStream;
  // 获取HTTP实体主体的内容byte[] bytes = GetEntityBody(entityStream, 0);
  if (bytes == null || bytes.Length <= 0)
  { return;}
  // 因为是字节数据,所有的数据都需要解码if (contentType.StartsWith("application/x-www-form-urlencoded", System.StringComparison.CurrentCultureIgnoreCase))
  { try { FillFromBytes(bytes, encoding);return;} catch (Exception ex)
  { throw new HttpException("Invalid_urlencoded_form_data", ex);}
  if (contentType.StartsWith("multipart/form-data", System.StringComparison.CurrentCultureIgnoreCase))
  { if (GetMultipartBoundary())
  { try { // 获取各个参数FillFromMultipartBytes(bytes, encoding);return;} catch (Exception ex)
  { throw new HttpException("Invalid_multipart_form_data", ex);}
  /// <summary> /// 从字节数组读取变量填充到集合/// </summary> /// <param name="bytes"></param> /// <param name="encoding"></param> private void FillFromBytes(byte[] bytes, Encoding encoding)
  { // 字节数组长度int bLen = (bytes != null) ? bytes.Length : 0;
  // 遍历字节数组for (int i = 0; i < bLen; i++)
  { string parameterName;string parameterValue;
  //参数名开始位置int startIndex = i;
  //参数名结束位置int endIndex = -1;
  while (i < bLen)
  { byte bt = bytes[i];
  // 符号:= if (bt == 0x3d)
  { if (endIndex < 0)
  { endIndex = i;} else if (bt == 0x26) //符号:& { break;} i++;}
  if (endIndex >= 0)
  { parameterName = HttpUtility.UrlDecode(bytes, startIndex, endIndex - startIndex, encoding);parameterValue = HttpUtility.UrlDecode(bytes, endIndex + 1, (i - endIndex) - 1, encoding);} else { parameterName = null;parameterValue = HttpUtility.UrlDecode(bytes, startIndex, i - startIndex, encoding);}
  base.Add(parameterName, parameterValue);
  if ((i == (bLen - 1)) && (bytes[i] == 0x26))
  { base.Add(null, string.Empty);}
  /// <summary> /// 从多部件的实体主体内容中读取变量填充到集合,文件排除在外。
  /// </summary> /// <param name="bytes"></param> /// <param name="isUrlDecode"></param> /// <param name="encoding"></param> private void FillFromMultipartBytes(byte[] bytes, Encoding encoding)
  { // 字节数组长度int bLen = (bytes != null) ? bytes.Length : 0;
  // 当前字节索引int currentIndex = 0;
  // 当前行开始索引int lineStartIndex = -1;
  // 当前行结束索引int lineEndIndex = currentIndex;
  // 当前行字节长度int lineLength = -1;
  // 是否最后一个分界符bool isLastBoundary = false;
  // 上一行是否分界符行bool prevIsBoundary = false;
  // 上一行是否参数名称行bool prevIsParaName = false;
  // 上一行是否参数名称行的结束索引int prevParaNameLineEndIndex = 0;
  // 参数名称string paraName = string.Empty;
  // 参数值string paraValue = string.Empty;
  // 遍历字节数组for (int i = 0; i < bLen; i++)
  { //查找行,行由char(13)+char(10)结束while (lineEndIndex < bLen)
  { // 换行if (bytes[lineEndIndex] == 10)
  { lineStartIndex = currentIndex;lineLength = lineEndIndex - currentIndex;
  // 回车if (lineLength > 0 && bytes[lineEndIndex - 1] == 13)
  { lineLength——;}
  currentIndex = lineEndIndex + 1;
  break;}
  if (++lineEndIndex == bLen)
  { lineStartIndex = currentIndex;lineLength = lineEndIndex - currentIndex;currentIndex = bLen;}
  // 处理行if (lineStartIndex >= 0)
  { // 如果是分界符行if (AtBoundaryLine(bytes, lineLength, lineStartIndex, out isLastBoundary))
  { // 获取参数值if (prevIsParaName)
  { paraValue = GetParaValueFromContent(bytes, bLen, prevParaNameLineEndIndex, lineStartIndex, encoding);prevIsParaName = false;base.Add(paraName, paraValue);}
  prevIsBoundary = true;
  // 最后一行了if (isLastBoundary)
  { break;} else { // 如果上一行是分界符行,则处理本行if (prevIsBoundary)
  { if (lineLength <= 0)
  { continue;}
  byte[] buffer = new byte[lineLength];Array.Copy(bytes, lineStartIndex, buffer, 0, lineLength);
  string l = encoding.GetString(buffer);int colonIndex = l.IndexOf(':');if (colonIndex >= 0)
  { string str2 = l.Substring(0, colonIndex);
  if (string.Equals(str2, "Content-Disposition", StringComparison.CurrentCultureIgnoreCase))
  { // 获取参数名称paraName = this.GetParaNameFromContent(l, colonIndex + 1, "name");
  //// 获取文件名称//string paraFileName = this.GetParaNameFromContent(l, colonIndex + 1, "filename");
  // 参数名不为空,且非文件if (!string.IsNullOrEmpty(paraName) && !l.Contains("filename"))
  { // 标记上一行是参数名称行prevIsParaName = true;
  // 行结束的索引prevParaNameLineEndIndex = lineEndIndex;}
  prevIsBoundary = false;}
  // 处理下一行lineEndIndex++;i = lineEndIndex;}
  /// <summary> /// 获取HTTP实体主体的内容的字节数组形式/// </summary> /// <param name="stream"></param> /// <param name="bufferLen"></param> /// <returns></returns> private byte[] GetEntityBody(System.IO.Stream stream, int bufferLen)
  { // 如果指定的无效长度的缓冲区,则指定一个默认的长度作为缓存大小if (bufferLen < 1)
  { bufferLen = 0x8000;}
  // 初始化一个缓存区byte[] buffer = new byte[bufferLen];
  // 已读取的字节数int read = 0;
  // 缓冲区中的总字节数int block;
  // 每次从流中读取缓存大小的数据,直到读取完所有的流为止// 如果当前可用的字节数没有请求的字节数那么多,则总字节数可能小于请求的字节数;如果已到达流的末尾,则为零 (0)
  while ((block = stream.Read(buffer, read, buffer.Length - read)) > 0)
  { // 重新设定读取位置read += block;
  // 检查已读取字节数是否到达了缓冲区的边界if (read == buffer.Length)
  { // 尝试读取一个字节,检查是否还有可以读取的信息int nextByte = stream.ReadByte();
  // 读取失败则说明读取完成可以返回结果if (nextByte == -1)
  { return buffer;}
  // 调整数组大小准备继续读取byte[] newBuf = new byte[buffer.Length * 2];Array.Copy(buffer, newBuf, buffer.Length);newBuf[read] = (byte)nextByte;
  // buffer是一个引用(指针),这里意在重新设定buffer指针指向一个更大的内存buffer = newBuf;read++;}
  // 如果缓存太大则收缩前面while读取的buffer,然后直接返回byte[] ret = new byte[read];Array.Copy(buffer, ret, read);return ret;}
  /// <summary> /// 获取边界字符串/// </summary> /// <returns></returns> private bool GetMultipartBoundary()
  { // 获取边界字符串属性的值string attributeFromHeader = GetAttributeFromHeader(contentType, "boundary");if (attributeFromHeader == null)
  { return false;}
  // 每一个边界符前面都需要加2个连字符“——”
  attributeFromHeader = "——" + attributeFromHeader;boundary = Encoding.ASCII.GetBytes(attributeFromHeader.ToCharArray());
  return true;}
  /// <summary> /// 判断是否在分界符行/// </summary> /// <param name="bytes"></param> /// <param name="lineLength"></param> /// <param name="lineStartIndex"></param> /// <param name="isLastBoundary"></param> /// <returns></returns> private bool AtBoundaryLine(byte[] bytes, int lineLength, int lineStartIndex, out bool isLastBoundary)
  { isLastBoundary = false;
  int length = this.boundary.Length;if (lineLength != length && lineLength != (length + 2))
  { return false;}
  for (int i = 0; i < length; i++)
  { if (bytes[lineStartIndex + i] != this.boundary[i])
  { return false;}
  // 最后一个分界符后两个字符是“——”
  if (lineLength != length)
  { if ((bytes[lineStartIndex + length] != 0x2d) || (bytes[(lineStartIndex + length) + 1] != 0x2d))
  { return false;}
  isLastBoundary = true;}
  return true;}
  /// <summary> /// 获取ContentType中属性的值/// </summary> /// <param name="headerValue">ContentType</param> /// <param name="attrName">属性名称</param> /// <returns></returns> private string GetAttributeFromHeader(string headerValue, string attrName)
  { int index;if (headerValue == null)
  { return null;}
  int headerValueLen = headerValue.Length;int attrNameLen = attrName.Length;
  // 获取attrName的起始索引位置int startIndex = 1;while (startIndex < headerValueLen)
  { // ContentType结构类似:multipart/form-data; boundary=——7db2693010b2a startIndex = CultureInfo.InvariantCulture.CompareInfo.IndexOf(headerValue, attrName, startIndex, CompareOptions.IgnoreCase);
  // 不包含“attrName”,跳出循环if ((startIndex < 0) || (startIndex + attrNameLen >= headerValueLen))
  { break;}
  // 符合如下条件即跳出循环// attrName前一个字符可以为 ; 或 , 或 空白(char 11 12 13)
  // attrName后一个字符可以为 = 或 空白(char 11 12 13)
  char c = headerValue[startIndex - 1];char ch2 = headerValue[startIndex + attrNameLen];if ((c == ';' || c == ',' || char.IsWhiteSpace(c)) && ((ch2 == '=') || char.IsWhiteSpace(ch2)))
  { break;}
  // 不符合条件,索引前进,继续查找startIndex += attrNameLen;}
  // 不包含符合条件的“attrName”
  if ((startIndex < 0) || (startIndex >= headerValueLen))
  { return null;}
  // ContentType中包含了attrName,获取attrName的值startIndex += attrNameLen;
  // 如果startIndex是空白,则索引++,直到非空白while ((startIndex < headerValueLen) && char.IsWhiteSpace(headerValue[startIndex]))
  { startIndex++;}
  // 移动到符号 = if ((startIndex >= headerValueLen) || (headerValue[startIndex] != '='))
  { return null;}
  // 继续前进到值startIndex++;
  while ((startIndex < headerValueLen) && char.IsWhiteSpace(headerValue[startIndex]))
  { startIndex++;}
  // 如果索引超出,则返回if (startIndex >= headerValueLen)
  { return null;}
  // 如果是被双引号包含的if ((startIndex < headerValueLen) && (headerValue[startIndex] == '"'))
  { if (startIndex == (headerValueLen - 1))
  { return null;}
  // 获取结束的双引号index = headerValue.IndexOf('"', startIndex + 1);
  if ((index < 0) || (index == (startIndex + 1)))
  { return null;}
  // 截取双引号之间的值return headerValue.Substring(startIndex + 1, (index - startIndex) - 1)。Trim();}
  // 索引前进,查找空格或逗号等分隔符// 如果找不到,索引到倒数第二个字符index = startIndex;while (index < headerValueLen)
  { if ((headerValue[index] == ' ') || (headerValue[index] == ','))
  { break;}
  index++;}
  if (index == startIndex)
  { return null;}
  // 截取返回return headerValue.Substring(startIndex, index - startIndex)。Trim();}
  /// <summary> /// 获取参数名称/// </summary> /// <param name="l"></param> /// <param name="pos"></param> /// <param name="name"></param> /// <returns></returns> private string GetParaNameFromContent(string l, int pos, string name)
  { string str = name + "=\"";int startIndex = CultureInfo.InvariantCulture.CompareInfo.IndexOf(l, str, pos, CompareOptions.IgnoreCase);if (startIndex < 0)
  { return null;} startIndex += str.Length;int index = l.IndexOf('"', startIndex);if (index < 0)
  { return null;} if (index == startIndex)
  { return string.Empty;}
  return l.Substring(startIndex, index - startIndex);}
  /// <summary> /// 获取参数值/// </summary> /// <param name="bytes"></param> /// <param name="bLen"></param> /// <param name="pos"></param> /// <param name="lineStartIndex"></param> /// <param name="encoding"></param> /// <returns></returns> private string GetParaValueFromContent(byte[] bytes, int bLen, int pos, int lineStartIndex, Encoding encoding)
  { int valueStart = pos + 3;int valueLength = -1;int valueEndIndex = lineStartIndex - 1;
  if (valueStart > bLen || valueEndIndex > bLen)
  { return null;}
  if (bytes[valueEndIndex] == 10)
  { valueEndIndex——;} if (bytes[valueEndIndex] == 13)
  { valueEndIndex——;}
  valueLength = (valueEndIndex - valueStart) + 1;
  return encoding.GetString(bytes, valueStart, valueLength);}注意我在这个类中剔除了获取文件项的方法,只能获取其它表单项的值。
  使用的时候可以如下调用:
  查看源代码打印?
  /// <summary> /// 获取以Post方式提交的参数集合。
  /// </summary> /// <param name="isUrlDecode">是否要进行Url解码</param> /// <param name="encoding">Url解码时用的编码</param> /// <returns>参数集合。</returns> /// <example> /// string paras = string.Empty;/// System.Collections.Specialized.NameValueCollection paraCollection = RequestHelper.GetFormStrings(Encoding.UTF8);/// /// foreach (string key in paraCollection.AllKeys)
  /// { ///     paras += key + ":" + paraCollection[key] + "\r\n";/// } /// </example> public static NameValueCollection GetFormStrings(Encoding encoding)
  { return new PostVariableCollection(encoding);}

(编辑:成都北大青鸟名流)