[转载]Red5总结

mikel阅读(1216)

[转载]Red5总结 – 青青豆(QQingDou) – 博客园.

网站开发已经几年有余了,最近终于忙完了自己的青青豆,以前始终没有抽出时间自己写点什么,偶尔拿起偶尔放下,终究是空,希望自己多多坚持,也希望博友的多多支持,分享自己一些积累的经验!

前一段时间公司鉴于首页不错的流量,希望增加一些格外的收入或者做些视频推广,需要增加一个FLASH流媒体服务器播放视频,本来对于做C#.NET我来 说,这个项目应该不是我来接的,最后可能是各位博友想的那样,”梦里花落知多少” 落到了我的怀里,‘杯具’还是这样发生了。

Red5的主要功能 和Macromedia公司的FMS类似,提供基于Flash的流媒体服务的一款基于Java的开源流媒体服务器。它由Java语言编写,使用RTMP作 为流媒体传输协议,这与FMS完全兼容。它具有流化FLV、MP3文件,实时录制客户端流为FLV文件,共享对象,实时视频播放、Remoting等功 能。用Red5替换FMS后,客户端不用更改可正常运行。

Red5竟然是用JAVA编写,我.NET,  无语了,那么用FMS吧,对于一个试用型项目,几千元的RMB似乎不可能,只能硬着头皮继续研究Red5。

准备工作:

一、JAVA环境配置:

下载的JDK安装包,我选择的是jdk-6u10-rc2-bin-b32-windows-i586-p-12_sep_2008.exe,参考地址http://aben328.javaeye.com/blog/341499

二、确认你的安装环境并选择RED5安装包:

如果是Windows操作系统,可以下载对应的安装文件Red5 0.9.0 Final (27 January 2010) ,不是最新的(不一定是最好的),也可以下载对应的源代码自己进行研究Source,其他的操作可以参考该页面http://code.google.com/p/red5/

准备工作完成,一切就绪。

安装工作:

步骤一:首先安装上面下载的JDK安装包(备注:如果你先安装RED5,会提示找不到JDK,你必须先完成步骤一在继续以下操作), 安装时首先会安装JDK,必须记住安装路径,保持默认即可,默认是C:\Program Files\Java\jdk1.6.0_10,然后安装JRE,保持默认即可,默认是C:\Program Files\Java\jre6,安装完成后,必须配置环境变量,我的电脑–>属性–>高级 选项卡–>环境变量(N)–>找到 系统变量(S) 下 新建(W),然后输入 变量名(N):JAVA_HOME,变量值(V):上面JDK安装路径C:\Program Files\Java\jdk1.6.0_10,确定即可,JDK准备就绪。

步骤二:安装RED5,安装RED5时,会要求输入外网可访问的IP,比如101.23.45.67,然后输入可访问的端口(Port),一般是5080,最后安装完成即可。

测试工作:

a) 一切安装就绪,现在应该体验一下RED5的真实面目了,首先启动RED5服务:重启电脑然后 我的电脑–>系统服务–>启动 RED5服务 或者 直接在安装目录下找到Red5.bat启动即可,接着在IE输入http://101.23.45.67:5080/,(你刚刚输入的IP地址和Port),没有忘吧,回车进行测试,

会出现RED5欢迎页面,如果出现以下页面,说明RED5安装成功,如果不成功,请确认IP是否正确和可访问,Port是否正确且没有被占用。

b)安装 DEMO

点击 Install,进入安装页面,连接成功出现一下页面:

选中要安装的 DEMO,然后点击 Install即可,比如说 SOSample。

返回上个页面,点击 DEMO连接进行测试,然后点击上一步安装的DEMO,比如Shares Ball View demo,进行测试,注意必须把rtmp://localhost/SOSample 改为 rtmp://101.23.45.67/SOSample,点击Connect TO Red5按钮,右边会变成绿色,否则请检查是否连接成功。在不同页面进行同样操作,如果拉动其中一个的页面的red5图标, 另外一个页面的RED5图标也按照相同轨迹移动,说明安装RED5成功。

配置站点:

打开RED5的安装目录下的webapps目录,新建自己需要的目录,如MyStream,r然后复制SOSample下的全部文件到MyStream,修改两个文件:

一、red5-web.properties

webapp.contextPath=/MyStream

二、web.xml

<param-value>/FlvStream</param-value>

保存即可。

下一步在MyStream目录下放置.FLV文件的即可。重启服务


RTMP服务测试:

下载 RTMP播放器测试 http://www.longtailvideo.com/players/jw-flv-player/,配置playlist.xml,将

<location>rtmp://101.23.45.67/MyStream</location>
<identifier>FileName</identifier>//你FLV文件名称,不需要扩展名

OK,IE浏览mediaplayer.html 文件,出现视频播放,恭喜你,一切成功!更多介绍,请详见参考资料。

参考资料http://osflash.org/red5

http://code.google.com/p/red5/

http://labs.influxis.com/?p=47

http://developer.longtailvideo.com/trac/wiki/Player5FlashVars

[转载]ASP.NET MVC的全球化方案

mikel阅读(988)

[转载]ASP.NET MVC的全球化方案 – P_Chou Go deep and Keep learning – 博客园.

由于项目需要最近在学习ASP.NET MVC。在实践中,网站要支持多语言,需要全球化。在MVC下我实现了一个全球化框架,在这里与各位分享一下,不足之处也请各位看官指教。

让URL支持全球化

经常上微软网站的朋友可能很熟悉类似包含..\zh-cn\..、..\en-us\..的url形式,这就是本文要使用的全球化方案。当然还有使用QueryString传递参数的方案,基本思路我想是类似的。

由于MVC天生的URL路由原理,使得这个方案很容易被接受。

基本思路

这个方案的基本思路是:

1.当用户访问的url含有合法的culture参数时,能够直接路由到对应的controller,在controller初始化时设置线程的Culture;

2.当用户访问的url不包含culture参数时,同样被路由到对应的controller,但controller在执行action前,重定向到包含Culture的url。这里的Culture按照先检测cookie,再检测语言浏览器设置,最后使用默认值的优先级顺序实施。

先看下效果演示,注意url,点击下载例子

image

image

Resource.resx

