不用asp.net MVC,用WebForm照樣可以實現MVC(請看最后一句話)


    在《避開WebForm天坑,擁抱ASP.Net MVC吧》這篇博客中我講到了ASP.net WebForm由於一些先天的“誘導犯罪”的缺陷,現在用ASP.net MVC的公司越來越多。但是根據那篇文章末尾的"ASP.net MVC的免費網絡公開課"調查表的統計,我們發現有一大半的人還沒有使用過ASP.Net MVC,而沒用過ASP.net MVC的人中竟然有很多人人是因為感覺ASP.Net 難、沒時間學。調查表分析數據如下:

 

 

    初看ASP.net確實難:復雜的路由機制、 ViewData/ViewBag/TempData、過濾器、Razor、Layout、XXXHelper、驗證、WebAPI、依賴注入、單元測試……光看這一堆概念頭就暈了,“還是拖控件簡單”。

    其實學習一個新的框架,只要搞清他的原理就會“豁然開朗”,再看其他的東西就不會感覺恐懼了。

    這篇文章我將會帶着大家搞明白什么叫MVC模式,並且帶着大家用大家熟悉的Asp.Net WebForm實現MVC!

    對!你沒聽錯!

    用Asp.Net WebForm實現MVC!

 

    再次感受一下ASP.net WebForm吧。

   假設有一個Person對象的集合,我們要在網頁中以html渲染,那么要如下編寫

<table>
        <asp:Repeater ID="Repeater1" runat="server">
            <ItemTemplate><tr><td><%#Eval("Name") %></td><td><%#Eval("Age") %></td></tr></ItemTemplate>
        </asp:Repeater>
</table>

  

C#代碼:

if(!IsPostBack)
{
List<Person> list = new List<Person>();
list.Add(new Person { Name = "rupeng", Age = 8 });
list.Add(new Person { Name = "qq", Age = 18 });
Repeater1.DataSource = list;
Repeater1.DataBind();
}

 

這樣做的缺點是C#代碼中訪問了apsx中的控件Repeater1,也就是在aspx中必須要有一個Repeater類型、Id為Repeater1的控件,這樣aspx就和C#代碼耦合在了一起。麻煩在哪兒呢?

1)如果aspx有兩個地方都要用list了,那么就要寫兩組DataSource=list;DataBind();

2)如果aspx中突然不想要Repeater了,把Repeater1刪掉C#代碼就會報錯

3)Aspx中忽然不想用Repeater進行數據的顯示了,想換別的控件,那么C#代碼也要改

 

再比如,在ASP.Net WebForm中,實現加法計算器會如下實現:

<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
+<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="=" />
<asp:TextBox ID="TextBox3" runat="server"></asp:TextBox>

   

