国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > .NET > 正文

在ASP.NET中實(shí)現(xiàn)Model-View-Controller模式(1)

2024-07-10 13:10:52
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

  背景:

  當(dāng)利用asp.net創(chuàng)建web應(yīng)用程序時(shí),基于程序的復(fù)雜性,必須把程序分割成不同的部分以減少代碼的重復(fù)及減少日后變革時(shí)所引起的改動(dòng)。

 實(shí)現(xiàn)策略:

 為了解釋如何在asp.net中實(shí)現(xiàn)(mvc)模型-視圖-控制器模式,以及說(shuō)明將軟件分離成模型、視圖、及控制器角色的好處,在此以一個(gè)示例程序?yàn)槔M(jìn)行說(shuō)明。這個(gè)示例程序是一個(gè)帶有下拉框的單頁(yè)程序,它的功能是顯示數(shù)據(jù)庫(kù)中的數(shù)據(jù)。

  當(dāng)用戶(hù)在下拉框中選擇了一個(gè)記錄,并單擊submit按鈕的時(shí)候,程序從數(shù)據(jù)庫(kù)中搜索與選中記錄相關(guān)的數(shù)據(jù)庫(kù)記錄,并以列表的形式顯示出來(lái)。下面,將以三種不同的實(shí)現(xiàn)方式進(jìn)行實(shí)現(xiàn)。

  單頁(yè)模式

  在asp.net中有許多解決這個(gè)問(wèn)題的辦法,其中最簡(jiǎn)單也是最直接的辦法就是把所有的代碼都放到一個(gè)文件中,并起名為solution.aspx,實(shí)現(xiàn)代碼如下:

  <%@ import namespace="system.data" %>
  
  <%@ import namespace="system.data.sqlclient" %>
  
  <html>
  
  <head>
  
  <title>start</title>
  
  <script language="c#" runat="server">
  
  void page_load(object sender, system.eventargs e)
  
  {
  
  string selectcmd = "select * from recording";

sqlconnection myconnection =
  
  new sqlconnection(
  
  "server=(local);database=recordings;trusted_connection=yes");
  
  sqldataadapter mycommand = new sqldataadapter(selectcmd,
  
  myconnection);

dataset ds = new dataset();
  
  mycommand.fill(ds, "recording");

recordingselect.datasource = ds;
  
  recordingselect.datatextfield = "title";
  
  recordingselect.datavaluefield = "id";
  
  recordingselect.databind();
  
  }