在接下去之前先回顾一下资源文件。在ASP.NET web应用程序(winform同样)中定义的资源文件.resx实际上是一个xml配置文件,通常我们只关心其中的key\value配置;我们可以建 立一个或多个.resx,这些.resx会对应生成一个cs文件,这个cs文件会定义一个类(可能是Resource类,取决于你的资源文件的命名),通 过访问这个类的静态属性即可访问这些key,而选择哪个.resx读取的关键就是CultureInfo,只要我们设置当前线程的 CultureInfo,Resource便会自动识别对应的.resx配置文件。而在.resx的命名上,需要按照这样的规则:

Resource.zh-cn.resx(对应简体中文资源文件)

Resource.en-us.resx(对应美国英语资源文件)

中间的Culture名字很重要。

通常在开发时,只要一个默认的Resource.resx,当开发完成之后,拷贝一个相同的Resource.resx,并改名字成上面的样子,然后手动或自动将其中的所有value都翻译成对应的语言。

解决路由问题

在这个方案中,首先要考虑的是url路由配置。首先,理想情况下,我们所有的url都是domain/culture/controller /action/param1/..这种形式,那么只要一份以culture开头的路由就可以了。但是事实上并非这么简单,如果用户不知道这个规则,他手 动输入了domain/controller/action/param1..那么这种url将不能被正确路由。这种情况在初次访问网站的时候最为常见 (通常我们都会键入www.microsoft.com而不会在后面加 上任何的culture参数)。那么难道我们要为了这种场景写两份路由吗?显然不是,或者说不用手动做这件事。这里要解决的第一个问题出现了。我的方案 是:只为domain/controller/action/param1..这种路由手动写代码配置,这也比较符合习惯;然后通过一个方法,遍历 route表中的所有路由,并在每个url规则前面加上一个参数ci表示culture,生成一份新的路由加到路由表中即可。这样做尽管没有减少路由规 则,但是至少不用手动一个个写了,要不然没人会同意这个方案的。下面是代码和解释:

1 protected void Application_Start()
2 {
3 AreaRegistration.RegisterAllAreas();
4 RegisterRoutes(RouteTable.Routes);
5 RegisterGlobalizationRoutes();
6 ...
7 }
01 private void RegisterGlobalizationRoutes()
02 {
03 //RouteTable.Routes即路由表
04 if (RouteTable.Routes == null)
05 return;
06 //创建一个新的路由集合,存放将要添加到路由
07 RouteCollection rc = new RouteCollection();
08
09 //这里需要跳过routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
10 //由于IgnoreRouteInternal是个私有类,所以这里只能反射
11 //skip IgnoreRouteInternal
12 var routes = RouteTable.Routes.SkipWhile(p => (p.GetType().Name == "IgnoreRouteInternal"));
13
14 int insertpoint = RouteTable.Routes.Count() - routes.Count();
15
16 //遍历所有需要处理的路由
17 foreach (var r in routes)
18 {
19 Route item = (r as Route);
20 //下面的代码创建一个新的路由对象,在url规则前面加上ci参数,并拷贝其他设置
21 Route newitem = new Route(
22 //string.Format(@"{ci}/{0}",item.Url),
23 @"{ci}/" + item.Url,
24 new MvcRouteHandler());
25 newitem.Defaults = new RouteValueDictionary(item.Defaults);
26 newitem.Constraints = new RouteValueDictionary(item.Constraints);
27 //ci参数需要验证,因为只有合法的culture才能被接受
28 newitem.Constraints.Add("ci", new CulturePrefixRule());
29 newitem.DataTokens = new RouteValueDictionary();
30 newitem.DataTokens["Namespaces"] = item.DataTokens["Namespaces"];
31 rc.Add(newitem);
32 }
33 //带ci参数的路由应当靠前放,所以这里插入到前面
34 foreach (var c in rc)
35 {
36 RouteTable.Routes.Insert(insertpoint++, c);
37 }
38 }
01 //实现IRouteConstraint的一个类
02 private class CulturePrefixRule : IRouteConstraint
03 {
04 IEnumerable<string> cultureConllection = CultureInfo.GetCultures(CultureTypes.SpecificCultures).Select(p => p.Name.ToLower());
05 public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
06 {
07 if (values[parameterName] != null)
08 return cultureConllection.Contains(values[parameterName].ToString().ToLower());
09 else
10 return false;
11 }
12 }

这里要注意几点:

1.routes.IgnoreRoute(“{resource}.axd/{*pathInfo}”);会在路由表中添加一条IgnoreRouteInternal类型的路由,只不过这条是需要被跳过的而已。三个类的关系是:

RouteBase->Route->IgnoreRouteInternal

而不巧的是IgnoreRouteInternal是个私有类,因此,只能借助反射了。

2.为路由设置Constraints属性时,实际上是为其指 定一个IRouteConstraint。MVC内部有一个实现了IRouteConstraint的接受正则表达式的类,我们在MapRoute方法中 用一个string初始化Constraints,实际上就是实例化了这个类。而这里我们的需求显然要复杂点:需要判断ci参数是否是支持的,所以也就有 了CulturePrefixRule实现IRouteConstraint。

3.带有ci参数的路由更“特殊”,所以最好还是放在路由表前面。原因我就不再累述了。

在Controller的Action执行前跳转

所有的Controller都应该具有一个相同的行为:能够针对没有ci参数的url实施跳转。因此自然想到实现一个基类Controller,这里我命名为BaseController,代码如下:

