壹個更好的做法是用“過慮屬性”(filter attribute),可能妳的post的action的形式如下:
[HttpPost]//或許妳並沒有這樣用,或許妳就是這樣用的。。
public ViewResult MyAction(int page)
那麽,妳應該知道(或是可以)這麽做:
[HttpGet]
public ViewResult MyAction(int page)
MyAction的形式參數page會通過ASP.NET MVC的“值提供程序(value provider)”提供,它會按優先級從下以列表中為page綁定壹個值:
Request.Form
RouteData.Values
Request.QueryString
Request.Files
這也就意味著,妳的條件完全可以以壹個<input name="page" type="...">的html域接收用戶的輸入,當妳提交表單時,name等於page(name="page")的表單裏的域(就是html input)的值將作為MyAction的形參的值,且表單域的值是首先的。
針對補充問題:
明白妳的意思了,妳是想通過Get請求而又不把條件暴露在URL中對吧,如果是的話,那麽有壹個好的辦法是直接用《Pro ASP.NET MVC2 Framework(second edition)》第四章還是第五章裏的分頁例子的思路。
大概的思路是這樣的,讓每頁對應壹個URL,這樣的好處之壹是當客戶看上了某壹頁(假設是第三頁)的內容,此時他右擊頁面選擇“加入收藏夾”,而當他幾天後從收藏夾打開收藏的鏈接時,他得到的還將是第三頁的數據。這在Web Form中通過簡單的辦法是很難做到的。
話遠了,為了實現這個辦法,需要為此維護壹個擁有CurrentPageIndex屬性的View Model,並在配置Route的時候加個CurrentPageIndex項。。
寢室要斷電了,如果妳不想下那本電子書的話(當然,我推薦妳下),明天繼續。。
希望這會是最終版本的補充:
以下是Steven Sanderson的《Pro ASP.NET MVC2 Framework(second edition)》上的例子,以及壹些我的說明(以下說明都基於妳對C#壹些或新或舊語法的了解):
整體的思想是把“分頁”做成壹個組件,利於復用。
具體的是,首先給HtmlHelper擴展壹個方法(有關擴展方法可參數相關文檔,如MSDN),這個方法返回的是壹個能被<%%>語法解析的MvcHtmlString對象,事實上這個對象包含的內容則是HTML標簽<a>。擴展方法如下:
public static class PagingHelpers
{
public static MvcHtmlString PageLinks(this HtmlHelper html, PagingInfo pageInformation,
Func<int, string> pageUrl)
{
StringBuilder result = new StringBuilder();
for (int i = 1; i <= pageInformation.TotalPages; i++)
{
TagBuilder tag = new TagBuilder("a");
tag.MergeAttribute("href", pageUrl(i));
tag.InnerHtml = i.ToString();
if (i == pageInformation.CurrentPage)
{
tag.AddCssClass("selected");
}
result.AppendLine(tag.ToString());
}
return MvcHtmlString.Create(result.ToString());
}
}
從方法體可以理解到,需要分頁的數據的每壹頁此方法都將為其提供壹個鏈接,如此每壹頁數據就會對應壹個URL。正如之前我說過那樣,這會是壹個好的用戶體驗。
再看視圖(View)是怎樣調用此方法來實現分布的,以下是名為List(List為強類型(strongly typed)視圖,其類型為ProductsListViewModel,對此類型壹會兒將作解釋)的視圖調用此方法來實現分頁的代碼:
<%: Html.PageLinks(Model.PagingInfo,i => Url.Action("List", new ))%>
可以看到,調用擴展的分頁方法時我們傳入了兩個實參,壹個是Model.PagingInfo,壹個是lambda表達式(有關lambda表達式可參考相關文檔,如MSDN)i => Url.Action("List", new )。
在看第壹個參數Model.PagingInfo之前,我們先看看Model的類型定義:
public class ProductsListViewModel
{
public IList<Product> Products
public PagingInfo PagingInfo
public string CurrentCategory
}
此類型有三個屬性,在此我們僅需關心其第二個屬性,PagingInfo類型的PagingInfo(名字取成壹樣,希望不要混淆)屬性。PagingInfo類型定義如下:
public class PagingInfo
{
public int CurrentPage //當前頁碼
public int TotalItems //數據總記錄數
public int ItemsPerPage //每頁記錄數
public int TotalPages//總頁數
{
get
{
return (int)(Math.Ceiling((decimal)TotalItems / ItemsPerPage));
}
}
}
這就是我們分頁時所關心的信息,也正是我們調用擴展的分頁方法時需要傳遞過去的信息。當然,這些信息不會憑空而生,而需要我們自己設置。
我所舉的例子是Steven Sanderson的《Pro ASP.NET MVC2 Framework(second edition)》所提供的壹個以視圖List來分頁產品的例子。應當註意,用戶從瀏覽器請求/list時,他請求的不是list.aspx那個頁面(雖然我們為用戶顯示的就是它),他請求的是我們壹個叫List的Action。這也就意味著,為輸出用戶需要的那個List.aspx我們需要做的準備工作(當然,不是業務邏輯)都將在名叫List的Action裏進行,Action List定義如下:
public ViewResult List(string category, int page = 1/*C#的形參默認值(參考C# 4’s
optional parameter)*/)
{
var productsToShow = (category == null ? productsRepository.Products : productsRepository.Products.Where(x => x.Category == category));
var viewModel = new ProductsListViewModel
{
Products = productsToShow.Skip((page - 1) * PageSize).Take(PageSize).ToList(),
PagingInfo = new PagingInfo ,
CurrentCategory = category
};
return View(viewModel);
}
可以看到,當用戶首次請求List時,他很有可能沒有給壹個page參數(當然,在妳的應用中妳完全可以有妳的選擇),為此我們給了它壹個默認的值。如果妳用的不是C#4.0,那麽妳可以把int page = 1換成[DefaultValue(1)] int page,在這裏它們的效果是壹樣的。
接下來是對實現分頁的整個過程的闡述:
不管用戶第壹次請求是否帶了page這個參數,在Action List執行過程中,Action List便會構造壹個ProductsListViewModel對象,這個對象正是分頁方法所需要的信息。當Action List順利地執行完成return View(viewModel)時,視圖List.aspx將收到Action List返回的viewModel並把它作為視圖的Model屬性。
當視圖List.aspx執行到<%: Html.PageLinks(Model.PagingInfo,i => Url.Action("List", new ))%>時(視圖得先在服務器上編譯執行,產生最後的HTML才發送到客戶端),它就會調用擴展方法Html.PageLinks()為每頁生成壹個唯壹的<a>標簽,這樣也就作到了壹頁數據對應壹個URL的良好用戶體驗。
還需說明的壹點是,這裏的<a>標簽導航到的可不是某個.aspx頁面,而是某個Action(當然,本例中是Action List)。
最後還有壹處配置,就是增加壹個Route項,形式如下:
routes.MapRoute(
null,
"/Page",
new ,
new );
這樣就做到了應妳需求,無QueryString。。
當然,如有需要,加上AJAX,用戶將得到更好的體驗。
如果不明白的話,請補充問題,希望我能幫到妳。
如果這對妳有幫助話,請將此標為最佳答案,謝謝。