void submitbtn_click(object sender, eventargs e)
  
  {
  
  string selectcmd =
  
  string.format(
  
  "select * from track where recordingid = {0} order by id",
  
  (string)recordingselect.selecteditem.value);

sqlconnection myconnection =
  
  new sqlconnection(
  
  "server=(local);database=recordings;trusted_connection=yes");

sqldataadapter mycommand = new sqldataadapter(selectcmd,
  
  myconnection);

dataset ds = new dataset();
  
  mycommand.fill(ds, "track");

mydatagrid.datasource = ds;
  
  mydatagrid.databind();
  
  }
  
  </script>
  
  </head>
  
  <body>
  
  <form id="start" method="post" runat="server">
  
  <h3>recordings</h3>
  
  select a recording:<br />
  
  <asp:dropdownlist id="recordingselect" runat="server" />
  
  <asp:button runat="server" text="submit" onclick="submitbtn_click" />
  
  <p/>
  
  <asp:datagrid id="mydatagrid" runat="server" width="700"
  
  backcolor="#ccccff" bordercolor="black" showfooter="false"
  
  cellpadding="3" cellspacing="0" font-name="verdana"
  
  font-size="8pt" headerstyle-backcolor="#aaaadd"
  
  enableviewstate="false" />
  
  </form>
  
  </body>
  
  </html>

 這個(gè)實(shí)現(xiàn)文件包含了模型、視圖、控制器這三種角色,但是沒(méi)有將它們分割為不同的文件或類(lèi)。其中的視圖對(duì)象用html實(shí)現(xiàn),用一個(gè)數(shù)據(jù)綁定控件來(lái)顯示從數(shù)據(jù)庫(kù)返回的dataset中的數(shù)據(jù)。模型角色在page_load 和 submitbtn_click函數(shù)中實(shí)現(xiàn)。而控制器角色并沒(méi)有顯式的實(shí)現(xiàn),而是由asp.net隱式實(shí)現(xiàn)。程序運(yùn)行時(shí),當(dāng)用戶(hù)發(fā)出頁(yè)面的請(qǐng)求,頁(yè)面隨著用戶(hù)的選擇更新。

 mvc模式形容這種實(shí)現(xiàn)方式是一種被動(dòng)的實(shí)現(xiàn)機(jī)制,asp.net充當(dāng)了程序執(zhí)行中的控制器的角色,但程序員必須將具體的事件處理方法添加到事件的響應(yīng)函數(shù)中。如在這個(gè)例子中,控制器在頁(yè)面加載之前調(diào)用page_load函數(shù)并執(zhí)行其中的代碼,當(dāng)用戶(hù)點(diǎn)擊submit按鈕時(shí)由系統(tǒng)調(diào)用submitbtn_click函數(shù)并執(zhí)行。

 這種將代碼都包含在一個(gè)文件中的實(shí)現(xiàn)方式非常的直接,而且當(dāng)應(yīng)用程序很小并不經(jīng)常修改的時(shí)候也可以說(shuō)是一種好的方法,但是如果下面的一些情況出現(xiàn)的話(huà)你也許會(huì)開(kāi)始考慮修改這種實(shí)現(xiàn)方法:

 使編程的工作并行并減少由此帶來(lái)的發(fā)生錯(cuò)誤的可能性。為了增加工作的并行性,提高效率,你可能想讓不同的人編寫(xiě)視圖的代碼及模型代碼并盡力減少這種工作方式所帶來(lái)的出錯(cuò)的可能性。例如:當(dāng)所有的代碼都在一個(gè)文件中的話(huà),那么一個(gè)編程人員可能會(huì)在改變datagrid顯示格式的時(shí)候無(wú)意中修改數(shù)據(jù)訪問(wèn)的代碼。這種錯(cuò)誤是很難被發(fā)現(xiàn)的,直到頁(yè)面整體被編譯的時(shí)候才會(huì)顯現(xiàn)出來(lái)。。

 使你的數(shù)據(jù)訪問(wèn)代碼在其它頁(yè)面中重用。在這種單文件的實(shí)現(xiàn)方式中,除了拷貝代碼,沒(méi)有其它的方法能夠做到代碼的重用。拷貝的代碼是很難被維護(hù)的,因?yàn)橐坏┐a發(fā)生了變化,你必須在所有的頁(yè)面都進(jìn)行修改。

 為了避免上面這些情況的發(fā)生,asp.net引入了代碼分離(code-behind)機(jī)制。

 用代碼分離機(jī)制進(jìn)行重構(gòu)
  
  microsoft visual studio .net中的代碼分離機(jī)制使視圖層的代碼與模型及控制器的代碼能夠很容易的分離。每個(gè)asp.net頁(yè)面都有一種機(jī)制,能夠使其要調(diào)用的方法在一個(gè)與其分離的類(lèi)中實(shí)現(xiàn)。這種方式使用起來(lái)非常的方便,而且也可以利用visual studio .net中的一些其它特性共同完成開(kāi)發(fā)工作。比如如當(dāng)你利用代碼分離的機(jī)制開(kāi)發(fā)你的頁(yè)面的時(shí)候,可以利用智能感知(intellisense technology)顯示出一個(gè)可用方法的列表方便編程。而智能感知技術(shù)在.aspx頁(yè)面中是不能使用的。

 下面給出的是上面例子利用代碼分離機(jī)制的實(shí)現(xiàn)。

 視圖部分:

 視圖層的代碼現(xiàn)在一個(gè)單獨(dú)的文件中實(shí)現(xiàn)。solution.aspx:

<%@ page language="c#" codebehind="solution.aspx.cs"
  
  autoeventwireup="false" inherits="solution" %>
  
  <html>
  
  <head>
  
  <title>solution</title>
  
  </head>
  
  <body>
  
  <form id="solution" method="post" runat="server">
  
  <h3>recordings</h3>
  
  select a recording:<br/>
  
  <asp:dropdownlist id="recordingselect" runat="server" />
  
  <asp:button id="submit" runat="server" text="submit"
  
  enableviewstate="false" />
  
  <p/>
  
  <asp:datagrid id="mydatagrid" runat="server" width="700"
  
  backcolor="#ccccff" bordercolor="black" showfooter="false"
  
  cellpadding="3" cellspacing="0" font-name="verdana" font-size="8pt"
  
  headerstyle-backcolor="#aaaadd" enableviewstate="false" />
  
  </form>
  
  </body>
  
  </html>

  大部分代碼都與前面的解決方案的代碼相同。主要的不同點(diǎn)是第一行:

  <%@ page language="c#" codebehind="solution.aspx.cs"
  
  autoeventwireup="false" inherits="solution" %>

 這行告訴asp.net執(zhí)行環(huán)境,這個(gè)頁(yè)面的具體實(shí)現(xiàn)機(jī)制在一個(gè)單獨(dú)的類(lèi)中。因?yàn)檫@個(gè)頁(yè)面是獨(dú)立的,因此如果數(shù)據(jù)訪問(wèn)的代碼發(fā)生變化,這個(gè)頁(yè)面并不需要做任何改動(dòng)。同樣,一些設(shè)計(jì)師也可以改變這個(gè)頁(yè)面的代碼而不會(huì)引起任何數(shù)據(jù)訪問(wèn)的錯(cuò)誤。

  模型及控制器部分:
  
  這個(gè)解決方案的第二個(gè)部分是被隱藏的后臺(tái)代碼:

  using system;
  
  using system.data;
  
  using system.data.sqlclient;

