2011年9月27日 星期二

ASP.NET MVC 2 + MvcPaging + MiniProfiler 連結出現錯誤?


之前以兩篇文章介紹了有關MiniProfiler在ASP.NET MVC 2 與 ASP.NET MVC 3 的應用

ASP.NET MVC 2 + MiniProfiler 偵測執行效能

ASP.NET MVC 3 + MiniProfiler.MVC3 偵測執行效能

今天試著把MiniProfiler給裝在之前的資料分頁的範例專案「ASP.NET MVC - 資料分頁(5) 範例程式下載」,

在我自定的MvcSimplePager以及 MvcSimplePostPager, MvcSimplePostPager + Ajax都沒有什麼問題,

但是在原生的MvcPaging的Pager就出現了錯誤,如下:

image

所有的分頁連結變成了「http://localhost:4371/mini-profiler-results?page=2

URL應該是 Home/PageMethod1 的部份都被代換成 mini-profiler-result 了……


我追了一下 MvcPaging – Pager的原始碼,在Pager.cs中的最後一個method:

   1: private string GeneratePageLink(string linkText, int pageNumber)
   2: {
   3:     var pageLinkValueDictionary = new RouteValueDictionary(linkWithoutPageValuesDictionary) { { "page", pageNumber } };
   4:     var virtualPathForArea = RouteTable.Routes.GetVirtualPathForArea(viewContext.RequestContext, pageLinkValueDictionary);
   5:  
   6:     if (virtualPathForArea == null)
   7:         return null;
   8:  
   9:     var stringBuilder = new StringBuilder("<a");
  10:  
  11:     stringBuilder.AppendFormat(" href=\"{0}\">{1}</a>", virtualPathForArea.VirtualPath, linkText);
  12:  
  13:     return stringBuilder.ToString();
  14: }

當中對於產生URL的部份,Methoid裡面是用:RouteTable.Routes.GetVirtualPathForArea()

 

MSDN - RouteCollectionExtensions.GetVirtualPathForArea 方法

傳回包含路由及虛擬路徑相關資訊的物件,而路由與虛擬路徑是在目前的區域中產生 URL 的結果。

 

MSDN - RouteCollectionExtensions.GetVirtualPathForArea 方法 (RouteCollection, RequestContext, RouteValueDictionary)

「傳回包含路由及虛擬路徑相關資訊的物件,而路由與虛擬路徑是在目前的區域中產生 URL 的結果。」

 

這看起來沒錯,而在偵錯模式下就已經是產生錯誤的URL了…,所以一到了前端的Pager生成就完全走了樣

image

 

我所自訂MvcSimplePager在產生連結時,是使用 HtmlHelper.RouteLink() 方法,

MSDN - LinkExtensions.RouteLink 方法 (HtmlHelper, String, RouteValueDictionary)

「傳回錨定項目 (a 項目),這個項目包含指定之動作的虛擬路徑。」

所以可以使用RouteValueDictionary的資料,然後產生正確的URL。

 

於是最後在取得路徑的地方就改用「RouteTable.Routes.GetVirtualPath()」,

 

MSDN - VirtualPathData.VirtualPath 屬性

「取得或設定透過路由定義來建立的 URL。」

 

而且一開始的RouteValueDictionary則是直接取用

viewContext.RequestContext.RouteData.Values["controller"]
以及
viewContext.RequestContext.RouteData.Values["action"]

 

改寫後的程式:

   1: private string GeneratePageLink(string linkText, int pageNumber)
   2: {
   3:     var pageLinkValueDictionary = new RouteValueDictionary(linkWithoutPageValuesDictionary) 
   4:     { 
   5:         { "controller", viewContext.RequestContext.RouteData.Values["controller"] },
   6:         { "action", viewContext.RequestContext.RouteData.Values["action"] },
   7:         { "page", pageNumber } 
   8:     };
   9:     var virtualPath = RouteTable.Routes.GetVirtualPath(null, pageLinkValueDictionary);
  10:  
  11:     if (virtualPath == null)
  12:     {
  13:         return null;
  14:     }
  15:  
  16:     var stringBuilder = new StringBuilder("<a");
  17:     stringBuilder.AppendFormat(" href=\"{0}\">{1}</a>", virtualPath.VirtualPath, linkText);
  18:     return stringBuilder.ToString();
  19: }

再來看看前端Pager的連結:

image

可以看到Pager頁數連結的URL都是正確路徑的URL。

 

但要是在MVC的Area之中呢?又會不會這修改過的 GeneratePageLink() 會不會出現錯誤?

這就有時間再來討論。

 

2011-09-28 補充:

這是將之前的Mvc資料分頁1-4的範例程式加上MiniProfiler的修改後程式,也包含修改MvcPaging的部份

http://dl.dropbox.com/u/26764200/MVC_Page_With_MiniProfiler.zip

 

以上

沒有留言:

張貼留言

提醒

千萬不要使用 Google Talk (Hangouts) 或 Facebook 及時通訊與我聯繫、提問,因為會掉訊息甚至我是過了好幾天之後才發現到你曾經傳給我訊息過,請多多使用「詢問與建議」(在左邊,就在左邊),另外比較深入的問題討論,或是有牽涉到你實作程式碼的內容,不適合在留言板裡留言討論,請務必使用「詢問與建議」功能(可以夾帶檔案),謝謝。