01 public class BaseController : Controller
02 {
03 protected string redirectUrl;
04
05 protected override void Initialize(System.Web.Routing.RequestContext requestContext)
06 {
07 base.Initialize(requestContext);
08 object cultureValue;
09 //检测ci参数
10 if (requestContext.RouteData.Values.TryGetValue("ci", out cultureValue))
11 {
12 //设置当前线程的culture
13 try
14 {
15 Thread.CurrentThread.CurrentUICulture = CultureProvider.GetCultureInfo(cultureValue.ToString());
16 Thread.CurrentThread.CurrentCulture = CultureProvider.GetCultureInfo(cultureValue.ToString());
01 Response.Cookies.Add(new HttpCookie(CultureProvider.culturecookiekey,cultureValue.ToString()));
02 }
03 catch { throw new Exception("Culture Error!"); }
04 }
05 else //如果没有ci参数
06 {
07 //check cookie
08 HttpCookie cLang = requestContext.HttpContext.Request.Cookies[CultureProvider.culturecookiekey];
09 if (cLang != null)
10 {
11 cultureValue = cLang.Value;
12 }
13 else //check brower setting
14 {
15 string[] langs = requestContext.HttpContext.Request.UserLanguages;
16 if (langs != null && langs.Length > 0)
17 {
18 cultureValue = langs[0].Split(';').First();
19 }
20 }
21
22 if (cultureValue == null)
23 {
24 cultureValue = CultureProvider.culturedefault;
25 }
26 //设置redirectUrl,如果不需要重定向到化redirectUrl 为null
27 redirectUrl = string.Format(@"/{0}{1}",
28 cultureValue.ToString(),
29 requestContext.HttpContext.Request.RawUrl);
30
31 }
32 }
33
34 protected override IActionInvoker CreateActionInvoker()
35 {
36 return new CustomControllerActionInvoker(redirectUrl);
37 }
38 }
39
40 //一个IActionInvoker 的实现,MVC默认使用ControllerActionInvoker,因为在
41 //redirectUrl != null 的时候需要在action执行之前执行重定向
42 internal class CustomControllerActionInvoker : ControllerActionInvoker
43 {
44 string redirectUrl;
45 public CustomControllerActionInvoker(string url)
46 : base()
47 {
48 redirectUrl = url;
49 }
50 protected override ActionResult InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary<string, object> parameters)
51 {
52 object returnValue;
53 //ChildAction内部不能重定向
54 if (!string.IsNullOrEmpty(redirectUrl) && !controllerContext.IsChildAction)
55 returnValue = new RedirectResult(redirectUrl);
56 else
57 returnValue = actionDescriptor.Execute(controllerContext, parameters);
58 ActionResult result = CreateActionResult(controllerContext, actionDescriptor, returnValue);
59 return result;
60 }
61 }
62
63 public static class CultureProvider
64 {
65 public const string culturecookiekey = "Lang";
66 public const string culturedefault = "en-US";
67
68 public static CultureInfo GetCultureInfo(string ci)
69 {
70 try
71 {
72 return new CultureInfo(ci);
73 }
74 catch
75 {
76 return null;
77 }
78 }
79 }

只要所有的Controller继承这个BaseController即可。

这里需要重点指出的是 CustomControllerActionInvoker类,事实上发现从这个类入手解决重定向问题花了我不少时间,为此我不得不调试MVC的源码。 当然最初的想法是在每个action执行时手动判断redirectUrl,从而指导重定向,但显然,没人愿意将自己已经写好的action都拿出来一个 个改,所以也就有了这个小小的探索。

页面中的链接、跳转

最后令我感到即高兴又担心的问题是:当我使用这个框架后,页面 中的所有链接和跳转因素几乎都能自动在url前面加上ci参数!虽然我知道类似Html.ActionLink之类的helper有从路由表中产生url 的能力,但是能够自动添加上ci,还是让我感到有点始料未及。不过,链接的url是否正确,还是要注意,有一些特殊情况。

页面中使用资源

在页面中引用资源可以直接在C#脚本中引用Resource类。这里提供一个helper。这个Html的扩展方法。

01 public static class ResourceExtensions
02 {
03 public static string Resource(this Controller controller, string expression, params object[] args)
04 {
05 ResourceExpressionFields fields = GetResourceFields(expression, "~/");
06 return GetGlobalResource(fields, args);
07 }
08
09 public static string Resource(this HtmlHelper htmlHelper, string expression, params object[] args)
10 {
11 string path = "~/";
12 ResourceExpressionFields fields = GetResourceFields(string.Format("Resource,{0}", expression), path);
13 return GetGlobalResource(fields, args);
14 }
15
16 static string GetGlobalResource(ResourceExpressionFields fields, object[] args)
17 {
18 return string.Format((string)HttpContext.GetGlobalResourceObject(fields.ClassKey, fields.ResourceKey, CultureInfo.CurrentUICulture), args);
19 }
20
21 static ResourceExpressionFields GetResourceFields(string expression, string virtualPath)
22 {
23 var context = new ExpressionBuilderContext(virtualPath);
24 var builder = new ResourceExpressionBuilder();
25 return (ResourceExpressionFields)builder.ParseExpression(expression, typeof(string), context);
26 }
27 }

需要注意的是这个方法默认认为Resource是资源的类名,所以必要的话需要修改

ResourceExpressionFields fields = GetResourceFields(string.Format(“Resource,{0}”, expression), path); 中的”Resource,{0}”

结语

初学MVC,甚至可以说是初学web开发。以上是我个人提出的一种方案,不知道有没有什么不足之处,还请各位看官提出见解,探讨一下。

点击下载例子

其他相关资源:

http://blog.miniasp.com/post/2010/01/ASPNET-MVC-Developer-Note-Part-15-Globalization-and-Localization.aspx

[转载]ASP.NET MVC 3 Beta初体验之超酷的Chart

mikel阅读(916)

[转载]ASP.NET MVC 3 Beta初体验之超酷的Chart – 海纳百川 – 博客园.

前面一篇文章:ASP.NET MVC 3 Beta初体验之WebGrid介 绍了WebGrid控件的使用,ASP.NET MVC 3 Beta中才内置Chart的。这篇文章中将介绍Chart的使用。包括Chart数据源的配置、Chart的显示、Chart保存三个方面。Chart 是很多系统中使用,所以在ASP.NET MVC 3 Beta初体验之中介绍它是很有必要的。

1、配置Chart的数据源

给Chart配置数据源大概有三种方式。
第一种:使用数组
示例:
Controller代码:
public ActionResult BasicChart() { return View(); }
BasicChart.cshtml代码:

<p> @{ var key = new Chart(width: 600, height: 400) .AddTitle("人员流动情况") .AddSeries(name: "Employee",xValue: new[] { "一月份", "二月份", "三月份", "四月份", "五月份", "六月份", "七月份", "八月份", "九月份"}, yValues: new[] { "2", "6", "4", "5", "3","4","9","2","5"}) .Write(); } </p>

从上面代码可以看到,我给 Chart的xValue配置了一个数组,相应的yValue也配置了一个相应的数组。
运行效果:

此时,我们发现这个图形是单独显示的,没有站点的样式和母版。下面实现将这个图形显示在一个页面中。
定义一个Action:
public ActionResult ShowBasicChart() { return View(); }
View代码:定义一个img标签,将src改成生成图片的action。
<p><img src="BasicChart" /> </p>
效果:有了站点样式和母板:
第二种方式:数据库查询
示例:
@{ var db = Database.Open("SmallBakery"); var data = db.Query("SELECT Month, Number FROM Employee"); var key = new Chart(width: 600, height: 400) .AddTitle("人员流动") .DataBindTable(dataSource: data, xField: "Month") .Write(); }
第三种方式:XML
示例:
@using System.Data; @{ var dataSet = new DataSet(); dataSet.ReadXmlSchema(Server.MapPath("~/App_Data/data.xsd")); dataSet.ReadXml(Server.MapPath("~/App_Data/data.xml")); var dataView = new DataView(dataSet.Tables[0]); var key = new Chart(width: 600, height: 400) .AddTitle("Sales Per Employee") .AddSeries("Default", chartType: "Pie", xValue: dataView, xField: "Name", yValues: dataView, yFields: "Sales") .Write(); }
由于这三种方式都类似,了解其中一种,其余的类似,就不细说了,为了简单起见,下面的例子都是用数组的方式来实现。
2、Chart的显示:
chartType属性:它有一个chartType属性,可以定义显示的方式。比如将上面的例子的chartType定义为”Pie”,就显示为饼图。
@{ var key = new Chart(width: 600, height: 400) .AddTitle("人员流动情况") .AddSeries(name: "Employee",chartType: "Pie", xValue: new[] { "一月份", "二月份", "三月份", "四月份", "五月份", "六月份", "七月份", "八月份", "九月份"}, yValues: new[] { "2", "6", "4", "5", "3","4","9","2","5"}) .Write(); }
效果:
template属性:它可以定义背景模板,如修改代码为:template: ChartTheme.Green
代码

@{ var key = new Chart(width: 600, height: 400,template: ChartTheme.Green) .AddTitle("人员流动情况") .AddSeries(name: "Employee",xValue: new[] { "一月份", "二月份", "三月份", "四月份", "五月份", "六月份", "七月份", "八月份", "九月份"}, yValues: new[] { "2", "6", "4", "5", "3","4","9","2","5"}) .Write(); }
效果:
3、Chart保存
将Chart保存到缓存中:看下面代码:
代码

@{ var chartKey = Request["key"]; if (chartKey != null) { var cachedChart = Chart.GetFromCache(key: chartKey); if (cachedChart == null) { cachedChart = new Chart(600, 400); cachedChart.AddTitle("Cached Chart -- Cached at " + DateTime.Now); cachedChart.AddSeries( name: "Employee", axisLabel: "Name", xValue: new[] { "一月份", "二月份", "三月份", "四月份", "五月份", "六月份", "七月份", "八月份", "九月份"}, yValues: new[] { "2", "6", "4", "5", "3","4","9","2","5"}); cachedChart.SaveToCache(key: chartKey,minutesToCache: 2,slidingExpiration: false); } Chart.WriteFromCache(chartKey); } }
Chart.GetFromCache(key: chartKey)将根据key从缓存中取出Chart,cachedChart.SaveToCache(key: chartKey,minutesToCache: 2,slidingExpiration: false)是将Chart缓存起来。看下图:
当再次请求的时候,就直接从缓存中取数据。设置缓存两分钟,两分钟之后这次的缓存失效。
将Chart保存为图片:
使用下面代码将图形保存为图片:
@{ var filePathName = "_ChartFiles/chart01.jpg"; if (!File.Exists(Server.MapPath(filePathName))) { var chartImage = new Chart(600, 400); chartImage.AddTitle("Chart Title"); chartImage.AddSeries( name: "Employee", axisLabel: "Name", xValue: new[] { "一月份", "二月份", "三月份", "四月份", "五月份", "六月份", "七月份", "八月份", "九月份"}, yValues: new[] { "2", "6", "4", "5", "3","4","9","2","5"}); chartImage.Save(path: filePathName); } }
保存之后的图片:
将Chart保存为保存为XML:
@{ Chart chartXml; var filePathName = "_ChartFiles/XmlChart.xml"; if (File.Exists(Server.MapPath(filePathName))) { chartXml = new Chart(width: 600,height: 400,templatePath: filePathName); } else { chartXml = new Chart(width: 600,height: 400); chartXml.AddTitle("Chart Title -- Saved at " + DateTime.Now); chartXml.AddSeries( name: "Employee", axisLabel: "Name", xValue: new[] { "一月份", "二月份", "三月份", "四月份", "五月份", "六月份", "七月份", "八月份", "九月份"}, yValues: new[] { "2", "6", "4", "5", "3","4","9","2","5"}); chartXml.SaveXml(path: filePathName); } chartXml.Write(); }
从上面代码我们可以看到,可以通过templatePath将XML转换成Chart。通过SaveXml可以将Chart保存为XML。生成的XML如下:
代码

<Chart Width="600" Height="400"> <Series> <Series Name="Employee" XValueType="String" YValueType="String" ChartArea="Default" AxisLabel="Name"> <Points> <DataPoint YValues="2" AxisLabel="一月份" /> <DataPoint YValues="6" AxisLabel="二月份" /> <DataPoint YValues="4" AxisLabel="三月份" /> <DataPoint YValues="5" AxisLabel="四月份" /> <DataPoint YValues="3" AxisLabel="五月份" /> <DataPoint YValues="4" AxisLabel="六月份" /> <DataPoint YValues="9" AxisLabel="七月份" /> <DataPoint YValues="2" AxisLabel="八月份" /> <DataPoint YValues="5" AxisLabel="九月份" /> </Points> </Series> </Series> <ChartAreas> <ChartArea Name="Default"> </ChartArea> </ChartAreas> <Titles> <Title Name="Title1" Text="Chart Title -- Saved at 2010/10/19 23:41:02"> </Title> </Titles> </Chart>
总结:本文就三个方面介绍了ASP.NET MVC 3 Beta中的Chart。包括它的数据源配置、显示以及保存。

作者:朱祁林
出处:http://zhuqil.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

[转载]More Effective C#Lambda表达式优化

mikel阅读(1007)

[转载]【More Effective C#】Lambda表达式优化 – 空逸云 – 博客园.

使用Lambda表达式将会造成Lambda表达式主题部分的代码重复.

var allEmployees = new List<Employee>() { new Employee { EmployeeId = 1, Classification = 1, FirstName = "Skin", LastName = "Sen" } };

            var earlyFolks = from e in allEmployees

                             where e.MonthlySalary < 4000 && e.Classification == 1 && e.YearsOfService > 20

                             select e;

若每当我们要获取一次不同工薪阶层的数据.就要重复一次.相信久经”高重用,松耦合”定律的你.肯定会想尽办法将其实现高重用,松耦合.在以前方法调用的时代.可能你会将其提炼出

private static bool LowPaidSalaried(Employee e, int salar)
        {
            return e.MonthlySalary < salar && e.Classification == 1;
        }

这样,每次我们调用的时候,将大大减少代码量,提高可复用性.

var earlyFolks = from e in allEmployee
                             where LowPaidSalaried(e, 4000) && e.YearsOfService > 20
                             select e;

然而,很不幸的是.在这里.这种重构的方式反倒降低了其可重用性.实际上,第一种方法的可重用性比第二种方法更高些.为什么呢?明明已经提炼出重用方法了.这与Lambda表达式的求值,解析以及最终的执行方式有关.

前面的<<LINQ表达式与方法调用的映射>>里说过.编译器会根据不同的LINQ Provider将Lambda表达式转换成不同的内容来执行.对于LINQ to Object.将转换成委托方法.而LINQ to SQL则是转换成表达式数.在数据迭代时才会转换成SQL语句执行.所以.若我们是在LINQ2SQL或ADO.Net EF中如此重构.编译期通过了.但运行时将出错.因为无法将你的自定义方法转换成相关的SQL语句.,因此.将抛出一个异常.

难道,Lambda表达式就只能重复再重复了吗?当然不是.在这里.延迟执行很好的将其作用发挥得淋漓精致.前面说过.延迟执行保存的并不是值,而是获取 值的方法或者步骤.这样,每次我们调用完”获取”数据的方法.实际上.数据还没获得.得到的.只是一系列的”步骤”.我们可以在步骤的的基础上再添加步 骤.这样.就完美的实现了Lambda下的重构.

public static IQueryable<Employee> LowPaidSalaried(this IQueryable<Employee> sequence)
        {
            return from s in sequence
                   where s.Classification == 1 && s.MonthlySalary < 4000
                   select s;
        }
var allEmployees = FindAllEmployees();

var salaried = allEmployees.LowPaidSalaried();

这样.只有在需要数据的时候,才会根据”步骤”得到相应的数据.对于IEnumerable<T>,我们可以使用yield return来返回序列.

在复杂的查询中服用Lambda表达式最有效的办法就是封装封闭泛型类型的查询创建扩展方法.通过包含Lambda表达式的小方法叠加”步骤”.从而达到最有效的优化.

[转载]InfoQ: Data Link:jQuery的数据绑定插件

mikel阅读(1103)

[转载]InfoQ: Data Link:jQuery的数据绑定插件.

作为微软贡献的JQuery程序库之一,Data Link让双向数据绑定成为可能。尽管目的相同,Data Link的实现和WPF或者Silverlight则是完全不同的。

Data Link通过一个名为link的方法,来将表单中的input元素和目标对象绑定在一起。就像在XAML中设置一个DataContext一般,link 方法是由表单来调用的。默认情况下,这会在每个命名input元素和对象相对应的字段之间创建一个双向绑定。然而,还有很多选项可供选择。

如果不需要绑定所有的元素,开发者可以将一个形如“{fieldName: “elementName”, …}”的字典传给表单。这样就限定了数据绑定的范围,只会绑定指定的元素字段对。对于特定的元素,还可通过设置“twoWay: false”选项,来避免对象的改变反过来影响input元素。

值转换器和twoWay属性有些类似,命名为“convert”和“convertBack”。和XAML不同的是,既可以把一个函数作为参数传 入,也可以通过一个内联的匿名函数来定义转换器。如果在某些绑定字段变化的时候,其他字段也要随之变动的话,便可通过转换器来实现。

jQuery Data Link API依赖于JQuery 1.4.3,这个版本尚未发布。可以在github上下载jQuery 1.4.3和jQuery Data LinkJQuery Data Link基于MIT和GPL V2授权。

查看英文原文:Data Link – A Data-Binding for jQuery

[转载]ASP.NET MVC 专题 ViewEngine的发展以及应用

mikel阅读(910)

[转载][ASP.NET MVC 专题] ViewEngine的发展以及应用 – JasenKin – 博客园.

ViewEngine的发展以及应用

()MVC1版本的ViewEngine

从上图,我们可以知道:(1)当客户端发送请求时,DefaultControllerFactory根据RequestContext对象和ControllerName来生成我们的Controller。Controller的ViewDataDictionary将保存相关的数据,并且通过ViewEngine传递给View。

public virtual IController CreateController(RequestContext requestContext, string controllerName)
{
Type controllerType =
this.GetControllerType(requestContext, controllerName); //type = this.GetControllerTypeWithinNamespaces(requestContext.RouteData.Route, controllerName, namespaces);
return this.GetControllerInstance(requestContext, controllerType);
}

protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return (IController) Activator.CreateInstance(controllerType);//反射
}

2)在我们以前的MVC版本中,Controller拥有ViewEngine的属性。我们先看下下述的代码:ViewEngine依据ViewContextViewLocator怎么处理View以及响应客户端??

public void RenderView(ViewContext viewContext)
{
string viewLocation = ViewLocator.GetViewLocation(viewContext, viewContext.ViewName);//
根据ViewContext以及相关内容获取view的相对文件路径
string viewPath = viewContext.HttpContext.Request.MapPath(viewLocation););//获取view的绝对文件路径
string viewTemplate = File.ReadAllText(viewPath);//读取文件内容
IRenderer renderer = new PrintRenderer();
viewTemplate = renderer.Render(viewTemplate, viewContext);
//正则表达式处理相应内容,难点!
viewContext.HttpContext.Response.Write(viewTemplate);//发送响应到客户端
}

从上面的代码中,我们能够清晰的看到,总体框架就是这么赤裸裸的“请求—>响应”。虽然代码是过去版本的,但是依旧能够使我们比较容易的理解整个过程的细节。

关于以前版本的自定义ViewEngine请参考http://blog.maartenballiauw.be/post/2008/05/Creating-a-custom-ViewEngine-for-the-ASPNET-MVC-framework.aspx

(二)随着MVC版本的改进,我们的ViewEngine一直在变,从未被超越。ViewLocator不再使用了,将属性整合到ViewEngine中了。先看下我们的继承链上的LocationFormats,如下:

public abstract class VirtualPathProviderViewEngine : IViewEngine
{
public string[] AreaMasterLocationFormats { get; set; }
public string[] AreaPartialViewLocationFormats { get; set; }
public string[] AreaViewLocationFormats { get; set; }
public string[] MasterLocationFormats { get; set; }
public string[] PartialViewLocationFormats { get; set; }
public string[] ViewLocationFormats { get; set; }
}

上面的6个属性就涵盖了我们的代码文件的相对路径形式。如果要改变我们的代码文件路径,我们需要设置一下我们自己的LocationFormats。我们仅仅需要做的就是将父类的属性重新设置成相关的路径形式既可,如下示例:

1 public class HomeViewEngine : WebFormViewEngine
2 {
3 public HomeViewEngine(): this(Default)
4 {
5 }
6 public HomeViewEngine(string directory){
7 MasterLocationFormats = new[]{
8 string.Format(~/{0}/{{1}}/{{0}}.master, directory),
9 string.Format(~/{0}/shared/{{0}}.master, directory)
10 };
11 ViewLocationFormats = new[]{
12 string.Format(~/{0}/{{1}}/{{0}}.aspx, directory),
13 string.Format(~/{0}/{{1}}/{{0}}.ascx, directory),
14 string.Format(~/{0}/shared/{{0}}.aspx, directory),
15 string.Format(~/{0}/shared/{{0}}.ascx, directory)
16 };
17 PartialViewLocationFormats = ViewLocationFormats;
18 }
19 public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache){
20 return base.FindView(controllerContext, viewName, masterName, useCache);
21 }
22 public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache){
23 return base.FindPartialView(controllerContext, partialViewName, useCache);
24 }
25 }

将属性重新赋值后,相对路径就改变了,系统会通过GetLocation()方法获取每次请求匹配的相对视图路径地址。我们可以通过 ViewEngineCollection(IList<T>)来添加自己的ViewEngine。如下所示,我们通过双检锁的技巧(盗版的)来添加新的ViewEngine。其他的留给系统去考虑吧,XX,封装的太厉害了,哥也有时候摸不清方向!

public class BaseHomeController :Controller
{
public static object lockObj = new object();
private HomeViewEngine viewEngine = null;
public BaseHomeController(){
if (viewEngine == null){
lock (lockObj){
if (viewEngine == null){
viewEngine
= new HomeViewEngine();//设置你的路径前缀目录名称,可为空
ViewEngines.Engines.Add(viewEngine);
}
}
}
}
}

将你的相关的代码文件放在你想放置的地方,对于public HomeViewEngine(string directory){}构造函数,我们实例化 HomeViewEngine时传递相关的参数既可。系统会根据相关路径查找文件。

(三)RazorViewEngine的相对文件路径如下:

public RazorViewEngine()
{
base.AreaViewLocationFormats = new string[] { ~/Areas/{2}/Views/{1}/{0}.cshtml, ~/Areas/{2}/Views/{1}/{0}.vbhtml, ~/Areas/{2}/Views/Shared/{0}.cshtml, ~/Areas/{2}/Views/Shared/{0}.vbhtml };
base.AreaMasterLocationFormats = new string[] { ~/Areas/{2}/Views/{1}/{0}.cshtml, ~/Areas/{2}/Views/{1}/{0}.vbhtml, ~/Areas/{2}/Views/Shared/{0}.cshtml, ~/Areas/{2}/Views/Shared/{0}.vbhtml };
base.AreaPartialViewLocationFormats = new string[] { ~/Areas/{2}/Views/{1}/{0}.cshtml, ~/Areas/{2}/Views/{1}/{0}.vbhtml, ~/Areas/{2}/Views/Shared/{0}.cshtml, ~/Areas/{2}/Views/Shared/{0}.vbhtml };
base.ViewLocationFormats = new string[] { ~/Views/{1}/{0}.cshtml, ~/Views/{1}/{0}.vbhtml, ~/Views/Shared/{0}.cshtml, ~/Views/Shared/{0}.vbhtml };
base.MasterLocationFormats = new string[] { ~/Views/{1}/{0}.cshtml, ~/Views/{1}/{0}.vbhtml, ~/Views/Shared/{0}.cshtml, ~/Views/Shared/{0}.vbhtml };
base.PartialViewLocationFormats = new string[] { ~/Views/{1}/{0}.cshtml, ~/Views/{1}/{0}.vbhtml, ~/Views/Shared/{0}.cshtml, ~/Views/Shared/{0}.vbhtml };
this.ViewStartFileExtensions = new string[] { cshtml, vbhtml };
}

我们同样可以通过继承来覆盖原有的LocationFormats,这样,我们的视图文件路径也就可以随心所欲的放置在自己的目录下了。

更多Razor应用的请参考http://weblogs.asp.net/rashid/archive/2010/07/10/use-razor-as-asp-net-mvc-viewengine.aspx

总结

本文稍微的总结了ViewEngine的发展以及如何在项目中应用。随着MVC版本的改进,封装越来越多,很多细节被掩盖了。在Razor中,系统根据ViewEngine的相关路径属性获取的文件内容,系统如何处理@指令的?

Regex templatePattern = new Regex(@”@???”, RegexOptions.Multiline);//@??

MatchEvaluator replaceCallback = new MatchEvaluator(m => HandleRegexData());
templatePattern.Replace(viewTemplate, replaceCallback);这个需进一步学习才行。

作者:JasenKin
出处:http://www.cnblogs.com/jasenkin/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

[转载]ASP.NET MVC 3 Beta之WebGrid的使用

mikel阅读(967)

[转载]ASP.NET MVC 3 Beta之WebGrid的使用 – 海纳百川 – 博客园.

ASP.NET MVC 3 Beta中除了推出一种新的视图引擎Razor。还推出了几种新的HtmlHelper。我比较关注的是WebGrid,这篇文章将介绍一下 WebGrid的使用。WebGrid提供了分页和排序的功能,在此之前在MVC中分页和排序时需要自己去写的。这篇文章将分别介绍在aspx视图引擎和 Razor视图引擎中如何使用它。

我通过ADO.NET Entity Data Model从NORTHWND的Products中表中取数据。在Controller中取数据:

