擴展方法 之 Redirect 篇

作者: CoolCode  來源: 博客園  發布時間: 2009-09-28 13:17  閱讀: 2286 次  推薦: 0   原文鏈接   [收藏]  

前言:

  單看標題,可能很多朋友不知道我到底想寫什么。在寫這篇文章前,我自己跟自己斗爭了很久,到底該不該寫這篇文章?畢竟從現實主義來看,這篇文章可能落入“瞎扯淡”的行列,因為對大多數朋友來說,以下的所有擴展方法可能都不會用到。

  如果真是這樣,就當作一個“漫無邊際”的想法來看好了。如果你根本不想浪費你的寶貴時間,就點這里 Redirect 回博客園主頁,呵呵

一個 Redirect 為什么也可以耗費一篇文章的筆墨?

  就 Redirect 一詞成文的先例估計不會是我,但如果 擴展方法 + Redirect 這個話題,我可能就是第一人了。

葫蘆里賣的是什么藥?

  這個“漫無邊際”的想法實現的效果是:

  如果頁面是Foo.aspx,

  • 通過 this.Url() 來獲取Url;
  • 通過 this.View() 來Redirect;
  • 通過 this.Url( new {param1= "value1", param2= "value2"}); 來返回帶參數的Url。

“漫無邊際”的想法來源:

  Asp.Net MVC 是這個想法的主要來源,學習過 Asp.Net MVC的朋友都熟悉Controller 是如何獲知返回的頁面,主要方法:

public ActionResult Index()
{
    return View();
    return View("ViewName");
    return View("ViewName", new { ReturnUrl ="Foo"});
    return RedirectToAction("ActionName");
}

 

  不懂 Asp.Net MVC 的朋友也沒關系,因為本文實際上跟 Asp.Net MVC 完全沒關系,跟稍后講 WebForm 的 View 擴展方法也完全是沒有任何一點關系,僅是方法名相同而已。

如何實現?

  對于最簡單的情況:頁面在根目錄,就直接根據 類名 + ".aspx" 返回就可以了

public static string Url(this IHttpHandler httpHandler )
{
    return string.Format("~/{0}.aspx", typeof(T).Name);
}

  但如果是多層目錄:

 

image

  如何根據類型來返回我們需要的頁面 Url 呢?那么我們得變通一下才行。怎么變通?就是把命名空間也扯上來:

 

image

  例如這里Home文件夾里的Index.aspx 頁面后臺的命名空間是 RedirectTests.Views.Home,就根據這個命名空間和類名來拼裝出 "~/Views/Home/Index.aspx" 還不簡單嘛。

  示例代碼:

public static string Url(this IHttpHandler httpHandler)
{
    string fullViewName = typeof(TView).FullName;
    string[] splits = fullViewName.Split('.');
    if (splits.Length < 2)
        throw new ArgumentException("Cannot find the namespace on view name");
       return string.Format("~/Views/{0}/{1}.aspx", splits[splits.Length - 2],
 splits[splits.Length - 1]);
}

  以上代碼限制路徑只能在 Views 文件夾下了,有興趣的朋友不妨改改。

如何為 Url 添加查詢字符串?

  啥?這也是一個問題?我見過不少朋友寫查詢字符串時基本上是這樣寫的:

  string url = "~/Foo.aspx?param1=" + value1 + "&param2=" + value2 ...;

  或者,想寫美觀一點的朋友就這樣寫:

  string url = string.Format( "~/Foo.aspx?param1={0}&param2={1}" , value1, value2);

  當查詢字符串比較長時,那可就有些亂了。個人覺得以Asp.Net MVC 那種形式來書寫很不錯,這就產生另一個“漫無邊際”的想法,請看下面的寫法:

this.Url<Foo>(new { param1 = "value1", param2 = "value2" }); 

 

  當然,執行效率肯定稍遜一籌啦,因為用了反射(題外話,其實大家可以不必聞“射”喪膽,老趙的關于快速反射的開源項目很好很強大)。

public static string Url(this IHttpHandler httpHandler, object param)
{
    string queryString = param.ToQueryString();
    string virtualPath = string.Format("{0}?{1}", httpHandler.Url(), queryString);
    return virtualPath;
}

 

/// 拼裝查詢字符串
public static string ToQueryString(this T model)
{
    StringBuilder sb = new StringBuilder();
    if (model != null)
    {
        Type type = model.GetType();
        //遍歷所有屬性,拼裝查詢字符串
        type.GetProperties().ForEach(p =>
        {
            sb.Append(p.Name);
            sb.Append("=");
            sb.Append(UrlEncode(p.GetValue(model, null)));
            sb.Append("&");
        });
        if (sb.Length > 0)
        {
            //去掉最后一個“&” 
            return sb.ToString(0, sb.Length - 1);
        }
    }
    return sb.ToString();
}
/// Url編碼
public static string UrlEncode(object obj)
{
    if (obj == null)
    {
        return string.Empty;
    }
    else if (obj is DateTime)
    {
        string value = ((DateTime)obj).ToString("yyyy-MM-dd HH:mm:ss.ffffff");
        return System.Web.HttpUtility.UrlEncode(value);
    }
    return System.Web.HttpUtility.UrlEncode(obj.ToString());
}

 

  以上代碼關于 Url 編碼的部分,你可以看到如果是DateTime類型轉字符串時,這里進行特定格式的轉化。因為如果不這樣轉化,當獲取這個DateTime類型時,不能保證能從字符串轉回正確的DateTime。

  那么,有了上面介紹,自然而然一堆擴展方法就呼之欲出了:

public static void View(this IHttpHandler httpHandler)
{
    HttpContext.Current.Response.Redirect(httpHandler.Url());
}
public static void View(this IHttpHandler httpHandler, object param)
{
    HttpContext.Current.Response.Redirect(httpHandler.Url(param));
}
public static void ViewHome(this IHttpHandler httpHandler)
{
    HttpContext.Current.Response.Redirect("~");
}
public static void ViewLogin(this IHttpHandler httpHandler)
{
    ViewLogin(httpHandler,null);
}
public static void ViewLogin(this IHttpHandler httpHandler, string returnUrl)
{
    string virtualPath = FormsAuthentication.LoginUrl;
    if (!string.IsNullOrEmpty(returnUrl))
        virtualPath += "?ReturnUrl=" + returnUrl;
    HttpContext.Current.Response.Redirect(virtualPath);
}

 

結束

  當然沒結束。以上的 Url 返回的只能是.aspx的頁面,那么IHttpHandler 的情況呢?

 

image

string handlerUrl = this.Url<Handler1>();

最終也可以實現以上效果,但是Url 方法就要適當改改了,這里我就不再貼代碼了。

總結:

  最后還是要說的是,這是一個“漫無邊際”的想法。

  如果想看其他不那么“漫無邊際”的文章,下面有另外幾篇

0
0
 
 
 

文章列表

arrow
arrow
    全站熱搜

    大師兄 發表在 痞客邦 留言(0) 人氣()