ASP.NET MVC 2框架試用經(jīng)驗(yàn)談
本文將為大家介紹已經(jīng)發(fā)布的ASP.NET MVC 2框架正式版的使用情況,包括緩存,靜態(tài)內(nèi)容的放置等等。希望本文能對(duì)大家有所幫助。
這個(gè)月一直在用 ASP.NET MVC 2 做http://www.86e0.com/t 這個(gè)網(wǎng)站,用的時(shí)候是 aps.net MVC2 RC2,然后現(xiàn)在ASP.NET MVC 2正式版已經(jīng)是發(fā)布了。 在MVC的使用上,有一些心得。下面作一下總結(jié),希望對(duì)大家有用,也歡迎大家討論。
1.關(guān)于緩存
緩存上,數(shù)據(jù)層上的緩存是必須的,這點(diǎn)不必多說(shuō)了。
另一個(gè)很重要的是:視圖片段緩存。
我參考了老趙的寫的三篇關(guān)于片段緩存的文章:
適合ASP.NET MVC的視圖片斷緩存方式(上):起步
適合ASP.NET MVC的視圖片斷緩存方式(中):更實(shí)用的API
適合ASP.NET MVC的視圖片斷緩存方式(下):頁(yè)面輸出原則
本想用老趙的了,但是我發(fā)現(xiàn)ASP.NET MVC 2 的有一個(gè)新功能: Html.Partial可以返回生成的HTML, 返回的類型是:MvcHtmlString. 雖然要利用Partial View才能生成Html片段,但是我想這個(gè)已經(jīng)夠我用的了, 所以我做了一個(gè)這樣一個(gè)Helper,主要是將生成的HTML片段緩存到Memcached里。代碼如下:
- public static class MvcHtmlHelper
- {
- public static MvcHtmlString MemcacheHtmlPartial(this HtmlHelper htmlHelper,int duration, string partialViewName, object model, ViewDataDictionary viewData)
- {
- object obaear = htmlHelper.ViewContext.RouteData.DataTokens["area"];
- string area=string.Empty;
- if (obaear != null) area = obaear.ToString();
- string key = string.Format("MemcacheHtmlPartial_{0}{1}", area, partialViewName);
- object ob = DistCache.Get(key);
- if (ob == null)
- {
- MvcHtmlString mstr = htmlHelper.Partial(partialViewName, model, viewData);
- DistCache.Add(key, mstr.ToString(), TimeSpan.FromSeconds(duration));
- return mstr;
- }
- else
- {
- return MvcHtmlString.Create((string)ob);
- }
- }
- }
然后,我覺得,這樣,在每次請(qǐng)求時(shí),還是要在Controller 里把數(shù)據(jù)取出來(lái),然后再傳到 Partial View里。 既然已經(jīng)緩存了,就應(yīng)該不用每次請(qǐng)求都要在Controller里把數(shù)據(jù)取出來(lái)才對(duì)!雖然數(shù)據(jù)層會(huì)有緩存。
所以我,能不能再省下去Controller取數(shù)據(jù)的消耗,于是又有了以下代碼,其功能是:緩存Action生成的HTML到Memcached里。
- public static MvcHtmlString MemcacheHtmlRenderAction(this HtmlHelper htmlHelper,
- int duration, string actionName,string controllerName, RouteValueDictionary routeValues)
- {
- object obaear = htmlHelper.ViewContext.RouteData.DataTokens["area"];
- string area = string.Empty;
- if (obaear != null) area = obaear.ToString();
- string key = string.Format("MemcacheHtmlRenderAction_{0}{1}{2}", area, controllerName,actionName);
- object ob = DistCache.Get(key);
- if (ob == null)
- {
- // htmlHelper.RenderAction(actionName, controllerName, routeValues);
- StringWriter writer = new StringWriter(CultureInfo.CurrentCulture);
- ActionHelper(htmlHelper, actionName, controllerName, routeValues, writer);
- string wStr = writer.ToString();
- DistCache.Add(key, wStr,TimeSpan.FromSeconds(duration));
- MvcHtmlString mstr = MvcHtmlString.Create(wStr);
- return mstr;
- }
- else { return MvcHtmlString.Create((string)ob); }
- }
說(shuō)明一下,Actionhelper的方法是在MVC原代碼里提取出來(lái)的。 因?yàn)镸VC2里的 Html.RenderAction方法并沒有返回 MvcHtmlString的重載版。那位有更好的方法?
其實(shí),MVC里的Action有輸出緩存,所以直接在View里用 Html.RenderAction都可以解決很多問題了。這個(gè)主要是可以用程序管理緩存。
2.關(guān)于靜態(tài)內(nèi)容的放置
習(xí)慣上,靜態(tài)內(nèi)容會(huì)放在 mvc程序所在的目錄下,比如說(shuō)js,css,上傳的圖片等。但是這樣的話,所有的靜態(tài)請(qǐng)求都要經(jīng)過 aspnet_isapi 處理,這樣是非常不合算的。所以靜態(tài)內(nèi)容一般都會(huì)放在另外的子域上。http://www.86e0.com/t 是放在 cdn.86e0.com上。
3.關(guān)于強(qiáng)類型ViewModel
我基本上看了老趙的Asp.net MVC***實(shí)踐。 其中有一點(diǎn),就是強(qiáng)烈推薦使用強(qiáng)類型的ViewModel. 我試了一些頁(yè)面,發(fā)現(xiàn)用強(qiáng)類型的ViewModel,現(xiàn)階段并不適用于我。因?yàn)槲沂怯肗bearLite,從數(shù)據(jù)庫(kù)抓出來(lái)的大多是DataTable. 我是覺得DataTable+NbearLite蠻方便的,雖然沒有動(dòng)態(tài)語(yǔ)言的數(shù)據(jù)訪問來(lái)得方便,但是比用Entity,ViewModel, DTO,等等來(lái)說(shuō),還是可以省下很多代碼。然后,最重要的是,由于我這種站經(jīng)常會(huì)修改,所以數(shù)據(jù)庫(kù)改變,加字段,減字段是很經(jīng)常性的事。但是,用NbearLite + DataSet,DataTable,卻非常方便。
所以我覺得,做Asp.net MVC,如果你不是用DDD,DDT的話,用DataTable還是可以的。因?yàn)镈DD,DDT學(xué)習(xí)起來(lái)還是要點(diǎn)成本的。
4.關(guān)于URL生成
URL生成, 老趙寫了一系列文章:
各種URL生成方式的性能對(duì)比
各種URL生成方式的性能對(duì)比(結(jié)論及分析)
為URL生成設(shè)計(jì)流暢接口(Fluent Interface)
URL生成方式性能優(yōu)化結(jié)果
我直接選擇
Raw方式了, 速度最快的,才是適合我的。呵。 而不是強(qiáng)類型的才是適合我的。
***,分享一個(gè)很實(shí)用的Asp.net MVC 分頁(yè)Helper.
這個(gè)Helper引自重典老大的blog:http://www.cnblogs.com/chsword/ . 我在之前做了少少修改,現(xiàn)已經(jīng)在http://www.86e0.com/t 上使用了。
效果如下:
請(qǐng)大家注意生成的 URL, 是用 ?參數(shù)=頁(yè)碼 的方式。代碼如下:
- /// <summary>
- /// 分頁(yè)P(yáng)ager顯示
- /// </summary>
- /// <param name="html"></param>
- /// <param name="currentPageStr">標(biāo)識(shí)當(dāng)前頁(yè)碼的QueryStringKey</param>
- /// <param name="pageSize">每頁(yè)顯示</param>
- /// <param name="totalCount">總數(shù)據(jù)量</param>
- /// <returns></returns>
- public static string Pager(this HtmlHelper html, string currentPageStr, int pageSize, int totalCount)
- {
- var queryString = html.ViewContext.HttpContext.Request.QueryString;
- int currentPage = 1; //當(dāng)前頁(yè)
- if(!int.TryParse(queryString[currentPageStr], out currentPage)) currentPage = 1; //與相應(yīng)的QueryString綁定
- var totalPages = Math.Max((totalCount + pageSize - 1) / pageSize, 1); //總頁(yè)數(shù)
- var dict = new RouteValueDictionary(html.ViewContext.RouteData.Values);
- var output = new StringBuilder();
- foreach (string key in queryString.Keys)
- if (queryString[key] != null && !string.IsNullOrEmpty(key))
- dict[key] = queryString[key];
- if (totalPages > 1)
- {
- if (currentPage != 1)
- {//處理首頁(yè)連接
- dict[currentPageStr] = 1;
- output.AppendFormat("<span class=\"p_home\">{0}</span>", html.RouteLink("首頁(yè)", dict));
- }
- if (currentPage > 1)
- {//處理上一頁(yè)的連接
- dict[currentPageStr] = currentPage - 1;
- output.AppendFormat("<span class=\"p_up\">{0}</span>", html.RouteLink("上一頁(yè)", dict));
- }
- else
- {
- output.AppendFormat("<span class=\"p_disable\">{0}</span>","上一頁(yè)");
- }
- int currint = 5;
- for (int i = 0; i <= 10; i++)
- {//一共最多顯示10個(gè)頁(yè)碼,前面5個(gè),后面5個(gè)
- if ((currentPage + i - currint) >= 1 && (currentPage + i - currint) <= totalPages)
- if (currint == i)
- {//當(dāng)前頁(yè)處理
- output.Append(string.Format("<span class=\"p_current\">{0}</span>", currentPage));
- }
- else
- {//一般頁(yè)處理
- dict[currentPageStr] = currentPage + i - currint;
- output.AppendFormat("<span class=\"p_num\">{0}</span>",html.RouteLink((currentPage + i - currint).ToString(), dict));
- }
- }
- if (currentPage < totalPages)
- {//處理下一頁(yè)的鏈接
- dict[currentPageStr] = currentPage + 1;
- output.AppendFormat("<span class=\"p_down\">{0}</span>", html.RouteLink("下一頁(yè)", dict));
- }
- else
- {
- output.AppendFormat("<span class=\"p_disable\">{0}</span>", "下一頁(yè)");
- }
- if (currentPage != totalPages)
- {
- dict[currentPageStr] = totalPages;
- output.AppendFormat("<span class=\"p_last\">{0}</span>",html.RouteLink("末頁(yè)", dict));
- }
- }
- output.AppendFormat("<span class=\"p_count\">第{0}頁(yè)/共{1}頁(yè)</span>", currentPage, totalPages);//這個(gè)統(tǒng)計(jì)加不加都行
- return output.ToString();
- }
ASP.NET MVC延伸閱讀
ASP.NET MVC是微軟官方提供的MVC模式編寫ASP.NET Web應(yīng)用程序的一個(gè)框架。
它由Castle的MonoRail而來(lái).目前已經(jīng)歷經(jīng)數(shù)個(gè)版本。ASP.NET MVC中的MVC本來(lái)是存在于Desktop程序中的,M是指數(shù)據(jù)模型,V是指用戶界面,C則是控制器。使用MVC的目的是將M和V的實(shí)現(xiàn)代碼分離,從而使同一個(gè)程序可以使用不同的表現(xiàn)形式。比如一批統(tǒng)計(jì)數(shù)據(jù)你可以分別用柱狀圖、餅圖來(lái)表示。C存在的目的則是確保M和V的同步,一旦M改變,V應(yīng)該同步更新。
ASP.NET MVC框架是既ASP.NET WebForms后的又一種開發(fā)方式。它提供了一系列優(yōu)秀特性,使ASP.NET開發(fā)人員擁有了另一個(gè)選擇。ASP.NET MVC框架選項(xiàng)非常干凈,而且容易使用。它將允許你在應(yīng)用中輕易地保持關(guān)注分離,且有助于進(jìn)行干凈的測(cè)試和TDD。
原文標(biāo)題:Asp.net MVC2 使用經(jīng)驗(yàn),性能優(yōu)化建議
鏈接:http://www.cnblogs.com/OtisBlog/archive/2010/03/22/1691676.html
【編輯推薦】