扩展方法 之 Redirect 篇

前言:

  单看标题,可能很多朋友不知道我到底想写什么。在写这篇文章前,我自己跟自己斗争了很久,到底该不该写这篇文章?毕竟从现实主义来看,这篇文章可能落入“瞎扯淡”的行列,因为对大多数朋友来说,以下的所有扩展方法可能都不会用到。

  如果真是这样,就当作一个“漫无边际”的想法来看好了。如果你根本不想浪费你的宝贵时间,就点这里 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);

}

 但如果是多层目录:

  如何根据类型来返回我们需要的页面 Url 呢?那么我们得变通一下才行。怎么变通?就是把命名空间也扯上来:

  例如这里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 的情况呢?

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

最终也可以实现以上效果,
但是Url 方法就要适当改改了,这里我就不再贴代码了。

总结:

  最后还是要说的是,这是一个“漫无边际”的想法。

  如果想看其他不那么“漫无边际”的文章,下面有另外几篇

时间: 2024-07-31 02:21:24

扩展方法 之 Redirect 篇的相关文章

艾伟_转载:扩展方法 之 Redirect 篇

前言: 单看标题,可能很多朋友不知道我到底想写什么.在写这篇文章前,我自己跟自己斗争了很久,到底该不该写这篇文章?毕竟从现实主义来看,这篇文章可能落入"瞎扯淡"的行列,因为对大多数朋友来说,以下的所有扩展方法可能都不会用到. 如果真是这样,就当作一个"漫无边际"的想法来看好了.如果你根本不想浪费你的宝贵时间,就点这里 Redirect 回博客园主页,呵呵 一个 Redirect 为什么也可以耗费一篇文章的笔墨? 就 Redirect 一词成文的先例估计不会是我,但如

扩展方法 之 基本数据篇

前一篇我列举了几个最常用到的基于Asp.Net的扩展方法,而这一篇基于基本数据的扩展方法理应不会逊一筹,因为它不局限于Asp.Net.何谓基本数据,这里直接摆定义: C# 中有两种基本数据类型:值类型和引用类型. 值类型包括:简单类型.结构类型.枚举类型:引用类型包括:Object 类型.类类型.接口.代表元.字符串类型.数组. 说白了这篇就是扩展 int, string, double, DateTime...等基本类型.这么多数据类型,如果int来个扩展,double也来个扩展,肯定会是一个

艾伟_转载:扩展方法 之 基本数据篇

前一篇我列举了几个最常用到的基于Asp.Net的扩展方法,而这一篇基于基本数据的扩展方法理应不会逊一筹,因为它不局限于Asp.Net.何谓基本数据,这里直接摆定义: C# 中有两种基本数据类型:值类型和引用类型. 值类型包括:简单类型.结构类型.枚举类型:引用类型包括:Object 类型.类类型.接口.代表元.字符串类型.数组. 说白了这篇就是扩展 int, string, double, DateTime...等基本类型.这么多数据类型,如果int来个扩展,double也来个扩展,肯定会是一个

c#扩展方法奇思妙用高级篇八:Type类扩展

Type 类提供了大量的属性和方法,但在一些基础性开发工作中,Type类功能还有些欠缺,尤其上在处理泛型类型时,如可空类型和泛型集合类型.下面的类就针对这些地方进行扩展. 1 public static class TypeHelper 2 { 3 public static bool IsNullableType(this Type type) 4 { 5 return (((type != null) && type.IsGenericType) && 6 (type.

c#扩展方法奇思妙用高级篇七:“树”通用遍历器

先看一个简单的类People(将作为测试用的例子): 1 public abstract class People 2 { 3 public bool IsMale { get; private set; } 4 public abstract IEnumerable<People> Children { get; } 5 } People类有一个Children属性,返回该People的所有孩子.People类通过Children属性最终可形成一个People树. "树"

c#扩展方法奇思妙用高级篇五:ToString(string format) 扩展

在.Net中,System.Object.ToString()是用得最多的方法之一,ToString()方法在Object类中被定义为virtual,Object类给了它一个默认实现: 1 public virtual string ToString() 2 { 3 return this.GetType().ToString(); 4 } .Net中原生的class或struct,如int,DateTime等都对它进行重写(override),以让它返回更有价值的值,而不是类型的名称.合理重写

c#扩展方法奇思妙用高级篇四:对扩展进行分组管理

从系列文章开篇到现在,已经实现的很多扩展了,但过多的扩展会给我们带来很多麻烦,试看下图: 面对这么多"泛滥"的扩展,很多人都会感到很别扭,的确有种"喧宾夺主"的感觉,想从中找出真正想用的方法来太难了!尽管经过扩展后的string类很"强大",但易用性确很差. 很多人因此感觉扩展应适可而止,不该再继续下去...其实这是一种逃避问题的态度,出现问题我们应该主动去解决,而不是去回避! 有很多种方法可以解决以上问题,最简单的就是使用将扩展放入不同name

c#扩展方法奇思妙用高级篇二:Aggregate扩展其改进

Enumerable.Aggregate 扩展方法在System.Linq命名空间中,是Enumerable类的第一个方法(按字母顺序排名),但确是Enumerable里面相对复杂的方法. MSDN对它的说明是:对序列应用累加器函数.备注中还有一些说明,大意是这个方法比较复杂,一般情况下用Sum.Max.Min.Average就可以了. 看看下面的代码,有了Sum,谁还会用Aggregate呢! public static void Test1() { int[] nums = new int[

c#扩展方法奇思妙用高级篇一:改进Scottgu的"In"扩展

先看下ScottGu对In的扩展: 调用示例1: 调用示例2: 原文地址:New "Orcas" Language Feature: Extension Methods(http://weblogs.asp.net/scottgu/archive/2007/03/13/new-orcas-language-feature-extension-methods.aspx) 很多介绍扩展方法的也大都使用"In"作为例子,但很少有人再深入想一步.个人感觉这个In扩展的不够彻