艾伟_转载:扩展方法 之 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);
}

  但如果是多层目录:

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 方法就要适当改改了,这里我就不再贴代码了。

总结:

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

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

目录
相关文章
|
6月前
|
存储 JavaScript 前端开发
页面传值的方法详解
页面传值的方法详解
|
.NET
艾伟_转载:扩展方法 之 基本数据篇
  前一篇我列举了几个最常用到的基于Asp.Net的扩展方法,而这一篇基于基本数据的扩展方法理应不会逊一筹,因为它不局限于Asp.Net。何谓基本数据,这里直接摆定义:   C# 中有两种基本数据类型:值类型和引用类型。
957 0
|
前端开发 .NET 数据库
艾伟:ASP.NET MVC,深入浅出IModelBinder,在Post方式下慎用HtmlHelper
本文基于ASP.NET MVC Beta版本,正式版如有变动诸不另行通知! 在开始这个主题之前,我先简要介绍一下如何在ActionMethod中通过Form使用Post的方式进行传递参数。 原生类型参数传递 先看一个简单的示例: public ActionResult SimplePost(str...
1200 0
|
Web App开发 .NET C#
艾伟_转载:HttpContext类Current属性 的运用
1、.Net的HTTP请求.NET与ASP的运行机制有很大不同.ASP的请求与响应是,ASP页面被请求,然后逐行解释.是基于过程的.最多是包含了文件,需要先引入文件罢了.而.Net,在页面被请求后,首先是加载HTTP Module,这不是本文的重点.
984 0
|
数据库
艾伟_转载:Entity Framework的默认值BUG解决方法
  在使用.Net 3.5里的Entity Framework开发网站的时候,遇到了一个问题:添加记录时,对于DateTime型的数据,无法使用数据库的默认值。   具体的情况是这样的,我的数据库有个Users表,三个字段,id,username,createtime。
830 0
|
前端开发
艾伟:[一步一步MVC]第一回:使用ActionSelector控制Action的选择
本系列文章导航 [一步一步MVC]第一回:使用ActionSelector控制Action的选择 [一步一步MVC]第二回:还是ActionFilter,实现对业务逻辑的统一Authorize处理 [一步一步MVC]第三回:MVC范例大观园 [一步一步MVC]第四回:漫谈ActionLink,有时“...
861 0
|
存储 Web App开发 .NET
艾伟_转载:Cookie是什么?用法是怎样?与SESSION有什么区别?(二)
  二session 简介   IE中:   有效的窗品包括   1.Session对象只在建立Session对象的窗口中有效。   2.在建立Session对象的窗口中新开链接的窗口   无效的窗口包括   1.直接启动IE浏览器的窗口   2.不是在建立Session对象的窗口中新开链接的窗口   NetScape中:   只要一个窗口有了某个Session对象,则全部窗口对此Session都有效   Session是什么呢?简单来说就是服务器给客户端的一个编号。
916 0
|
存储 Web App开发
艾伟_转载:Cookie是什么?用法是怎样?与SESSION有什么区别?(一)
  Cookie是什么?用法是怎样?与SESSION有什么区别?   一 Cookie简介   因特网的Cookie技术极其简单,却有着旺盛的生命力。Cookie开始引起众人的注意是从2000年二月份随着网络隐私权的提出开始的,有关的辩论至今仍在继续。
1077 0
|
C#
wpfのuri(让你完全明白wpf的图片加载方式以及URI写法)
原文:wpfのuri(让你完全明白wpf的图片加载方式以及URI写法) 绝对 pack WPF URI pack://application:,,,/是协议;“,,,”是“///”的变体 1.资源文件 — 本地程序集 Uri uri = new Uri("pack://application:,,,/ResourceFile.
1788 0
|
前端开发 索引 API
利刃 MVVMLight 5:绑定在表单验证上的应用
原文:利刃 MVVMLight 5:绑定在表单验证上的应用    表单验证是MVVM体系中的重要一块。而绑定除了推动 Model-View-ViewModel (MVVM) 模式松散耦合 逻辑、数据 和 UI定义 的关系之外,还为业务数据验证方案提供强大而灵活的支持。
778 0