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

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

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

      Page,我想每個ASP.NET開發(fā)人員對它應該都是比較熟悉的。
      這次的博客我就打算專門談談它。 不過呢,我不打算說 在Page中使用控件的一些話題,也不會說Page的生命周期的相關話題, 因為我認為這些話題被人談論的次數(shù)實在是太多了,尤其是市面上的ASP.NET的書籍,都會比較喜歡這些話題。

      我不喜歡重復,因此今天我只想談些人家不談的那點事,但我認為它們?nèi)匀缓苤匾?

      一些重要的Page指令

      雖然Page公開了很多屬性,讓我們可以在運行時調(diào)整它的狀態(tài)與行為,但是,還有些重要的參數(shù)卻是以“指令”方式提供的,需要在設計時就指定。
      下面是我整理的一些我認為 比較重要并且經(jīng)常需要使用 的指令:

      @ Page 指令
      Async指示頁面要不要以異步頁的方式運行。默認值為 false。
      注意:如果需要開發(fā)一個異步頁,必須要設置這個指令屬性,以便在編譯頁面時實現(xiàn)IHttpAsyncHandler接口。
      AsyncTimeOut定義在處理異步任務時使用的超時時間間隔(以秒為單位)。默認值為 45 秒。 該值必須是整數(shù)。
      此屬性僅對Page.RegisterAsyncTask()方法有效。
      AutoEventWireup指示頁的事件是否自動綁定。如果啟用了事件自動綁定,則為 true;否則為 false。默認值為 true。
      所謂的事件自動綁定就是識別Page_Load這些類型的頁面事件處理程序。
      事件自動綁定發(fā)生在頁面第一次請求時,在后續(xù)請求中會使用緩存的委托調(diào)用列表,因此對性能的輕微影響也僅發(fā)生在第一次請求時。
      EnableSessionState定義頁的會話狀態(tài)要求。如果啟用了會話狀態(tài),則為 true;如果可以讀取會話狀態(tài)但不能進行更改,則為 ReadOnly;否則為 false。默認值為 true。
      建議不要保留默認值:
      1. 如果只是部分頁面需要使用Session,那么不需要使用Session的頁面請顯式設置為關閉狀態(tài),
      2. 對于不需要修改Session的頁面請設置為ReadOnly。
      頁面編譯時就是根據(jù)這個指令來決定生成對IRequiresSessionState,IReadOnlySessionState接口的實現(xiàn)關系。
      EnableViewState指示是否在頁請求之間保持視圖狀態(tài)。如果要保持視圖狀態(tài),則為 true;否則為 false。默認值為 true。
      強烈建議不要使用視圖狀態(tài),因為它解決的問題比引用的問題更多。
      MasterPageFile設置內(nèi)容頁的母版頁或嵌套母版頁的路徑。支持相對路徑和絕對路徑。
      可以在頁面的PreInit事件中動態(tài)設置同名的屬性實現(xiàn)動態(tài)切換母版頁的功能。
      Trace指示是否啟用跟蹤。如果啟用了跟蹤,則為 true;否則為 false。默認值為 false。
      啟用跟蹤對頁面調(diào)試非常有用,我們可以調(diào)用Page.Trace對象的方法輸出一些有價值的診斷信息。
      Page.Trace.Write()采用默認字體輸出,Page.Trace.Warn()采用紅色字體輸出。
      如果你總是記不住頁面生命周期,啟用跟蹤后,一切就擺在你眼前。
      ValidateRequest指示是否應發(fā)生請求驗證。如果為true,請求驗證將根據(jù)具有潛在危險的值的硬編碼列表檢查所有輸入數(shù)據(jù)。默認值為 true。
      如果希望用戶輸入HTML代碼,請設置為false 。
      注意:在ASP.NET 2.0中不驗證ashx請求,但是ASP.NET 4.0默認會驗證,
      如果希望在4.0中兼容2.0的行為,請在web.config中配置<httpRuntime requestValidationMode="2.0"/>
      其它指令
      @ Import導入允許您指定要在代碼中引用的命名空間。
      @ OutputCache設置頁面或者用戶控件的輸出緩存。
      @ Register聲明控件的標記前綴和控件程序集的位置。如果要向頁面添加用戶控件或自定義 ASP.NET 控件,可以使用此指令。

      web.config的全局設置

      前面我介紹了一些常用的Page指令,考慮到方便性,ASP.NET還允許我們在web.config中為一些常用的指令配置默認值。 下面我就一些常用的場景來說明這些全局配置的方便性。

      1. 通常,我在創(chuàng)建一個網(wǎng)站項目時,肯定會決定不使用ViewState和Session的。 那么如果為每個頁面設置EnableViewState,EnableSessionState指令屬性,那就顯得太麻煩了,而且還容易遺漏。 此時,我們可以直接在web.config中為這些參數(shù)指定一個全局的默認值:

      
      <pages enableViewState="false" enableSessionState="false"></pages>
      
      

      補充說明一下:全局禁用Session的徹底方法是把Session對應的HttpModule從httpModules列表中移除。

      web.config允許我們設置Page默認參數(shù)的具體配置節(jié)如下:

      2. 為了代碼重用,設計用戶控件也是很常用的方法。
      我們可以使用 @ Register指令 在頁面注冊需要使用的UserControl或者WebControl。 然而,有些控件比較通用,許多頁面都會使用它,那么就不要再使用 @ Register指令了,可以在web.config中統(tǒng)一注冊。例如:

      <pages>
          <controls>
              <add tagPrefix="fish" tagName="MainMenu" src="~/Controls/MainMenu.ascx" />
              <add tagPrefix="fish" tagName="PageHeader" src="~/Controls/PageHeader.ascx" />
          </controls>
      </pages>
      

      有了這個定義后,我就可以在任何頁面中直接使用:

      
      <fish:PageHeader runat="server" ID="PageHeader1" />
      
      

      3. 對于喜歡使用頁面內(nèi)聯(lián)代碼的人來說,可能經(jīng)常需要使用自己定義的類型。 如果這些類型定義在某個命名空間中,那么就需要在內(nèi)聯(lián)代碼中采用完整命名空間的寫法。 雖然這樣做沒有什么問題,但就是麻煩,于是,我們可以在頁面中使用 @ Import指令 來導入我們需要使用的命名空間, 但是這個指令每次只能導入一個命名空間,而且每個頁面還得重復導入,顯然不夠方便。

      為了方便使用一些常用的命名空間,我們可以在web.config中統(tǒng)一指定,例如:

      <pages>
          <namespaces>
              <add namespace="MyMVC" />
              <add namespace="WebSiteCommonLib" />
              <add namespace="WebSiteModel" />
          </namespaces>
      </pages>
      

      這樣設置后,所有頁面就可以直接使用這些命名空間下的類型了。

      不知道有些人想過:為什么在頁面中使用某些微軟提供的類型就不需要導入命名空間?
      答案是:其實ASP.NET已經(jīng)將一些微軟認為常用的命名空間在web.config中配置好了:

      4. 現(xiàn)在,有越來越多的人為了方便而使用擴展方法。使用擴展方法的好處是:可以讓我們不去關心這些擴展方法定義在那個類中, 只要在支持擴展方法的對象上調(diào)用就可以了,就像下面的代碼這樣:

      
      當前用戶已登錄,登錄名:<%= Context.User.Identity.Name.HtmlEncode() %>
      
      

      然而,在頁面中使用擴展方法時,也必須先導入擴展方法的定義類的命名空間。
      因此,為了方便,我們可以在web.config中為我們定義的擴展方法導入相應的命名空間:

      <pages>
          <namespaces>
              <add namespace="FishDemoCodeLib" />
          </namespaces>
      </pages>
      

      換個方式使用 Page

      在傳統(tǒng)的WEB開發(fā)模式下,我們通常會設計一些頁面(Page)響應來自用戶瀏覽器的請求, 在這種模式下,Page會將最后生成的整頁HTML代碼直接發(fā)送給用戶瀏覽器。 然而,在某些時候,我們只需要生成一個HTML片段:
      1. 在AJAX請求中,客戶端為了局部刷新,只要求服務端返回一個HTML片段。
      2. BigPipe方式下,為了能分塊輸出,每次也只需要輸出一個HTML片段。

      如果只是為了得到一段簡單的HTML代碼,可能有些人會選擇采用代碼來拼接,但是如果那段HTML還有些復雜呢? 顯然拼接方法肯定是不行的。

      對于第一個問題,可能有人說:我可以創(chuàng)建一個頁面,只放部分代碼到頁面上。
      的確,這種方法可以勉強解決第一個問題,但是,很有可能那部分代碼在整頁輸出時也會用到,怎么辦?
      做成UserControl,然后放在一個單獨的頁面中!
      其實這種做法很無奈,因為那個容器頁面的意義不大(僅僅是個容器),最后搞得項目中一大堆頁面文件!
      事實上,這種方法僅適用于使用簡單服務端控件的場合,如果想使用一些高級的服務端控件,它根本就不行。

      為了能實現(xiàn)前面說到的二個需求,我們就不能再按照傳統(tǒng)的方式來使用Page了。 因為我們希望能得到(返回)一段HTML。

      有二種方法可以讓我們繼續(xù)使用頁面模板代碼的方式生成HTML代碼:
      1. Server.Execute()方法。
      2. Page.RenderControl()方法。

      下面這段代碼來源于 MyMVC框架, 這個方法可以根據(jù)指定的用戶控件以及控件顯示所需的數(shù)據(jù)得到控件的輸出結果(一段HTML代碼)。

      /// <summary>
      /// 用指定的用戶控件以及視圖數(shù)據(jù)呈現(xiàn)結果,最后返回生成的HTML代碼。
      /// 用戶控件應從MyUserControlView<T>繼承
      /// </summary>
      /// <param name="ucVirtualPath">用戶控件的虛擬路徑</param>
      /// <param name="model">視圖數(shù)據(jù)</param>
      /// <returns>生成的HTML代碼</returns>
      public static string Render(string ucVirtualPath, object model)
      {
          if( string.IsNullOrEmpty(ucVirtualPath) )
              throw new ArgumentNullException("ucVirtualPath");
          
          Page page = new Page();
          Control ctl = page.LoadControl(ucVirtualPath);
          if( ctl == null )
              throw new InvalidOperationException(
                  string.Format("指定的用戶控件 {0} 沒有找到。", ucVirtualPath));
      
          if( model != null ) {
              MyBaseUserControl myctl = ctl as MyBaseUserControl;
              if( myctl != null )
                  myctl.SetModel(model);
          }
      
          // 將用戶控件放在Page容器中。
          page.Controls.Add(ctl);
      
          StringWriter output = new StringWriter();
          HtmlTextWriter write = new HtmlTextWriter(output, string.Empty);
          page.RenderControl(write);
      
          // 用下面的方法也可以的。
          //HttpContext.Current.Server.Execute(page, output, false);
      
          return output.ToString();
      }
      

      整段代碼分為以下幾個步驟(我已用空行分隔開了):
      1. 檢查參數(shù)。
      2. 創(chuàng)建頁面容器并加載用戶控件。
      3. 設置頁面(視圖)所需的顯示數(shù)據(jù)。
      4. 將用戶控件添加到Page的Controls集合中。
      5. 調(diào)用RenderControl或者Execute讓Page輸出HTML代碼。
      6. 返回結果。

      這段代碼很簡單,唯獨值得介紹的就是第5步,調(diào)用它們就可以得到控件輸出的HTML代碼。
      RenderControl或者Execute的差別在于:
      RenderControl不支持服務器控件,原因在于它利用了頁面的一種獨特編譯方式,我已在以前的博客中分析過了。
      Execute可以支持服務器控件,因為它會執(zhí)行一次完整的頁面生命周期。

      注意:上面這段代碼就算使用Execute,也只能支持部分簡單的服務器控件,因為一些復雜的服務器控件需要在HtmlForm中才能運行。 因此,如果需要支持所有的服務器控件,那么還必須創(chuàng)建HtmlForm對象,并調(diào)整包含關系,還有就是還需要去掉產(chǎn)生的多余HTML代碼。

      如果你需要生成整個頁面生成的HTML代碼,可以參考 MyMVC框架, 那里有實現(xiàn)這個功能的完整代碼。

      重新認識Eval()方法

      我想很多人都寫過類似下面的代碼:

      <asp:Repeater ID="repeater1" runat="server">
          <HeaderTemplate><ul></HeaderTemplate>
          <FooterTemplate></ul></FooterTemplate>
          <ItemTemplate>
              <li><%# Eval("OrderID")%><%# Eval("OrderDate")%><%# Eval("SumMoney")%>
              </li>
          </ItemTemplate>
      </asp:Repeater>
      

      在這里我要說的是 Eval() 的調(diào)用,還不是Repeater控件。

      Eval()不僅僅可以讀取一個綁定數(shù)據(jù)項的屬性,還可以去讀取DataTable中的一個數(shù)據(jù)列。而且還能完成更復雜的綁定計算:

      <li><%# Eval("OrderID")%><%# Eval("OrderDate")%><%# Eval("SumMoney")%>
          ,訂單中的第一個商品:<%# Eval("Detail[0].ProductName") %>
      </li>
      

      當然了,對于頁面上的數(shù)據(jù)綁定,用Eval()的確不是性能最好的方法,建議還是使用強類型轉換的方法。

      有時候,尤其是在寫反射應用時,時常會有從字符串解析并實現(xiàn)求值計算的需求。 那么,前面這個示例中,Eval()的功能是不是值得挖掘呢? 我認為答案是肯定的。

      通過分析ASP.NET的綁定代碼,我發(fā)現(xiàn)Eval在內(nèi)部會調(diào)用DataBinder.Eval這個靜態(tài)方法,這個方法的簽名如下:

      //     在運行時計算數(shù)據(jù)綁定表達式。
      //
      // 參數(shù):
      //   container:
      //     表達式根據(jù)其進行計算的對象引用。此標識符必須是以頁的指定語言表示的有效對象標識符。
      //
      //   expression:
      //     從 container 到要放置在綁定控件屬性中的公共屬性值的導航路徑。
      //     此路徑必須是以點分隔的屬性或字段名稱字符串,如 C# 中的 "Tables[0].DefaultView.[0].Price"
      //     或 Visual Basic 中的 "Tables(0).DefaultView.(0).Price"。
      //
      // 返回結果:
      //     System.Object,它是數(shù)據(jù)綁定表達式的計算結果。
      public static object Eval(object container, string expression);
      

      通過這個簽名的注釋,我們可以很容易地看出它的用法。
      下面我來舉個例子把它應用在非綁定的應用中:

      我有一個類:

      public class TestEvalClass
      {
          public List<Order> Orders { get; set; }
      
          // Order以及OrderDetail的定義就省略了,我想大家能想像得出來。
      }
      

      那么下面的代碼是可以運行的:

      static void Main()
      {
          TestEvalClass testObject = GetTestEvalClassInstance();
      
          string productName = (string)System.Web.UI.DataBinder.Eval(testObject, "Orders[0].Detail[0].ProductName");
          Console.WriteLine(productName);
      }
      

      對于這個示例,我想輸出什么結果,并不重要。
      我只想說:如果讓你去解析那個表達式,會不會比較麻煩,現(xiàn)在有現(xiàn)成的,用起來是不是很方便?

      不用基類也能擴展

      在一個ASP.NET網(wǎng)站中,如果想為所有的頁面添加某個功能,我們通常會想到使用基類的方式去實現(xiàn)。 這的確是一種很有效的方法,但不并唯一的方法,還有一種方法也能容易實現(xiàn)這個需求,那就是使用PageAdapter的方式。

      在我寫博客的過程中,我寫了很多示例頁面,頁面中包含一些提交按鈕是少不了的事情, 然而,為了能讓示例代碼看起來比較原始(簡單),我盡量不使用服務器控件,因此就要面臨提交按鈕的事件處理問題。 在博客【細說 ASP.NET Cache 及其高級用法】的示例代碼中, 我開始采用PageAdapter這種方法,它可以讓代碼很簡單,而且以后也方便以后重用(只需要復制幾個文件即可)。

      或許有些人認為:擴展所有頁面的功能,還是使用基類比較好。
      對于這個觀點,我完全不反對。
      但是,PageAdapter的好處在于它的可插拔性(類似HttpModule的優(yōu)點)。
      不過,我當時設計這種擴展方式只是想再換個方法嘗試一下而已。

      其實微軟設計PageAdapter的本意是為了處理各種瀏覽器的兼容問題,但是我把這個功能用到擴展Page的功能上去了。 HttpModule可以進入到ASP.NET請求管線的任何階段,但它就是進入不了頁面的生命周期中, 有了這個方法,我們就可以采用HttpModule這種【外掛】式的方法進入到頁面生命周期中, 我認為是很有意義的。

      方法多了,我想不是件壞事。每種方法都有適合它們的應用場合,了解更多的方法,以后就能做出更優(yōu)秀的設計。

      這次想到這個話題是因為前面的博客【細說ASP.NET Forms 身份認證】中的示例代碼。 有些人看到那些代碼,發(fā)現(xiàn)代碼的運行方式比較特別,所以,今天我就打算著重介紹這種方法。

      我們再來回顧一下以前博客中的示例代碼,首先從頁面代碼開始:

      <fieldset><legend>普通登錄</legend><form action="<%= Request.RawUrl %>" method="post">
          登錄名:<input type="text" name="loginName" style="width: 200px" value="Fish" />
          <input type="submit" name="NormalLogin" value="登錄" />
      </form></fieldset>
       
      <fieldset><legend>包含【用戶信息】的自定義登錄</legend>    <form action="<%= Request.RawUrl %>" method="post">
          <table border="0">
          <tr><td>登錄名:</td>
              <td><input type="text" name="loginName" style="width: 200px" value="Fish" /></td></tr>
          <tr><td>UserId:</td>
              <td><input type="text" name="UserId" style="width: 200px" value="78" /></td></tr>
          <tr><td>GroupId:</td>
              <td><input type="text" name="GroupId" style="width: 200px" />
              1表示管理員用戶
              </td></tr>
          <tr><td>用戶全名:</td>
              <td><input type="text" name="UserName" style="width: 200px" value="Fish Li" /></td></tr>
          </table>    
          <input type="submit" name="CustomizeLogin" value="登錄" />
      </form></fieldset>
      

      在這段頁面代碼中,我定義了二個表單,它們包含各自的提交按鈕(其實這也只是部分代碼)。
      再來看后臺處理代碼是如何響應提交請求的:

      public partial class _Default : System.Web.UI.Page 
      {
          [SubmitMethod(AutoRedirect = true)]
          public void NormalLogin()
          {
              // 省略登錄處理代碼。
              // 如果需要知道這段代碼可以瀏覽下面的網(wǎng)址:
              // http://www.rzrgm.cn/fish-li/archive/2012/04/15/2450571.html 
          }
      
          [SubmitMethod(AutoRedirect = true)]
          public void CustomizeLogin()
          {
              // 省略登錄處理代碼。
              // 如果需要知道這段代碼可以瀏覽下面的網(wǎng)址:
              // http://www.rzrgm.cn/fish-li/archive/2012/04/15/2450571.html 
          }
      

      注意觀察,這二個C#方法的名稱與頁面二個submit按鈕的name屬性相同,因此可以猜測到這二個C#方法可以處理那二個submit按鈕的提交請求。 那么這二段代碼是如何運行起來的呢?有些人或許看到了[SubmitMethod]的使用,認為與它們有關。 其實這種說法并不正確,我也可以完全不使用它們。請記住:Attribute永遠只是一個標記,它不可能讓代碼自動運行起來。

      前面的代碼能運行起來,與App_Browsers目錄下的Page.browser文件有關,此文件的代碼如下:

      <browsers>
          <browser refID="Default">
              <controlAdapters>
                  <adapter controlType="System.Web.UI.Page"
                           adapterType="FishDemoCodeLib.MyPageAdapter, FishDemoCodeLib" />
              </controlAdapters>
          </browser>
      </browsers>
      

      這里定義了一個MyPageAdapter,它用于Page控件的請求過程。 refID="Default" 表示是對ASP.NET定義的Default.browser文件補充一些配置,它將能匹配來自所有瀏覽器的請求。
      我再來看一下MyPageAdapter的代碼:

      [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
      public class SubmitMethodAttribute : Attribute
      {
          public bool AutoRedirect { get; set; }
      }
      
      internal sealed class MethodInvokeInfo
      {
          public MethodInfo MethodInfo;
          public SubmitMethodAttribute MethodAttribute;
      }
      
      public class MyPageAdapter : System.Web.UI.Adapters.PageAdapter
      {
          private static readonly Hashtable s_table = Hashtable.Synchronized(new Hashtable());
      
          private static MethodInvokeInfo[] GetMethodInfo(Type type)
          {
              MethodInvokeInfo[] array = s_table[type.AssemblyQualifiedName] as MethodInvokeInfo[];
              if( array == null ) {
                  array = (from m in type.GetMethods(BindingFlags.Instance | BindingFlags.Public)
                           let a = m.GetCustomAttributes(
                                  typeof(SubmitMethodAttribute), false) as SubmitMethodAttribute[]
                           where a.Length > 0
                           select new MethodInvokeInfo { 
                                  MethodInfo = m, MethodAttribute = a[0] }).ToArray();
      
                  s_table[type.AssemblyQualifiedName] = array;
              }
              return array;
          }
      
      
          protected override void OnLoad(EventArgs e)
          {
              base.OnLoad(e);
      
              if( Page.Request.Form.AllKeys.Length == 0 )
                  return;    // 沒有提交表單
      
              MethodInvokeInfo[] array = GetMethodInfo(Page.GetType().BaseType);
              if( array.Length == 0 )
                  return;
      
              foreach( MethodInvokeInfo m in array ) {
                  if( string.IsNullOrEmpty(Page.Request.Form[m.MethodInfo.Name]) == false ) {
                      m.MethodInfo.Invoke(Page, null);
      
                      if( m.MethodAttribute.AutoRedirect 
                                      && Page.Response.IsRequestBeingRedirected == false )
                          Page.Response.Redirect(Page.Request.RawUrl);
      
                      return;
                  }
              }
          }
      }
      

      這段代碼并不長,核心代碼更是比較少。
      代碼中,最重要的一塊是MyPageAdapter的實現(xiàn),它繼承了System.Web.UI.Adapters.PageAdapter, 并重寫了OnLoad方法(相當是在重寫Page的OnLoad方法),也正是由于這個重寫, 代碼才有機會在頁面的生命周期中被執(zhí)行,這一點是HttpModule做不到的。
      在OnLoad方法中做了以下事情:
      1. 檢查是不是發(fā)生了表單提交的操作。
      2. 獲取當前頁面類型的所有[SubmitMethod]修飾過的方法。
      3. 檢查提交的表單數(shù)據(jù)中,是否存在與name對應的C#方法名。
      4. 如果找到一個匹配的方法名,則調(diào)用。
      5. 如果在[SubmitMethod]中設置了AutoRedirect=true,則引發(fā)重定向。

      注意:如果不調(diào)用base.OnLoad(e); 那么頁面的Load事件根本不會發(fā)生。
      也就是說:PageAdapter.OnLoad的調(diào)用時間要早于Page.Onload方法。

      由于這段代碼僅供我寫示例代碼時使用,因此并沒有檢查要調(diào)用的方法的參數(shù)是否滿足條件,也沒有優(yōu)化刻意去優(yōu)化它的性能。 在我的設計中,被調(diào)用的方法應該是無參的,因此是容易判斷的,而且可以使用一個固定簽名的委托去優(yōu)化它的,這些細節(jié)留著以后再去完善它吧!

      posted on 2012-06-10 17:01  Fish Li  閱讀(33693)  評論(106)    收藏  舉報
      主站蜘蛛池模板: 九九热在线观看免费视频| 国产成人免费午夜在线观看| 色爱综合另类图片av| 老师破女学生处特级毛ooo片| 亚洲av久久精品狠狠爱av| 亚洲日韩亚洲另类激情文学| 99精品人妻少妇一区二区| 光泽县| 青青草国产精品一区二区| 亚洲精品二区在线播放| 亚洲欭美日韩颜射在线二 | 欧美牲交a欧美牲交aⅴ图片| 国产热A欧美热A在线视频| 蜜臀av午夜精品福利| 国产视频一区二区三区视频| 狠狠干| 亚洲精品美女久久久久9999| 国产区一区二区现看视频| 国产日韩一区二区天美麻豆| 中文字幕日韩精品有码| 蜜臀av性久久久久蜜臀aⅴ麻豆| 无码人妻人妻经典| 沈阳市| 欧美丰满熟妇xxxx性ppx人交| AV区无码字幕中文色| 中文文字幕文字幕亚洲色| 色翁荡息又大又硬又粗又视频图片| 成人国产精品中文字幕| 国产一区二区三区小说| 亚洲国产成人久久精品不卡| 国产不卡一区二区四区| 台南市| 国产gaysexchina男外卖| 男同精品视频免费观看网站| 桐乡市| 国产精品毛片一区二区| 日韩人妻无码精品久久久不卡| 国产办公室秘书无码精品99| 天堂网在线.www天堂在线资源 | 欧美激情a∨在线视频播放| 18禁精品一区二区三区|