日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
淺析WebFormView中的一個Bug

老趙的文章主要是針對WebFormView中的一個Bug,這個Bug在一般情況下不會出現(xiàn)問題,它沒有遵循ASP.NET MVC既定的模型。

10年積累的成都網(wǎng)站制作、做網(wǎng)站經(jīng)驗,可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識你,你也不認(rèn)識我。但先網(wǎng)站設(shè)計制作后付款的網(wǎng)站建設(shè)流程,更有新羅免費網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。

最近需要搞一些重要的功能,結(jié)果又遇到了意料外的障礙。于是又仔細(xì)地看了看ASP.NET和ASP.NET MVC的源代碼,又發(fā)現(xiàn)了以前不曾知道的一些細(xì)節(jié)。您最多說ASP.NET WebForms模型不一定適合某些Web應(yīng)用程序的開發(fā),但是我想沒有人可以否認(rèn)ASP.NET中設(shè)計的巧妙——以及復(fù)雜程度。其實ASP.NET為我們留下了不少切入點,但幾乎沒什么書會提到這些切入點,我們只能從微軟自己的框架中一探究竟。

不過這次我想談的是ASP.NET MVC框架中的一個Bug,這個Bug在一般情況下不會出現(xiàn)問題,但是這的確違反了ASP.NET MVC自身的設(shè)計。這個問題就出在WebFormView對象的實現(xiàn)上。

WebFormView是一個視圖對象的實現(xiàn)。而在ASP.NET MVC中,任何視圖都需要實現(xiàn)一個IView接口:

 
 
 
  1. public interface IView {  
  2.     void Render(ViewContext viewContext, TextWriter writer);  

Render方法的目的自然是根據(jù)ViewContext對象中的數(shù)據(jù),將視圖內(nèi)容輸出至TextWriter中。例如在HtmlHelper的RenderPartial方法,便是將一個Partial View輸出至Response中.

 
 
 
  1. public class HtmlHelper {  
  2.     ...  
  3.     internal virtual void RenderPartialInternal(  
  4.         string partialViewName,  
  5.         ViewDataDictionary viewData,  
  6.         object model,  
  7.         ViewEngineCollection viewEngineCollection) {  
  8.  
  9.         ...  
  10.  
  11.         ViewContext newViewContext = new ViewContext(...);  
  12.         IView view = FindPartialView(newViewContext, partialViewName, viewEngineCollection);  
  13.         view.Render(newViewContext, ViewContext.HttpContext.Response.Output);  
  14.     }  

雖然我認(rèn)為這里的做法是不太妥當(dāng)?shù)模ㄟ@點下次再談),但是這的的確確地表現(xiàn)了Render方法的設(shè)計意圖。只可惜在WebFormView中,Render方法卻違背了這一設(shè)計:

 
 
 
  1. public class WebFormView : IView {  
  2.     ...  
  3.     public virtual void Render(ViewContext viewContext, TextWriter writer) {  
  4.         ...  
  5.         object viewInstance = ...;  
  6.         ...  
  7.  
  8.         ViewUserControl viewUserControl = viewInstance as ViewUserControl;  
  9.         if (viewUserControl != null) {  
  10.             RenderViewUserControl(viewContext, viewUserControl);  
  11.             return;  
  12.         }  
  13.  
  14.         ...  
  15.     }  
  16.  
  17.     private void RenderViewUserControl(ViewContext context, ViewUserControl control) {  
  18.         ...  
  19.  
  20.         control.ViewData = context.ViewData;  
  21.         control.RenderView(context);  
  22.     }  

對于Partial View,WebFormView會加載合適的ViewUserControl實例,并調(diào)用其RenderView方法生成內(nèi)容……但是,我們的writer參數(shù)到哪里去了?沒錯,對writer參數(shù)Find All Reference就會發(fā)現(xiàn),這個參數(shù)根本沒有用到。既然在這里就已經(jīng)拋棄了我們指定writer,那么接下來的邏輯再怎么搞也就“那么一回事兒”了。

如果您感興趣閱讀代碼的話,會發(fā)現(xiàn)事實上最終這個對象被放入了一個新建的ViewPage對象中,然后調(diào)用ViewPage的RenderView方法生成視圖內(nèi)容:

 
 
 
  1. public class ViewPage : Page, IViewDataContainer {  
  2.     ...  
  3.     public virtual void RenderView(ViewContext viewContext) {  
  4.         ViewContext = viewContext;  
  5.         InitHelpers();  
  6.         // Tracing requires Page IDs to be unique.  
  7.         ID = Guid.NewGuid().ToString();  
  8.         ProcessRequest(HttpContext.Current);  
  9.     }  

瞧到這個HttpContext.Current了嗎?也就是說,無論RenderView方法何時調(diào)用,永遠(yuǎn)是向HttpContext.Current輸出內(nèi)容。這個設(shè)計很不合理,但是修改起來還是非常簡單的,例如以下幾行代碼就可以得到差不多的效果:

 
 
 
  1. public static class HtmlExtensions  
  2. {  
  3.     public static void Partial(this HtmlHelper htmlHelper, string partial)  
  4.     {  
  5.         var viewInstance = BuildManager.CreateInstanceFromVirtualPath(partial, typeof(object));  
  6.         var control = viewInstance as ViewUserControl;  
  7.  
  8.         control.ViewContext = htmlHelper.ViewContext;  
  9.         control.ViewData = htmlHelper.ViewData;  
  10.  
  11.         Page page = new ViewPage();  
  12.         page.Controls.Add(control);  
  13.  
  14.         htmlHelper.ViewContext.HttpContext.Server.Execute(  
  15.             page,  
  16.             htmlHelper.ViewContext.HttpContext.Response.Output,  
  17.             false);  
  18.     }  

但是我不喜歡這種做法,因為它沒有遵循ASP.NET MVC既定的模型。ASP.NET MVC的確可以擴展,但如果需要按照標(biāo)準(zhǔn)擴展的話,我們作的事情就多了:

繼承WebFormView,覆蓋RenderView方法。

繼承WebFormViewEngine,覆蓋CreatePartialView方法,返回剛創(chuàng)建的新類。

在Application Start時,使用新的ViewEngine類替換ASP.NET MVC原有的視圖引擎。

但是在實際情況中,我會選擇使用使用第三種方法:下載ASP.NET MVC的源代碼,改寫,編譯。既然它是MS-PL的授權(quán)協(xié)議,為什么不自己動手打一些Patch呢?事實上,我也打算使用這種方法來修補ASP.NET MVC的Bug或Design Issue,并發(fā)布一個臨時的新項目,就叫作……MvcPatch如何?


新聞標(biāo)題:淺析WebFormView中的一個Bug
分享地址:http://www.5511xx.com/article/cojsodh.html