protected void Button1_Click(object sender, EventArgs e)
{
    int i1 = Convert.ToInt32(TextBox1.Text);
    int i2 = Convert.ToInt32(TextBox2.Text);
    int i3 = i1 + i2;
    TextBox3.Text = i3.ToString();
}

 

    后台的C#代碼和aspx的耦合要求aspx視圖中必須有三個名字各為TextBox1、TextBox2、TextBox3的TextBox類型的服務器控件。如果我想把計算的結果從TextBox改成span就不行。前端設計人員看到TextBox絕對沒有input親切,前端人員對input 的把控能力會被TextBox更好。另外不必再說WebForm引入的ViewState、頁面生命周期、ClientID等令人作嘔的問題。 

    有同學會說了:你有病嗎,開發時候aspx怎么可能總是變來變去,即使aspx變了,你C#代碼也就變唄,有什么大不了的?

    如果說系統小的話可能無所謂,對於比較復雜的系統,如果aspx和C#這樣緊密的耦合,維護還會特別麻煩。而且如果實現像一些CMS系統那樣可以動態修改模板文件的話就是存在着“C#無法預測、無法強制要求aspx到底怎么寫”的問題。

 

    這還僅僅是展示一個集合的問題,如果要展示復雜的扁平化數據或者需要從用戶輸入中獲取數據,用這種方式更災難。

    那么MVC思想怎么解決呢?邏輯代碼(Controller)不直接和頁面視圖(View)進行交互,他們之間用Model(數據模型)作為溝通的通道。當需要展示數據的時候由Controller收集到數據(Model),然后把數據交給View去展示;當Controller需要讀取View中用戶輸入內容的時候,框架會把View中的數據映射到Model中,然后Controller讀取Model中的數據進行后續的邏輯處理。這樣就把邏輯代碼(俗稱C#代碼)和視圖(俗稱頁面)進行解耦了。

    光說概念沒用,還是先看代碼把。下面使用MVC模式改造的“顯示Person集合”:

 

View視圖PersonsView.aspx

<%@ Page  Language="C#"%>
<%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="WebApplication1" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
    <table>
        <%
            var persons = (List<Person>)Context.Items["persons"];
            foreach(var person in persons)
            {
        %>
        <tr><td><%=person.Name %></td><td><%=person.Age %></td></tr>
        <%
            } 
        %>
    </table>
</body>
</html>

 

注意,我把aspx相關的兩個自動生成的.cs文件刪掉了,並且把<%@Page%>標簽的AutoEventWireup、CodeBehind、Inherits等幾個屬性也都干掉了,這樣aspx就變成了一個純粹的“模板引擎”

 

作為Controller的Index.ashx的代碼如下:

public void ProcessRequest(HttpContext context)
{
    List<Person> list = new List<Person>();
    list.Add(new Person { Name="rupeng",Age=8});
    list.Add(new Person { Name = "qq", Age = 18 });
    context.Items["persons"] = list;
    context.Server.Transfer("PersonsView.aspx");
}

 

     這里借鑒了JSP中“request.getRequestDispatcher("index.jsp").forward(request,response)”一樣的思路。

     context.Server.Transfer是在服務器內部把請求處理權轉交給"PersonsView.aspx"處理。HttpContext中的Items的生命周期是整個請求響應,這樣我們在一般處理程序中把數據放到context.Items中,然后在"PersonsView.aspx"中就可以可以通過Context.Items["persons"]拿到這個數據從而進行數據的展示。

     為什么把數據放到HttpContext.Items中呢。由於Transfer僅僅是服務器內部處理權的轉接,但是仍然是在一個請求中的,所以放到Context.items是最好的。如果放到Session、Application等中會有並發的問題。 

    這樣Controller(一般處理程序)和View(aspx)之間只要維持一個“要傳遞一個名字為persons類型的List<Person>”這樣一個弱耦合關系即可,至於aspx用不用這個persons、用幾次persons、怎么用persons,你Controller都不用管。 

按照同樣方法改造加法計算器

 

下面是視圖AddView.aspx的代碼

<%@ Page Language="C#"%>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <%dynamic viewBag = Context.Items["ViewBag"]; %>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>加法計算器</title>
</head>
<body>
    <form id="form1">
        <input type="hidden" name="action" value="addSubmit" />
        <input type="text" name="i1" value="<%=viewBag.i1 %>" />+<input type="text" name="i2" value="<%=viewBag.i2%>" />
        <input type="submit" value="=" /><input type="text" value="<%=viewBag.i3 %>" />
    </form>
</body>
</html>

而AddHandler.ashx的主體代碼如下:

 public void ProcessRequest(HttpContext context)
{
    string action = context.Request["action"];
    dynamic viewBag = new System.Dynamic.ExpandoObject();
    if(string.IsNullOrEmpty(action))
    {
viewBag.i1 = "";
viewBag.i2 = "";
viewBag.i3 = "";                
    }
    else if(action=="addSubmit")
    {
int i1 = Convert.ToInt32(context.Request["i1"]);
int i2 = Convert.ToInt32(context.Request["i2"]);
int i3 = i1 + i2;
viewBag.i1 = i1;
viewBag.i2 = i2;
viewBag.i3 = i3;
    }
    context.Items["ViewBag"] = viewBag;
    context.Server.Transfer("AddView.aspx");
}

 

    由於View和Controller之間傳遞的數據比較復雜、比較多,為了簡化開發,這樣用了dynamic 動態類型。熟悉ASP.Net MVC的同學是不是感覺這個和ASP.net MVC中的ViewBag異曲同工呢。

    在這個加法計算器中如果我想把結算結果用span顯示,那么只要把<input type="text" name="i3" value="<%=viewBag.i3%>" />改成<span><%=viewBag.i3%></span>就可以了。美工也容易介入頁面美化。

    如果我想把頁面的Title從“加法計算器”改成“3和5相加的結果”,那么只要這樣改就可以:<title><%=viewBag.i1 %>和<%=viewBag.i2 %>相加的結果</title>    這樣model里的數據我aspx想用幾次用幾次,想怎么用就怎么用。有沒有感覺到和WebForm不一樣的地方呢?

 

   所以只要思想想通了,其實實現MVC模式不一定要用ASP.net MVC,我見過很多項目都是自己搞的MVC機制。

    當然既然ASP.net MVC已經這么優秀了,一般情況沒必要像我這樣重新自己發明一個輪子用。 

    這里給大家講ASPX實現MVC只是用大家熟悉的東西讓大家明白原理,工程項目應用還是直接用ASP.Net MVC吧。

 

如鵬網.Net培訓班正在報名,有網絡的地方就可以參加如鵬網的學習,學完就能高薪就業,點擊此處了解

 

    三年前只要懂“三層架構”就可以說“精通分層架構”;現在則需要懂IOC(AutoFac等)、CodeFirst、lambda、DTO等才值錢;

    三年前只要會SQLServer就可以說自己“精通數據庫開發”;現在則需還需要掌握MySQL等開源數據庫才能說是“.Net開源”時代的程序員;

    三年前只要會進行用戶上傳內容的安全性處理即可;現在則需要熟悉雲存儲、CDN等才能在雲計算時代游刃有余;

    三年前只要掌握Lucene.Net就會說自己“熟悉站內搜索引擎開發”;現在大家都用ElasticSearch了,你還用Lucene.Net就太老土了;

    三年前發郵件還是用SmtpClient;現在做大型網站發郵件必須用雲郵件引擎;

    三年前緩存就是Context.Cache;現在則是Redis、Memcached的天下;

    如鵬網再次引領.Net社區技術潮流!點擊此處了解如鵬網.Net最新課程

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM