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

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

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

      為WebForms說幾句話,以及一些ASP.NET開發上的經驗(2)

      2007-12-22 22:41  Jeffrey Zhao  閱讀(15878)  評論(150)    收藏  舉報

      沒想到我的文章引起了那么大的反應,看來最近MVC框架的確是一個熱門話題。正如上一篇文章開始所說的,我不會對MVC框架有任何“貶低”,任何技術濫用都有問題,所以任何東西都會有所謂的Best Practice(去MSDN的Patterns & Practice欄目看看就知道了)。我寫這幾篇文章,是想說明,很多WebForms的缺點是被夸大了。WebForms的確有缺點,但是我們完全可以避開,并且僅僅利用到WebForms給我們帶來的便利。這其實也是一種Best Practice。相信以后MVC框架也一定會出現這樣的東西。

      在上一篇的評論中,有朋友說我是“邊緣”的ASP.NET程序員,大概是因為我用WebForms但是拋棄ViewState、PostBack和GridView這種“重要”的東西吧。我不知道這樣是不是“邊緣”,但是我的確拋棄了不少東西。例如還有ADO.NET中的DataSet/DataTable——但是我們還有DataReader呢!拋棄了微軟提供的一部分東西,我們其實可以發現,.NET里的基礎組件一個都不少,用起來也會得心應手。

      去其糟粕,取其精華。

      三、生成丑陋的HTML,難以進行樣式控制

      在ASP.NET的WebForms剛出現時,各種“演示”看上去真的很美。這個特點微軟至今還保留著,各微軟技術大會上的演示真的讓人感到心潮澎湃。在我看來,那些“激素大會”更是一種推廣策略,而并沒有將目光集中在技術細節的本身。所以微軟的東西似乎總是有入門容易提高難的“毛病”。開發人員被“寵壞”了,上一篇文章中有位朋友說這就是“窮人的孩子早當家”,還是有一定道理的。在.NET環境下我們就像是官宦子弟,不過這并不能成為我們習慣于“吃喝嫖賭”的理由。我們要合理利用富裕的環境帶給我們的資源,但是要適當地拋棄一些不好的東西。

      好像說了幾句廢話,現在進入正題。說到WebForms則不得不提豐富的控件,基于ASP.NET平臺的第三方控件提供商似乎比其他平臺下的總合還要多,這也是產業阿。在微軟提供的控件里,GridView(或者1.1里的DataGrid)是被“演示”次數最多的,也似乎是最強大(還是差不多等同于“復雜”)的。有了GridView之后,很多開發人員就習慣于朝頁面上拖個控件,然后再設計器里點點鼠標,設設樣式,最后綁定一個DataTable上去。嘩,好一個表格就此誕生。然后我們還可以響應其事件,對某一行數據進行編輯,刪除。太輕松了,這世界一下子變得美好了起來。不過由于GridView過于“強大”,它幾乎成為了ASP.NET初學人員的必修課,當對于Web開發都不明就里的初學者都習慣于GridView、GridView、GridView時,它的濫用也就不可避免了。于是乎,做表格,用GirdView,做列表,也用GirdView(不就是個只有一列的表格嘛)。

      可惜的是,GridView有很多毛病。如果要使用GridView的高級功能(添加、修改、刪除等等),ViewState必不可少,再加上很多開發人員在綁定數據時沒有經過篩選,導致ViewState變得無比龐大(例如顯示一個文章列表,明明只需要ID、標題,創建時間等基本信息,卻用一個“令人無比愉悅”的SELECT * FROM Article語句把文章內容也選擇了出來并綁定在GridView上,ViewState中也就不得不包含幾千幾萬字的多余數據)。

      不過現在想說的,倒是它生成出的HTML。

      GridView在客戶端生成的HTML是個<table />,可惜這個<table />里東西太多了,的確顯得很丑陋。不過更關鍵的在于,這個表格的樣式實在難以控制。雖說GridView里從標題到單元格到低部都能夠進行樣式的定義,但是靈活度還是遠遠不夠。再加上GridView生成的HTML死板而不符合Web標準(例如不會生成<th />標簽,用ControlAdaptor進行改造的做法不算),但是優秀的樣式開發人員大都是堅定的Web標準支持或推廣者,ASP.NET對于標準支持不佳,難以控制樣式的說法滿天飛揚。

      我想為WebForms喊冤。不過首先我會打倒以GridView為首的復雜控件(包擴DataList、FormView等等)并狠狠踩上幾腳。有人說,當拋棄了GridView之后,用WebForms還有什么意義?其實類似的話也不斷在我說要拋棄ViewState和(復雜)的PostBack時出現。如果您覺得拋棄了這些東西WebForms就失去意義的話,那么我想說,ViewState、PostBack、GridView遠不是WebForms的全部。我認為,Control模型(或者說組件化模型)才是WebForms的關鍵。而這個模型的“基礎”是絕對優秀的。下面我會進行一些展示,雖然這些展示我覺得是基礎中的基礎。

      首先我們先來看一下最常用的用戶控件的表現吧(DemoControl.ascx):

      <%@ Control Language="C#" AutoEventWireup="true" %>

      <%= "Hello World!" %>

      然后將它放在頁面里:

      <div> 
          <uc1:DemoControl ID="DemoControl1" runat="server" />
      </
      div>

      在瀏覽器里打開頁面會發現如下的代碼:

      <div> 
          Hello World!
      </
      div>

      多干凈的代碼,我甚至連多余的空格都沒有去除。還有一個例子就是Master Page,<asp:ContentPlaceHolder />也不會產生任何多余的代碼。這說明了使用用戶控件搭出的WebForms頁面,是不會出現多余的“臟”代碼的。如果您在觀察那些基礎控件,TextBox,CheckBox(不設Text屬性),Panel等等,亦或是加上runat=server的HTML元素,無一例外(當然客戶端ID的確還是比較長,關于這個問題我會在以后的文章進行討論)。

      那么骯臟的Tag是哪里來的呢?當然是以GridView為首的復雜控件。那么如果我們要生成批量數據,又該怎么辦呢?現在來看看Repeater的表現吧,就以最常見的無序列表為例:

      <asp:Repeater runat="server" ID="rptItems">
          <HeaderTemplate>
              <ul>
          </HeaderTemplate>
          <ItemTemplate>
              <li>
                  <img src="<%# Eval("ImagePath")) %>" alt="<%# Eval("Title") %>" />
              </li>
          </ItemTemplate>
          <FooterTemplate>
              </ul>
          </FooterTemplate>
      </asp:Repeater>

      還是在瀏覽器里察看HTML(我這里就不貼出來了),一行多余的代碼也沒有。

      Repeater是ASP.NET 2.0中我最喜歡用的控件,它的功能很簡單,把ItemTemplate和AlternatingItemTemplate的內容返回生成在頁面上,并且將HeaderTemplate和FooterTemplate的內容顯示在頭尾。除此之外——沒了。但是這已經足夠了,對于綁定控件來說,還需要什么呢?這里面每一行代碼都由我們自己編寫,想定義樣式也易如反掌,我們對于HTML的控制沒有任何損失。

      另外,有些開發人員總認為ASP.NET中的DataTable綁定的方式讓我們無法寫出建模良好的代碼。就算使用ObjectDataSource,在控制上也會有諸多不便。但這個也是一種誤解,我們完全可以將領域模型中的對象綁定到視圖里的控件上。首先是ASPX的內容:

      <asp:Repeater runat="server" ID="rptItems">
          <HeaderTemplate>
              <ul>
          </HeaderTemplate>
          <ItemTemplate>
              <li>
                  <img src="<%# this.GetImagePath(Container.DataItem) %>"
                      alt="<%# Eval("Title") %>" />

              </li>
          </ItemTemplate>
          <FooterTemplate>
              </ul>
          </FooterTemplate>
      </asp:Repeater>

      然后是Code Behind:

      public partial class _Default : System.Web.UI.Page
      {
          protected void Page_Load(object sender, EventArgs e)
          {
              this.rptArticles.DataSource = this.GetArticles();
              this.rptArticles.DataBind();
          }

          protected string GetImageUrl(object dataItem)
          {
              return "http://img.jeffz.net/" + (dataItem as Article).ImagePath;
          }
      }

      GetArticles方法的返回值可以是List<Article>或任何一個實現了IEnumerable<Article>接口的類型,這個樣在ItemTemplate中訪問Container.DataItem就會得到這個Article對象。我們在Code Behind類里定義一個protected方法,由于aspx最終會被編譯為Code Behind類的子類,因此我們就可以在ASPX頁面中調用GetImageUrl方法。在方法內部我們可以將object類型的DataItem轉換成Article類型的對象,然后就可以做任意的處理了。

      非常方便,非常靈活,還有什么可挑剔的呢?。

      有。比如我們想要使用每行10個元素,最后一行如果不足就讓右邊空著的方式來展示,Repeater可能就難以實現了(其實不能這么說,按標準應該還是使用無序列表,用樣式來進行控制,Repeater完全夠用)。ASP.NET 1.1和2.0可能我們會使用DataList控件,只要把RepeaterColumns屬性設為10即可。可惜DataList生成的元素要么是<table />,要么是<span />和<br />,讓人頭疼。但是在ASP.NET 3.5中又多了一個ListView控件,使用這個控件進行展示可以分組循環,可以指定容器,真可謂無比強大。重要的是ListView和Repeater一樣,所有的HTML都由自己控制,一個多余的字符都沒有。

      有了Repeater和ListView,真可謂打遍天下無敵手,任何頁面的展示方式都不在話下。

      我們再走個極端吧,我們來看下面的呈現方式:

      <ul> <% foreach (Article article in this.GetArticles())
         { %>
              <li>
                  <img src="<%= "http://img.jeffz.net/" + article.ImagePath %>"
                      alt="<%= article.Title %>" />
              </li>
      <% } %>
      </ul>

      上面的例子在ASPX頁面中使用了內聯的foreach語句進行顯示。這樣生成代碼無論從干凈還是自定義角度來說,都可以的讓任何開發方式“無地自容”。但關鍵是,這個方式……為什么……恩,沒錯,說的難聽,這是原始的ASP的開發方式;說的好聽,這是“先進”ASP.NET MVC框架中模板的寫法。這是不是很諷刺?但是這個的確是事實。Rick Strahl大牛也在他的Blog中寫到:“我還記得在早些時候,那些ASP.NET的瘋狂追隨者們是多么不屑使用內聯的腳本標簽,或者使用顯式的URL而不是PostBack來進行開發的做法,而其中的一些人現在又毫不猶豫地張開雙臂去迎接MVC框架,這難道不諷刺嗎?”而且由于ASP.NET MVC的特性(從Controller傳遞到View的只是一個ViewData對象),因此真正ASP.NET MVC的“模板”的寫法還要多一次Cast,也就是類似于如下的寫法(當然ASP.NET MVC可以使用強類型的ViewData,這樣就免去了這樣強行的Cast):

      <ul> <% foreach (Article article in (ViewData["Articles"] as List<Article>))
         { %>
              <li>
                  <img src="<%= "http://img.jeffz.net/" + article.ImagePath %>"
                      alt="<%= article.Title %>" />
              </li>
      <% } %>
      </ul>

      這里就要談到ASP.NET MVC了。其實光從View上來看,我不知道這算不算是進步(當然其實我不介意內聯的寫法,有時候反而更清晰)。ASP.NET MVC如果光從View(模板)方式來看,有點回到了當年的ASP方式(當然,還是補充了一些Helper)。ASP.NET MVC的特點在于M-V-C的分離,在于業務邏輯的觸發方式,在于URL Routing的驅動方式,而不是模板化的寫法。如果要說MVC在View層面比ASP.NET清晰,我是肯定不會同意的,因為我完全可以在WebForms的ASPX頁面中“寫成”ASP.NET MVC類似的方式。不知道您是否同意,至少我認為,使用WebForms內Repeater或ListView的寫法,不會輸給ASP.NET MVC的模板。而且事實上,在ASP.NET MVC中作為View使用的aspx頁面里,我們完全也可以放置Repeater,然后再Page_Load方法里寫代碼,這更證明了,在View方面WebForms和ASP.NET MVC其實是非常相似的。

      剛才說了,ASP.NET MVC的重要特點,在于M-V-C之間的分離,非常清晰,而且Model和Controller之間能夠進行獨立的測試。但是WebForms也可以做到這一點,我在后面的文章中還會談一下WebForms里如何使用MVC來做到清晰、分離和單元測試等等。而且,我似乎覺得某些WebForms中能夠做到的東西在MVC框架里卻無法或者很難實現。可能是我對于MVC的了解程度還不夠多的緣故吧,等我先研究了MVC框架之后再說。:)

      講到這里,您心中是否有了答案,WebForms究竟能否寫出清晰美觀的HTML?在WebForms控制樣式是否困難?拋棄GridView,我們并沒有什么損失,因為現在的網頁中又有多少會用到GridView的功能呢?

      目前老趙在公司使用WebForms開發時會與一個專職的前臺開發人員配合。他是我認識的最好的前臺開發人員,編程能力強,經驗豐富,對于各種瀏覽器中腳本和樣式的差異和問題可謂了如指掌,只是在這之前他只用過PHP,并沒有接觸過ASP.NET WebForms。但是僅僅向他解釋了幾個控件生成HTML的方式,或者如何從服務器端獲得ClientID之后,我們之間的配合就非常輕松順暢了。無論是開發人員先寫放控件然后由他進行修飾,還是他先寫靜態樣式頁面我們再進行替換,都工作的非常順利。我現在已經能夠專注于業務的實現,架構的設計,而徹底從頁面樣式的“泥潭”中解放了出來,最多編寫一下簡單的JavaScript代碼。分工的明確,也使得我們的工作效率得到了相當的提高。

      所以最后我給大家的建議就是,盡可能地使用“純粹”的服務器端控件。例如使用Repeater和ListView,其實寫出優秀的頁面非常容易。當然,即使這么做,還是會有一些缺點的,例如:

      1. 例如Repeater的ItemCommand事件已經無法使用了,因為它會用到ViewState。但是我們開發的大部分的頁面甚至連PostBack都不需要,這又有什么關系呢?
      2. 使用服務器端控件雖然能讓我們對于HTML有十足的控制,但是我們無法避免在客戶端生成一個不規則的ID。這一點理論上可能會影響頁面樣式的開發,但是就我那前臺開發人員同事的話來說,除了一些在客戶端進行布局的DOM元素之外,幾乎不會使用ID來控制樣式。就我們工作的結果來看,不規則的ID也并沒有造成任何的影響。

       

      相關文章:

      為WebForms說幾句話,以及一些ASP.NET開發上的經驗(1):ViewState、性能

      為WebForms說幾句話,以及一些ASP.NET開發上的經驗(3):生成復雜的ID難以使用JavaScript操作

      未完待續:

      五、MVC

      六、單元測試

      主站蜘蛛池模板: 午夜福利片1000无码免费| 国产精品白丝久久av网站| 最新精品国偷自产在线美女足| 无码免费大香伊蕉在人线国产| 久久99热只有频精品8| 69天堂人成无码免费视频| 精品午夜福利在线视在亚洲| 成人免费看片又大又黄| 年轻女教师hd中字3| 欧美牲交a欧美在线| 国产亚洲精品黑人粗大精选| 亚洲AV国产福利精品在现观看| 色噜噜亚洲男人的天堂| 张北县| 被灌满精子的少妇视频| 亚洲精品久久7777777国产| 怡红院一区二区三区在线| 高颜值午夜福利在线观看| 日本一区二区精品色超碰| 亚洲精品欧美综合二区| 国产一区二区三区精美视频| 长兴县| 亚洲国产欧美一区二区好看电影| 草草浮力地址线路①屁屁影院| 亚洲第一国产综合| 狠狠五月深爱婷婷网| 国产在线观看网址不卡一区| 国产午夜福利小视频在线| 2020久久香蕉国产线看观看| 你懂的在线视频一区二区| 成人3D动漫一区二区三区| 翘臀少妇被扒开屁股日出水爆乳| 起碰免费公开97在线视频| 免费观看欧美猛交视频黑人| 色悠悠国产精品免费在线| 午夜天堂av天堂久久久| 亚洲熟女乱综合一区二区| 日日噜噜夜夜狠狠视频| 亚洲成在人线AⅤ中文字幕| 亚洲av永久无码精品天堂久久| 国产做a爱片久久毛片a片|