public class HomeController : Controller { public ActionResult Index() { NORTHWNDEntities entity = new NORTHWNDEntities(); return View( entity.Products.ToList()); } }

在aspx视图引擎中使用WebGrid代码如下:

<div id="grid"> <% var grid = new WebGrid(source: Model, defaultSort: "ProductName", rowsPerPage: 5); %> <%=grid.GetHtml( tableStyle: "grid", headerStyle: "head", alternatingRowStyle: "alt", columns: grid.Columns( grid.Column(format: (item) => Html.ActionLink("Edit", "Edit", new { id = item.ProductID })), grid.Column(format: (item) => Html.ActionLink("Delete", "Delete", null, new { onclick = string.Format("deleteRecord('Employee', '{0}')", item.ProductID), @class = "Delete", href = "JavaScript:void(0)" })), grid.Column("ProductName","产品名称"), grid.Column("QuantityPerUnit","每单位数量"), grid.Column("UnitPrice","单价"), grid.Column("UnitsInStock", "库存单位"), grid.Column("UnitsOnOrder","订单单位"), grid.Column("ReorderLevel","重新排序级别"), grid.Column("Discontinued","已停产") ) ) %> </div>

在Razor中使用WebGrid代码如下:

<div id="grid"> @{ var grid = new WebGrid(source: Model, defaultSort: "ProductName", rowsPerPage: 10); } @grid.GetHtml( tableStyle: "grid", headerStyle: "head", alternatingRowStyle: "alt", columns: grid.Columns( grid.Column(format: (item) => Html.ActionLink("Edit", "Edit", new { id = item.ProductID })), grid.Column(format: (item) => Html.ActionLink("Delete", "Delete", null, new { onclick = string.Format("deleteRecord('Product', '{0}')", item.ProductID), @class = "Delete", href = "JavaScript:void(0)" })), grid.Column("ProductName","产品名称"), grid.Column("QuantityPerUnit","每单位数量"), grid.Column("UnitPrice","单价"), grid.Column("UnitsInStock", "库存单位"), grid.Column("UnitsOnOrder","订单单位"), grid.Column("ReorderLevel","重新排序级别"), grid.Column("Discontinued","已停产") ) ) </div>

WebGrid构造函数如下:

public WebGrid(IEnumerable<dynamic> source, IEnumerable<string> columnNames = null, string defaultSort = null, int rowsPerPage = 10, bool canPage = true, bool canSort = true, string ajaxUpdateContainerId = null, string fieldNamePrefix = null, string pageFieldName = null, string selectionFieldName = null, string sortFieldName = null, string sortDirectionFieldName = null);

常见参数意思是:

1、source 表示数据源

2、columnNames表示显示的列

3、defaultSort 默认按什么排序

4、rowsPerPage 每页多少行数据

5、canPage 是否能排序

上面两段代码的意思是定义了一个既分页又能排序的grid。

运行:

在看看两个view的完整代码:

aspx:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<List<WebGridAspx.Models.Products>>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> 产品列表 </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <script type="text/javascript"> function deleteRecord(a, b) { alert("删除:"+b); } </script> <h2>产品列表</h2> <div id="grid"> <% var grid = new WebGrid(source: Model, defaultSort: "ProductName", rowsPerPage: 5); %> <%=grid.GetHtml( tableStyle: "grid", headerStyle: "head", alternatingRowStyle: "alt", columns: grid.Columns( grid.Column(format: (item) => Html.ActionLink("Edit", "Edit", new { id = item.ProductID })), grid.Column(format: (item) => Html.ActionLink("Delete", "Delete", null, new { onclick = string.Format("deleteRecord('Employee', '{0}')", item.ProductID), @class = "Delete", href = "JavaScript:void(0)" })), grid.Column("ProductName","产品名称"), grid.Column("QuantityPerUnit","每单位数量"), grid.Column("UnitPrice","单价"), grid.Column("UnitsInStock", "库存单位"), grid.Column("UnitsOnOrder","订单单位"), grid.Column("ReorderLevel","重新排序级别"), grid.Column("Discontinued","已停产") ) ) %> </div> </asp:Content>

Razor:

代码

@model List<WebGridRazor.Models.Products> @{ View.Title = "产品列表"; } <p> <h2>产品列表</h2> <div id="grid"> @{ var grid = new WebGrid(source: Model, defaultSort: "ProductName", rowsPerPage: 3); } @grid.GetHtml( tableStyle: "grid", headerStyle: "head", alternatingRowStyle: "alt", columns: grid.Columns( grid.Column(format: (item) => Html.ActionLink("Edit", "Edit", new { id = item.ProductID })), grid.Column(format: (item) => Html.ActionLink("Delete", "Delete", null, new { onclick = string.Format("deleteRecord('Product', '{0}')", item.ProductID), @class = "Delete", href = "JavaScript:void(0)" })), grid.Column("ProductName","产品名称"), grid.Column("QuantityPerUnit","每单位数量"), grid.Column("UnitPrice","单价"), grid.Column("UnitsInStock", "库存单位"), grid.Column("UnitsOnOrder","订单单位"), grid.Column("ReorderLevel","重新排序级别"), grid.Column("Discontinued","已停产") ) ) </div> </p>

Razor去掉了那些模板页的代码,使代码看起来更整洁。比较喜欢Razor。

总结:本文很简单,介绍了一下ASP.NET MVC 3 Beta中新功能WebGrid,由于这种方式WebGrid是在内存中分页和排序的,所以不适合大数据量。

代码:http://files.cnblogs.com/zhuqil/MvcApplication11.rar

作者:朱祁林
出处:http://zhuqil.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

[转载]再续 asp.net 域名欺骗式开发之泛解析域名

mikel阅读(886)

[转载]再续 asp.net 域名欺骗式开发之泛解析域名 – 路过秋天 – 博客园.

前言:

在很久前,曾发布过一篇:asp.net 域名欺骗式开发

有不少新新人类表示对此文不屑,觉得太基础,他们早懂了,懂了就懂了,毕竟还有人还没有懂的。

今天再续文,讲解域名欺骗式开发的进阶,泛解析方式开发:如果觉得本文对你有帮助,请热情地点下推荐

泛解析使用:在博客中比较常用,看博客园就知道了