public class solution : system.web.ui.page
  
  {
  
   protected system.web.ui.webcontrols.button submit;
  
   protected system.web.ui.webcontrols.datagrid mydatagrid;
  
   protected system.web.ui.webcontrols.dropdownlist recordingselect;

private void page_load(object sender, system.eventargs e)
  
   {
  
   if(!ispostback)
  
   {
  
   string selectcmd = "select * from recording";

sqlconnection myconnection =
  
   new sqlconnection(
  
   "server=(local);database=recordings;trusted_connection=yes");
  
   sqldataadapter mycommand = new sqldataadapter(selectcmd, myconnection);

dataset ds = new dataset();
  
   mycommand.fill(ds, "recording");

recordingselect.datasource = ds;
  
   recordingselect.datatextfield = "title";
  
   recordingselect.datavaluefield = "id";
  
   recordingselect.databind();
  
   }
  
   }

void submitbtn_click(object sender, eventargs e)
  
   {
  
   string selectcmd =
  
   string.format(
  
   "select * from track where recordingid = {0} order by id",
  
   (string)recordingselect.selecteditem.value);

sqlconnection myconnection =
  
   new sqlconnection(
  
   "server=(local);database=recordings;trusted_connection=yes");
  
   sqldataadapter mycommand = new sqldataadapter(selectcmd, myconnection);

dataset ds = new dataset();
  
   mycommand.fill(ds, "track");

mydatagrid.datasource = ds;
  
   mydatagrid.databind();
  
   }

#region web form designer generated code
  
   override protected void oninit(eventargs e)
  
   {
  
   //
  
   // codegen: this call is required by the asp.net web form designer.
  
   //
  
   initializecomponent();
  
   base.oninit(e);
  
   }

/// <summary>
  
   /// required method for designer support - do not modify
  
   /// the contents of this method with the code editor.
  
   /// </summary>
  
   private void initializecomponent()
  
   {
  
   this.submit.click += new system.eventhandler(this.submitbtn_click);
  
   this.load += new system.eventhandler(this.page_load);

}
  
   #endregion
  
  }

  這里將代碼從上個(gè)實(shí)現(xiàn)方法單獨(dú)的文件移動(dòng)到了一個(gè)它自己的文件中。并通過(guò)一些機(jī)制把視圖以及模型控制器這兩個(gè)部分連接成一個(gè)整體,如這個(gè)類(lèi)中的成員變量與solution.aspx文件中所用的控件是同名的。另外一個(gè)必須顯示指出的是控制器如何將行為與其所對(duì)應(yīng)的事件進(jìn)行連接。在這個(gè)例子中initializecomponent函數(shù)連接了兩個(gè)事件。第一個(gè)將load事件與 page_load函數(shù)連接,第二個(gè)是click事件,當(dāng)submit按鈕被點(diǎn)擊時(shí)調(diào)用submitbtn_click函數(shù)。

 代碼分離是一種將視圖部分與模型及控制器部分相分離的一種優(yōu)秀的機(jī)制。但當(dāng)你想把分離出的后臺(tái)的代碼給其它頁(yè)面重用時(shí)可能還是不足的。在技術(shù)上,將頁(yè)面背后的代碼復(fù)用是可行的,但隨著你需要共享的頁(yè)面的增加,把頁(yè)面與后臺(tái)代碼相連接是很困難的。

發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 通化县| 玉林市| 镇巴县| 商河县| 崇仁县| 余干县| 资溪县| 湖南省| 和林格尔县| 贵溪市| 吉安市| 乌海市| 庄河市| 上犹县| 沂南县| 中西区| 莆田市| 克什克腾旗| 莫力| 浪卡子县| 黄山市| 建阳市| 巴林右旗| 勃利县| 洛宁县| 大竹县| 普洱| 东方市| 津市市| 鸡泽县| 周至县| 芮城县| 正安县| 沁阳市| 重庆市| 苏尼特左旗| 合川市| 灵武市| 柏乡县| 古丈县| 龙川县|