自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

淺析WebFormView中的一個Bug

開發(fā) 開發(fā)工具
這里將介紹一個WebFormView中的Bug,它違反了ASP.NET MVC自身的設(shè)計,希望本文能對大家有所幫助。

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

最近需要搞一些重要的功能,結(jié)果又遇到了意料外的障礙。于是又仔細地看了看ASP.NET和ASP.NET MVC的源代碼,又發(fā)現(xiàn)了以前不曾知道的一些細節(jié)。您最多說ASP.NET WebForms模型不一定適合某些Web應用程序的開發(fā),但是我想沒有人可以否認ASP.NET中設(shè)計的巧妙——以及復雜程度。其實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.     }  

雖然我認為這里的做法是不太妥當?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)用,永遠是向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的確可以擴展,但如果需要按照標準擴展的話,我們作的事情就多了:

繼承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如何?

原文標題:應該算是WebFormView的一個Bug

鏈接:http://www.cnblogs.com/JeffreyZhao/archive/2009/09/14/webviewengine-bug-always-render-to-current-context.html

【編輯推薦】

  1. ASP.NET MVC與WebForm區(qū)別談
  2. 自定義的ControllerFactory:接口實現(xiàn),支持Area
  3. ASP.NET Routing之“解析URL”功能詳解
  4. 為ASP.NET MVC應用添加自定義路由
  5. 學習ASP.NET MVC路由的使用方法
責任編輯:彭凡 來源: 博客園
相關(guān)推薦

2025-02-13 07:00:00

Dubbo-goJava服務端

2009-07-14 16:02:42

JDBC例子

2013-06-18 11:37:42

XFSRHEL 6.4

2021-10-08 07:50:57

軟件設(shè)計程序

2017-10-10 15:14:23

BUGiOS 11蘋果

2014-12-17 09:40:22

dockerLinuxPaaS

2024-04-22 00:00:01

Redis集群

2022-06-15 08:14:40

Go線程遞歸

2023-03-13 08:09:03

Protobuffeature分割

2015-08-24 10:07:13

程序員bug

2019-08-01 12:59:21

Bug代碼程序

2022-05-16 08:42:26

Pandasbug

2024-08-08 08:09:38

2011-05-19 15:14:49

PostgreSQL

2011-03-03 21:04:08

bug程序員

2022-04-06 08:47:03

Dubbo服務協(xié)議

2021-09-11 19:00:54

Intro元素MemoryCache

2018-11-01 13:23:02

網(wǎng)關(guān)APIHTTP

2009-08-31 13:53:03

C#創(chuàng)建一個文件

2017-03-22 09:11:45

bugbug賞金計劃眾包項目
點贊
收藏

51CTO技術(shù)棧公眾號