对于http://cyq1162.cnblogs.com
或是http://www.cnlogs.com/cyq1162
访问的都是同一个用户,对*.cnblogs.com都解析到同一个IP去了

泛解析开发:

为了模拟多用户情况,对URL重定向、用户名称截取等开发测试时,这种欺骗式开发方式显的相当优越。

如何进行?

方式一:修改host

在上次asp.net 域名欺骗式开发中,我们通过修改host文件,实现了域名欺骗。

但是对于二级域名,我们只能通过一个一个输入来解析如:

#host文件
192.168.1.2 www.cnblogs.com
192.168.1.2 cyq1162.cnblogs.com
192.168.1.2 aaa.cnblogs.com
192.168.1.2 bbb.cnblogs.com
……

说明:

如果你想一个一个的敲,没人会阻止你,只是对于每个新注册的用户,当你进行测试时,就得加一行的host解析了。

疑问:host文件的域名能不能改成*.cnblogs.com实现泛解析欺骗?答案是不能!

于是,我们需要另一种方案来实现泛解析的欺骗式开发,而迎之而来的就是:

方式二:DNS解析[对于DNS就不解释那么多了,详情问Google]

实现简单步骤[示例演示泛解析博客园]:

1:安装[和iis安装方式大体差不多,只有服务器系统能装,xp就别折腾了]

2:配置域名DNS,上图

A :从管理工具打开DNS

B :右键新建区域

C :直接下一步

D :输入域名

E :直接下一步

F :直接下一步

G :直接点完成

H :区域建完了,右键新建主机

I :输入*,并指向本向IP,点击添加主机完成

OK,至此主机就完了,不过一般还不能立即生效[不知网上的其它教程咋就一下子就ping了出来,忽悠人还是咋的]

经过一翻折腾猜测性的发现,有两步需要注意

1:默认DNS要设置成本机IP

2:DNS生效刷新时间,默认15分钟,改一下吧,不改就等了。如下图

最后一切就绪,再Ping一下博客园,结果如图

结言:

至此,就完成了整个的泛解析了,现在可以继续以域名欺骗的方式开发了。

对于VS、IIS的配置还不会设置?回头看看:asp.net 域名欺骗式开发

本文仍旧写的很基础,看白了就是DNS的配置,只是配置VS+IIS合起来开发,就前进了那么一点了。
至于那些早懂的,懂了就懂了吧,还是有些人不懂的。
版权声明:本文原创发表于 博客园,作者为 路过秋天,博客 http://cyq1162.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。

[转载]探索Asp.net mvc 的文件上传(由浅入深)

mikel阅读(946)

[转载]探索Asp.net mvc 的文件上传(由浅入深) – 爱因斯坦的小脑 – 博客园.

代码下载:http://files.cnblogs.com/n-pei/mvcfileupload.zip

最近因为TeamVideo需要用到视频和图片上传功能,所以试着Google了很多资料,和大家分享下。

1.最基本的文件上传。

clip_image001

在View界面通过Form把数据POST到控制端(Controller),Controller把文件存储到服务器,再Redirect到其他页面。

View部分的代码:

clip_image003

Controller部分需要判断是否有Post过来文件,有文件就保存,再重定向到index页面。

clip_image005

上面的例子是最简单的,下一步我们考虑给它加上一个JQuery的UI,让上传文件时的样子变成如下:

clip_image006

要达到这个效果,首先需要下载JQuery UI的几个插件。

clip_image007

在模板中添加这些脚本:

clip_image009

把上面实现的简单的文件上传放到一个DIV中,我们需要实现的功能是当鼠标点击某个按钮时,这个DIV会弹出来。

clip_image011

最后是DIV弹出的脚本:

clip_image012

接下来我们考虑把图片上传到服务器后再让它显示在当前页面中。显示的效果如下:

clip_image014

也就是说我们在上传图片到服务器端后,需要得到此图片的创建时间,大小名称等。

clip_image016

FileRepository把文件的信息放到一个List中:

clip_image017通过Controller部分把这个List传递给View。

View部分的代码请参考附件。

对于图片的存储,我下一步想着把它存储在数据库中。

首先是创建表结构:

clip_image018

使用ADO.NET Data Model来存储数据,所以我们需要创建一个edmx文件。

clip_image019

保存到图片到数据库中的Controller部分:

clip_image020

View部分代码:

clip_image022

过程如下图:

clip_image024

这里需要一个辅助类来帮助输入文本的Post。你可以在下载的代码中看到。

上传图片并保存到数据库中,我们还需要来把图片显示出来,这个相对来说就比较麻烦了。

搜索了很久才找到的方法如下:

clip_image025

保存图片到数据库后的查询结果:

clip_image027

目前我还不知道如何把一个List的图片显示出来。希望谁能够提供一个好的解决方案。

传统的方法来存储文件(图片)上面的介绍已经很多了。如何使用AJAX方法来存储文件到服务器呢?

我搜索了下,比较多的是使用jQuery Form这个插件来实现的。

clip_image029

你需要去下载jQuery Form这个插件,放到你的Script文件夹中。并在Master模板中添加。

当你点击Button时,创建一个Form并使用AJAX方式POST到服务器端保存。保存方式就不说了,下面是使用jQuery Form的JS代码:

clip_image031

除了使用jQuery form这个插件还有其他的AJAX方式实现文件的上传:

我举两个例子:

1. jQuery & Flash AJAX上传文件。

代码地址:http://swfupload.googlecode.com/

主要是通过Flash和js的交互用flash程序来post数据到后台的Controller。

除了flash部分,其它的和上面介绍的代码大同小异。我会在代码包里放上这部分的代码,供大家下载。

效果:

clip_image032

2. 纯jQueryAJAX上传文件(http://valums.com/ajax-upload/)

这个推荐大家看一下。

clip_image033

看这边文章的同仁们,周末愉快,呵呵。

参考资料:

http://weblogs.asp.net/imranbaloch/archive/2010/04/03/image-preview-in-asp-net-mvc.aspx

http://weblogs.asp.net/jgalloway/archive/2008/01/08/large-file-uploads-in-asp-net.aspx

http://www.highoncoding.com/Articles/689_Uploading_and_Displaying_Files_Using_ASP_NET_MVC_Framework.aspx

http://www.mikesdotnetting.com/Article/125/ASP.NET-MVC-Uploading-and-Downloading-Files

http://valums.com/ajax-upload/

Cheers