<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      今天我來談一談容易被人混淆的二個集合:Request[]與Request.Params[]

      這二個集合我在博客【我心目中的Asp.net核心對象】中就提到過它們, 而且還給出了一個示例,并以截圖的形式揭示過它們的差別。但由于那篇博客中有更多有價值的對象要介紹, 因此也就沒有花太多的篇幅著重介紹這二個集合。但我發(fā)現(xiàn),不知道這二個集合差別的人確實(shí)太多,以至于我認(rèn)為很有必要為它們寫個專題來細(xì)說它們的差別了。

      在ASP.NET編程中,有三個比較常見的來自于客戶端的數(shù)據(jù)來源:QueryString, Form, Cookie 。 我們可以在HttpRequest中訪問這三大對象, 比如,可以從QueryString中獲取包含在URL中的一些參數(shù), 可以從Form中獲取用戶輸入的表單數(shù)據(jù), 可以從Cookie中獲取一些會話狀態(tài)以及其它的用戶個性化參數(shù)信息。 除了這三大對象,HttpRequest還提供ServerVariables來讓我們獲取一些來自于Web服務(wù)器變量。 通常,這4個數(shù)據(jù)來源都很明確,我想沒人會混淆它們。

      一般情況下,如果我們在事先就能明確知道某個參數(shù)是來源于哪個集合,那么直接訪問那個集合,問題也就簡單了。 然而,更常見的數(shù)據(jù)來源通常只會是QueryString, Form ,而且尤其是當(dāng)在客戶端使用Jquery的$.ajax()這類技術(shù)時, 可以很隨意地將參數(shù)放到QueryString或者是Form中,那么,服務(wù)端通常為了也能靈活地應(yīng)對這一現(xiàn)況, 可以使用Request[]與Request.Params[] 這二種方式來訪問這些來自于用戶提交的數(shù)據(jù)。 本文的故事也因此而產(chǎn)生了:Request[]與Request.Params[] 有什么差別??

      回顧博客原文

      由于【我心目中的Asp.net核心對象】有對它們的一些介紹以及示例截圖, 無奈,有些人可能由于各種原因,沒看到那段文字,這里我也只好再貼一次了:


      這二個屬性都可以讓我們方便地根據(jù)一個KEY去【同時搜索】QueryString、Form、Cookies 或 ServerVariables這4個集合。 通常如果請求是用GET方法發(fā)出的,那我們一般是訪問QueryString去獲取用戶的數(shù)據(jù),如果請求是用POST方法提交的, 我們一般使用Form去訪問用戶提交的表單數(shù)據(jù)。而使用Params,Item可以讓我們在寫代碼時不必區(qū)分是GET還是POST。 這二個屬性唯一不同的是:Item是依次訪問這4個集合,找到就返回結(jié)果,而Params是在訪問時,先將4個集合的數(shù)據(jù)合并到一個新集合(集合不存在時創(chuàng)建), 然后再查找指定的結(jié)果。
      為了更清楚地演示這們的差別,請看以下示例代碼:

      <body>    
          <p>Item結(jié)果:<%= this.ItemValue %></p>
          <p>Params結(jié)果:<%= this.ParamsValue %></p>
          
          <hr />
          
          <form action="<%= Request.RawUrl %>" method="post">
              <input type="text" name="name" value="123" />
              <input type="submit" value="提交" />
          </form>
      </body>
      

      public partial class ShowItem : System.Web.UI.Page
      {
          protected string ItemValue;
          protected string ParamsValue;
      
          protected void Page_Load(object sender, EventArgs e)
          {
              string[] allkeys = Request.QueryString.AllKeys;
              if( allkeys.Length == 0 )
                  Response.Redirect("ShowItem.aspx?name=abc", true);
      
      
              ItemValue = Request["name"];
              ParamsValue = Request.Params["name"];        
          }
      }
      

      頁面在未提交前瀏覽器的顯示:

      點(diǎn)擊提交按鈕后,瀏覽器的顯示:

      差別很明顯,我也不多說了。說下我的建議吧:盡量不要使用Params,不光是上面的結(jié)果導(dǎo)致的判斷問題, 沒必要多創(chuàng)建一個集合出來吧,而且更糟糕的是寫Cookie后,也會更新集合。


      正如我前面所說的客觀原因:由于那篇博客中有更多有價值的對象要介紹,因此也就沒有花太多的篇幅著重介紹這二個集合。 下面,我來仔細(xì)地說說它們的差別。

      實(shí)現(xiàn)方式分析

      前面的示例中,我演示了在訪問Request[]與Request.Params[] 時得到了不同的結(jié)果。為什么會有不同的結(jié)果呢,我想我們還是先去看一下微軟在.net framework中的實(shí)現(xiàn)吧。

      首先,我們來看一下Request[]的實(shí)現(xiàn),它是一個默認(rèn)的索引器,實(shí)現(xiàn)代碼如下:

      public string this[string key]
      {
          get
          {
              string str = this.QueryString[key];
              if( str != null ) {
                  return str;
              }
              str = this.Form[key];
              if( str != null ) {
                  return str;
              }
              HttpCookie cookie = this.Cookies[key];
              if( cookie != null ) {
                  return cookie.Value;
              }
              str = this.ServerVariables[key];
              if( str != null ) {
                  return str;
              }
              return null;
          }
      }
      

      這段代碼的意思是:根據(jù)指定的key,依次訪問QueryString,F(xiàn)orm,Cookies,ServerVariables這4個集合,如果在任意一個集合中找到了,就立即返回。

      Request.Params[]的實(shí)現(xiàn)如下:

      public NameValueCollection Params
      {
          get
          {
              //if (HttpRuntime.HasAspNetHostingPermission(AspNetHostingPermissionLevel.Low))
              //{
              //    return this.GetParams();
              //}
              //return this.GetParamsWithDemand();
      
              // 為了便于理解,我注釋了上面的代碼,其實(shí)關(guān)鍵還是下面的調(diào)用。
              return this.GetParams();
          }
      }
      private NameValueCollection GetParams()
      {
          if( this._params == null ) {
              this._params = new HttpValueCollection(0x40);
              this.FillInParamsCollection();
              this._params.MakeReadOnly();
          }
          return this._params;
      }
      private void FillInParamsCollection()
      {
          this._params.Add(this.QueryString);
          this._params.Add(this.Form);
          this._params.Add(this.Cookies);
          this._params.Add(this.ServerVariables);
      }
      

      它的實(shí)現(xiàn)方式是:先判斷_params這個Field成員是否為null,如果是,則創(chuàng)建一個集合,并把QueryString,F(xiàn)orm,Cookies,ServerVariables這4個集合的數(shù)據(jù)全部填充進(jìn)來, 以后的查詢都直接在這個集合中進(jìn)行。

      我們可以看到,這是二個截然不同的實(shí)現(xiàn)方式。也就是因為這個原因,在某些特殊情況下訪問它們得到的結(jié)果將會不一樣。
      不一樣的原因是:Request.Params[]創(chuàng)建了一個新集合,并合并了這4個數(shù)據(jù)源,遇到同名的key,自然結(jié)果就會不同了。

      再談Cookie

      在博客【我心目中的Asp.net核心對象】中, 說到Request.Params[]時,我簡單地說了一句:而且更糟糕的是寫Cookie后,也會更新集合。 如何理解這句話呢?

      我想我們還是來看一下我們是如何寫一個Cookie,并發(fā)送到客戶端的吧。下面我就COPY一段 【細(xì)說Coookie】中的一段原文吧:


      Cookie寫入瀏覽器的過程:我們可以使用如下代碼在Asp.net項目中寫一個Cookie 并發(fā)送到客戶端的瀏覽器(為了簡單我沒有設(shè)置其它屬性)。

      HttpCookie cookie = new HttpCookie("MyCookieName", "string value");
      Response.Cookies.Add(cookie);
      

      代碼的關(guān)鍵點(diǎn)在于調(diào)用了Response.Cookies.Add(),我們來看看它們是如何實(shí)現(xiàn)的。首先來看Response.Cookies

      public HttpCookieCollection Cookies
      {
          get
          {
              if (this._cookies == null)
              {
                  this._cookies = new HttpCookieCollection(this, false);
              }
              return this._cookies;
          }
      }
      

      再來看HttpCookieCollection這個集合的實(shí)現(xiàn):

      public sealed class HttpCookieCollection : NameObjectCollectionBase
      {
          public HttpCookieCollection() : base(StringComparer.OrdinalIgnoreCase)
          {
          }
      
          internal HttpCookieCollection(HttpResponse response, bool readOnly) 
              : base(StringComparer.OrdinalIgnoreCase)
          {
              this._response = response;
              base.IsReadOnly = readOnly;
          }
      
          public void Add(HttpCookie cookie)
          {
              if (this._response != null)
              {
                  this._response.BeforeCookieCollectionChange();
              }
              this.AddCookie(cookie, true);
              if (this._response != null)
              {
                  this._response.OnCookieAdd(cookie);
              }
          }
      

      注意:由于在HttpResponse中創(chuàng)建HttpCookieCollection時,把HttpResponse對象傳入了,因此,在調(diào)用HttpCookieCollection.Add()方法時, 會調(diào)用HttpResponse的OnCookieAdd(cookie); 我們接著看:

      internal void OnCookieAdd(HttpCookie cookie)
      {
          this.Request.AddResponseCookie(cookie);
      }
      

      又轉(zhuǎn)到Request對象的調(diào)用了,接著看:

      internal void AddResponseCookie(HttpCookie cookie)
      {
          if (this._cookies != null)
          {
              this._cookies.AddCookie(cookie, true);
          }
          if (this._params != null)
          {
              this._params.MakeReadWrite();
              this._params.Add(cookie.Name, cookie.Value);
              this._params.MakeReadOnly();
          }
      }
      

      從以上的代碼分析中,我們可以看到,我們調(diào)用Response.Cookies.Add()時,Cookie也會加到HttpRequest.Cookies中。
      而且,如果我們訪問過程Request.Params[],也會加到那個集合中。

      再談NameValueCollection

      本文一開始的示例中,為什么代碼 ParamsValue = Request.Params["name"]; 得到的結(jié)果是:【abc,123】?

      根據(jù)前面示例代碼我們可以得知:abc這個值是由QueryString提供的,123這值是由Form提供的,最后由Request.Params[]合并在一起了就變成這個樣子了。 有沒有人想過:為什么合起來就變成了這個樣子了呢?

      要回答這個問題,我們需要回顧一下Params的定義:

      
      public NameValueCollection Params
      
      

      注意:它的類型是NameValueCollection 。MSDN對這個集合有個簡單的說明:

      此集合基于 NameObjectCollectionBase 類。但與 NameObjectCollectionBase 不同,該類在一個鍵下存儲多個字符串值。

      為了便于大家更容易理解這個類的工作方式,我畫了一張草圖:

      【name】這個key對應(yīng)差一個ArrayList,而那個ArrayList中,包含了二個字符串:abc 和 123 ,這就是它的工作方式。

      既然它能在一個鍵值下存儲多個字符串,那我們就來看一下它到底是如何實(shí)現(xiàn)的,直接轉(zhuǎn)到Add()方法:(注意我在代碼中添加的注釋)

      public virtual void Add(string name, string value)
      {
          if( base.IsReadOnly ) {
              throw new NotSupportedException(SR.GetString("CollectionReadOnly"));
          }
          this.InvalidateCachedArrays();
      
          // 這是一個關(guān)鍵的調(diào)用,它調(diào)用基類,得到每個name對應(yīng)的元素,
          // 而每個name對應(yīng)的元素是一個ArrayList
          ArrayList list = (ArrayList)base.BaseGet(name);
      
          if( list == null ) {
              // 如果不存在name對應(yīng)的元素,則創(chuàng)建ArrayList
              list = new ArrayList(1);
              if( value != null ) {
                  // 添加value到ArrayList,它將是第一個值
                  list.Add(value);
              }
              base.BaseAdd(name, list);
          }
          else if( value != null ) {
              // 在原有的ArrayList中繼續(xù)添加新的值
              list.Add(value);
          }
      }
      

      我們再來看一下當(dāng)我們訪問Params[]這個索引器時,.net framework又是如何實(shí)現(xiàn)的:

      public string this[string name]
      {
          get { return this.Get(name); }
          set { this.Set(name, value); }
      }
      public virtual string Get(string name)
      {
          // 根據(jù)name得到ArrayList
          ArrayList list = (ArrayList) base.BaseGet(name);
          // 將ArrayList變成一個字符串行
          return GetAsOneString(list);
      }
      
      private static string GetAsOneString(ArrayList list)
      {
          int num = (list != null) ? list.Count : 0;
          if( num == 1 ) {
              return (string)list[0];
          }
          if( num <= 1 ) {
              return null;
          }
          StringBuilder builder = new StringBuilder((string)list[0]);
          for( int i = 1; i < num; i++ ) {
              builder.Append(',');    // 逗號就來源于此。
              builder.Append((string)list[i]);
          }
          return builder.ToString();
      }
      

      現(xiàn)在,您該明白了為什么當(dāng)一個key有多個值時,為什么會用逗號分開來了吧。

      或許,看到這里,您又有了一個新的想法:對于有多值的情況,還要我來按逗號拆分它們,太麻煩了,有沒有不要拆分的方法呢?

      答案是:有的,您可以訪問NameValueCollection的GetValues方法,這個方法的實(shí)現(xiàn)如下:

      public virtual string[] GetValues(string name)
      {
          ArrayList list = (ArrayList)base.BaseGet(name);
          return GetAsStringArray(list);
      }
      private static string[] GetAsStringArray(ArrayList list)
      {
          int count = (list != null) ? list.Count : 0;
          if( count == 0 ) {
              return null;
          }
          string[] array = new string[count];
          list.CopyTo(0, array, 0, count);
          return array;
      }
      

      我想結(jié)果一定是您所期待的,它是一個string[] ,我們可以方便的遍歷它:

      
      string[] array = Request.Params.GetValues("name");
      if( array != null )
          foreach(string val in array)
          
      

      再談QueryString, Form

      前面我解釋了NameValueCollection的工作原理,并揭示了Request.Params["name"]; 得到【abc,123】這個結(jié)果的原因。
      事實(shí)上,這個怪異的結(jié)果有時并不只是Params會有,同樣的故事還可能由QueryString, Form這二個對象上演(最終會在Request[]那里也有體現(xiàn))。

      我還是拿【我心目中的Asp.net核心對象】的示例來說明吧:

      protected void Page_Load(object sender, EventArgs e)
      {
          string[] allkeys = Request.QueryString.AllKeys;
          if( allkeys.Length == 0 )
              Response.Redirect(
                  Request.RawUrl + "?aa=1&bb=2&cc=3&aa=" + HttpUtility.UrlEncode("5,6,7"), true);
      
          StringBuilder sb = new StringBuilder();
          foreach( string key in allkeys )
              sb.AppendFormat("{0} = {1}<br />", 
                  HttpUtility.HtmlEncode(key), HttpUtility.HtmlEncode(Request.QueryString[key]));
      
          this.labResult.Text = sb.ToString();
      }
      

      頁面最終顯示結(jié)果如下(注意鍵值為aa的結(jié)果):


      示例代碼中,開始部分用于檢查URL是否包含參數(shù),如果沒有,則加入一些參數(shù)。寫成這樣的原因是: 第一次訪問這個頁面時,URL中肯定是不包含參數(shù)的,為了能演示,所以我就加了一些固定的參數(shù),這樣便于后面的講解。

      這個示例也演示了:遇到同名的多個值,用逗號分開的做法,并不是Params才會有的,QueryString也可能會有, 當(dāng)然,F(xiàn)orm也逃不掉這個特性的纏繞,不過,我現(xiàn)在倒想舉個有使用價值的示例。

      我有這樣一個錄入界面(左邊),并希望最終的錄入結(jié)果以右圖的方式顯示:

      我想這個功能的實(shí)現(xiàn)并不難,但如何做才是最簡單呢?

      下面我貼出我的實(shí)現(xiàn)方法,大家看看算不算比較容易:

      
          <tr><td style="vertical-align: top">項目類型</td><td>
          <% foreach( string pt in AppHelper.ProjectTypes ) { %>
              <label><input type="checkbox" name="ProjectType" value="<%= pt %>" /><%= pt%></label><br />
          <% } %>
              </td></tr>
      
      

      注意:所有的checkbox的name都是一樣的。

      服務(wù)端嘛,我認(rèn)為沒有必要再貼代碼了,我想您懂的。

      在這個示例中,我正好利用了NameValueCollection的這個特點(diǎn),讓它幫我實(shí)現(xiàn)了這個逗號分隔的效果,要不然,我還得自己去做!

      如何處理沖突

      通過前面的一些示例,我們可以看到并非只有Params[]會有沖突,只要類型是NameValueCollection的數(shù)據(jù)源,都有這個問題。
      我要再重申一次:QueryString, Form,Param都有這樣的沖突問題,只是Param需要合并4種數(shù)據(jù)源,它將沖突的機(jī)率變大了。

      那么,我們?nèi)绾握_的處理這類沖突呢? 還記得我前面提到的NameValueCollection的GetValues方法吧,也只好用它了。(除非你愿意自己手工拆分字符串) 然后再用一個循環(huán)就可以訪問所有沖突值了,就像下面這樣:

      
      string[] array = Request.Params.GetValues("name");
      if( array != null )
          foreach(string val in array)
          
      

      注意:Request[]的返回結(jié)果是一個字符串,就不能使用這種方法。但是,它的沖突機(jī)率要少很多。

      現(xiàn)在,還有個現(xiàn)實(shí)的問題:QueryString, Form是最常用的數(shù)據(jù)源,我們要不要這樣處理它呢?
      這的確是個很現(xiàn)實(shí)的問題,我認(rèn)為在回答這個問題前,我們需要分析一下這二個集合出現(xiàn)KEY沖突時是個什么樣子的。

      1. "abc.aspx?id=1 &id=2" 在這URL中,我想問問各位:看到這個URL,您會怎么想?我認(rèn)為它是錯的,錯在拼接URL的操作中。 其次,我認(rèn)為URL的修改或者拼接通常由一個工具類來控制,我們有理由保證它不會出現(xiàn)沖突,畢竟范圍相應(yīng)較小,我們?nèi)菀捉o出這個保證。 因此,我認(rèn)為,直接訪問QueryString可以忽略這種沖突的可能。

      2. 表單數(shù)據(jù)中name重復(fù)的情況。我認(rèn)為這個集合倒是有可能出現(xiàn)沖突,但也極有可能是我們故意安排的,就像前面的示例一樣。 其次,表單的內(nèi)容在開發(fā)階段相對固定,各個輸入控件的name也是比較清楚的,不存在動態(tài)變換的可能,因此, 我認(rèn)為,直接訪問Form也可以忽略這種沖突的可能。

      另一方面,我們平時寫QueryString[], Form[]都太習(xí)慣了,這樣的代碼太多了,也不可能改成循環(huán)的判斷, 因此,我們只能盡量保證在一個數(shù)據(jù)源的范圍內(nèi),它們是不重復(fù)的。 事實(shí)上,前二個集合通常僅僅與某一個頁面相關(guān),范圍也相對較小,更容易保證。 因此,如果有了這個保證,在訪問這二類集合時,忽略沖突也是可接受的。

      但是,Params需要合并4種數(shù)據(jù)源,尤其是包含Cookies,ServerVariables這二類對象并非與某個頁面相關(guān),它們是全局的, 因此沖突的可能性會更大,所以,我認(rèn)為:如果您要訪問Params[],那么,請改成Params.GetValues() ,因為這樣才更合適。

      Request[]還是Request.Params[] ??

      前面說了這么多,我想Request[]和Request.Params[]的差別,這次應(yīng)該是說清楚了,到此也該給個結(jié)論了: 到底選擇Request[]還是Request.Params[] ??

      我想很多人應(yīng)該會比較關(guān)注這個答案,這里我也想說說我的觀點(diǎn),不過,我要說明一點(diǎn): 本文的所有文字,都只表示我的個人觀點(diǎn),僅供參考。

      我認(rèn)為:要想清楚地回答這個問題,有必要從二個角度再來觀察這二者:常見用法和設(shè)計原因。

      1. 常見用法: 我一直認(rèn)為設(shè)計這二個集合是為了方便,讓我們可以不必區(qū)分GET, POST而直接得到所需的用戶數(shù)據(jù)。 如果沒有這二個集合,而我們又需要不區(qū)分GET,POST時,顯然就要自己去實(shí)現(xiàn)這類的集合, 而在自己實(shí)現(xiàn)時,也極有可能是先嘗試訪問QueryString, 如果沒有,再去找Form ...。看到了嗎,這不正是Request[]的實(shí)現(xiàn)方式嗎? 也正是基于這個前提,遇到前面那種【abc,123】場景時,Request[]得到的結(jié)果或許更符合我們的預(yù)期。畢竟在獲取到結(jié)果后, 我們會基于結(jié)果做一些判斷,比如:name參數(shù)可能對應(yīng)一個數(shù)據(jù)庫的表字段,用它可以找到一個實(shí)際數(shù)據(jù)行, 如果結(jié)果是abc或者是123,這時程序都能處理(都有匹配的記錄),但來個【abc,123】,這個還真沒法處理了。

      另一方面,在前面的例子中,我也解釋了這并不是Params[]特有的,QueryString, Form都有這樣的問題,自然地Request[]也有這個問題, 只是由于Params需要合并4類數(shù)據(jù)源,讓這種沖突的機(jī)會更大了

      說到這里,有必要再來談?wù)勄懊娴膸讉€例子,【abc,123】中,name在QueryString, Form中重復(fù)了,顯然這屬于不合理的設(shè)計, 現(xiàn)實(shí)情況中,應(yīng)該是不會產(chǎn)生這類事情的,除非偶然。不過,當(dāng)偶然的不幸發(fā)生時,也正好能體現(xiàn)這二者的差別了。 至于我前面所舉的幾個例子,雖然在現(xiàn)實(shí)中不太可能會出現(xiàn),但我的意圖是在向您展示這些技術(shù)的細(xì)節(jié)差異, 展示一些可能偶然會發(fā)生的情況,因此,請不要認(rèn)為那是個技術(shù)誤導(dǎo)。

      2. 設(shè)計原因:讓我們再從設(shè)計嚴(yán)謹(jǐn)性這個角度來看待這二者的差別,還是拿【abc,123】這個例子來說吧, Request[]這種依次判斷的方式,顯然會遺漏一些信息,因此,從嚴(yán)謹(jǐn)性這個角度來看,Request[]是不完美的。 畢竟,最終用戶會如何以某種想法使用這二個API,沒人知道。微軟是設(shè)計平臺的,他們不得不考慮這個問題,不設(shè)計這二個集合, 是.net framework的不完善,用錯了,就是我們自己的錯了。

      基于以上觀點(diǎn),我給出我的4點(diǎn)意見:
      1. 不建議使用Params[],因為:a. 不希望被偶然情況影響,b. 較高的使用成本。
      2. Request[] 使用簡單,適合要求不高的場合:示例代碼。
      3. 如果需要兼顧性能和易用性,可以模仿Request[]自行設(shè)計。(通常并不需要訪問4個集合)
      4. 了解差異,體會細(xì)節(jié),有時會發(fā)現(xiàn)它還是有利用價值的。

      posted on 2011-12-06 21:06  Fish Li  閱讀(58723)  評論(65)    收藏  舉報
      主站蜘蛛池模板: 亚洲精品三区二区一区一| 亚洲国产欧美一区二区好看电影| 另类图片亚洲人妻中文无码| 午夜福利啪啪片| 国产日产亚洲系列av| 国语精品国内自产视频| 亚洲精品日韩久久精品| 男女裸交免费无遮挡全过程| 久久国产免费观看精品3| 亚洲中文字幕一区二区| 中国CHINA体内裑精亚洲日本| 亚洲精品av一二三区无码| 中年国产丰满熟女乱子正在播放 | 精品国产女同疯狂摩擦2| 国产性色的免费视频网站| 国产亚洲色婷婷久久99精品| 天天摸夜夜摸夜夜狠狠添| 亚洲av色图一区二区三区| 亚洲中文在线精品国产| 国产四虎永久免费观看| 国产情侣一区二区三区| 四虎国产精品永久在线下载| 人人综合亚洲无线码另类| 高清无打码一区二区三区| 色噜噜在线视频免费观看| 亚洲欧美人成人让影院| 欧美成人精品在线| 亚洲经典av一区二区| 亚洲成av人片色午夜乱码| 福利一区二区1000| 亚洲丶国产丶欧美一区二区三区 | 亚洲一区二区三区丝袜| 国产精品护士| 好看的国产精品自拍视频| 青草99在线免费观看| 日区中文字幕一区二区| 国产中年熟女高潮大集合| 99精品高清在线播放| 桃花岛亚洲成在人线AV| 精品国产成人网站一区在线| 亚洲欧美中文字幕5发布|