[转载]ASP.NET MVC 2 验证消息本地化策略扩展

mikel阅读(987)

[转载]ASP.NET MVC 2 验证消息本地化策略扩展 – 阿不 – 博客园.

ASP.NET MVC2 结合System.ComponentModel.DataAnnotations 提供了一套非常有效的实体验证框架。对于错误信息的处理,它默认提供了两种选择:

  1. 字符串常量
  2. 从程序集资源文件读取

但是在我们这里,我们有一套自己的资源文件方案,也就是我们需要自己控件错误信息的本地化操作。由于在元数据,我们只能提供常量,无法进行字符串操作。一种比较直接和麻烦的办法就是重写所有的验证规则,在验证规则中对字符串常量进行本地化操作。

1 [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
2 public class CustomValidationAttribute : System.ComponentModel.DataAnnotations.ValidationAttribute
3 {
4 public CustomValidationAttribute(string message)
5 : base(() => message.Localize())
6 {
7 }
8 }

但是这样做,一方面会比较麻烦,所有的验证规则我们都要进行重写;另一方面我们在设计model时就是特别的小心使用我们自己重写过的规则才能达到 我们的目的,这将大大降低开发体验。为此,今天特别再次对照MVC2的源码,希望能找到一个可用的扩展点来解决这个问题。最终发现我们可以通过重写 DataAnnotationsModelValidatorProvider的GetValidators方法来达到我们希望的效果:

01 public class CustomDataAnnotationsModelValidatorProvider : System.Web.Mvc.DataAnnotationsModelValidatorProvider
02 {
03 protected override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes)
04 {
05 foreach (ValidationAttribute attribute in attributes.OfType<ValidationAttribute>())
06 {
07 if (!string.IsNullOrWhiteSpace(attribute.ErrorMessage))
08 {
09 attribute.ErrorMessage = attribute.ErrorMessage.Localize();
10 }
11
12 }
13
14 var validators = base.GetValidators(metadata, context, attributes);
15
16 return validators;
17 }
18 }

代码非常简单,我们只是在调用GetValidators方法之前,对attribute的错误消息进行一次本地化操作处理即可。通过这一次处理, 我们可以同步处理客户端验证消息和服务器端验证消息的本地化。下面的工作就是用这个Provider来代替它的父类,在Global.asax添加下面的 代码即可完成:

1 ModelValidatorProviders.Providers.RemoveAt(0);
2 ModelValidatorProviders.Providers.Insert(0, new CustomDataAnnotationsModelValidatorProvider());

通过这样一个小小的扩展,就可以很完美的达到我们的目的。不过,为了这个小扩展,却花费了我们不少的时间。

[转载]初探Razor视图引擎

mikel阅读(1392)

[转载]初探Razor视图引擎 – 冷冷的地盘 – 博客园.

前一段时间,ScottGu在博客上发表了一些有关WebMatrix的文章,其中提到了一个新的ASP.NET视图引擎——Razor。

Razor有着非常简单和干净的语法,但是不管怎么样,它毕竟只是一个表现层面的东西,其底层仍然使用ASP.NET,与平时的开发没有什么大的区别,唯一的区别在于:视图的简洁。

安装

使用Razor需要安装 Microsoft ASP.NET Web Pages,当然,官方的做法是:直接用Web Plamform安装WebMatrix,不过WebMatrix现在还处于Beta阶段,估计以后会增加更多支持Razor的功能。

安装完毕后打开WebMatrix,然后就可以通过Site Form Template来新建一个站点测试了。

默认生成的站点在“我的文档”\My Web Sites下以站点名命名。

初窥

Razor的语言简单之极,只需记住一个字符就可以:@。

在传统的ASP.NET视图引擎中,如果我们要进行一些数据绑定或者逻辑判断就会使用类似下面的做法:

1 <%
2 var testStr1 = "Hello";
3 var testStr2 = "lengleng";
4 %>

我们先搞了两个变量,当然,这些变量可以从任意的地方获得,然后,我们将这两个变量绑定到页面中去:

1 <%=testStr1 %>,Your name:<%=testStr2 %>

不知道您看的如何,总之我感觉是够乱的。

同样的东西,我们用Razor的语法来重写,会是怎么样的呢?(为了着色,直接贴图片了)

当然了,结果是一样的,不过在表现力上显然Razor更胜一筹,因为来回的<%%>看的人眼花,例如下面这个MVC中登陆部分的用户控件:

01 <%
02 if (Request.IsAuthenticated) {
03 %>
04 欢迎您,<b><%: Page.User.Identity.Name %></b>!
05 [ <%: Html.ActionLink("注销", "LogOff", "Account") %> ]
06 <%
07 }
08 else {
09 %>
10 [ <%: Html.ActionLink("登录", "LogOn", "Account") %> ]
11 <%
12 }
13 %>

我唯一的感觉:晕!用Razor后:

是不是更加的人性一些呢?唯一需要说的就是@:,这是说它后面的内容是混合内容,即有纯文本又有服务器端代码。不过上面的代码我没有做过测试,这是改成了Razor的样式,所以大家谨慎参考。

Helper

严格的讲这部分不能算语法层面上的特性,只能算是支持Razor的辅助类库。因为Razor实在过于简单了,说白了就一个@,只要会C#或才VB.NET就行,以前的知识全部能用,所以为了使内容不那么水,我将这部分也加了进来。完整的文档请到这里下载PDF文档,上面详细说明了Razor的细节(还有前面提到的Microsoft ASP.NET Web Pages安装包)。

  • 类似于传统ASP.NET的母版页、用户控件机制

在呈现类似用户控件的内容时(说白了就是用户控件),可以使用RenderPage辅助类,例如:

而所谓的“用户控件”其实就是一个没有<html><head><body>的裸页,将经常会使用的一部分逻辑或者内容分离出来以达到复用。

母版页可以提供统一的外观,按照原来的思路,一般会在母版页中插入ContentPlaceHolder控件来指明哪部分是要被使用页来替换内容的,在Razor中,它不叫ContentPlaceHodler,叫RenderBody。

不同的时,传统ASP.NET可以在母版页中插入多个ContentPlaceHolder,而RenderBody只能有一个。其实,类似ContentPlaceHolder,Razor中也提供RenderSection来实现。

先说RenderBody。当我们在母版页中的某个位置写了@RenderBody()后,接下来在使用母版页时,只需在页面的顶部写入:

@{ LayoutPage = “MasterPageLocation”; }, 这样,接下来的内容会自动填充到母版页RenderBody()对应的位置:

MasterPage:

Page:

使用RenderSection时需要指定Section片断的名字, 我们可以在母版页中的相关位置上写上@RenderSection(“name”),然后在使用母版页的页面中声明类似的Section,即:@section header {/*HTML or other*/},具体如下:

MasterPage:

Page:

  • 对Microsoft SQL Server Compact Edition数据库的辅助类

这个比较简单,就是通过Database类来操作数据。例如最常用的“查”:

查出来的数据想怎么着就怎么着吧,管不着了……

很简单不是么?至于“增”,“改”,“删”都用Database.Execute()方法来完成。

  • 文件上传与Image处理

对于常用的文件上传功能,Razor做了封装,让我们使用更加的方便,只需简单的在页面上使用FileUpload类的相关方法即可,配合Razor的清爽语法,可读性非常高:

配合C#4.0的默认参数,一个文件传的功能就实现了(其实我觉得更像是一种使用控件)生成的HTML如下:

1 <form action="" enctype="multipart/form-data" method="post">
2 <div id="file-upload-all-files">
3 <div><input name="fileUpload" type="file" /></div>
4 </div>
5 <div id="file-upload-buttons"><input type="submit" value="Upload" /></div>
6 </form>

对于更加常见的Image,Razor也做了相应的封装:WebImage,常用的一些方法如下:

1 WebImage.Resize(); //改变图像大小
2 WebImage.FlipXXXX(); //图像旋转,XXXX对就旋转方向,例如Vertical垂直翻转,Horizontal水平翻转,Left,Right……
3 WebImage.AddTextWatermark(); //在图像上加入文字水印
4 WebImage.AddImageWatermark(); //在图像上加入图像水印

  • 视频

对于常见的视频需求,Razor提供了简化手动配置视频标签的辅助类:Video。当下最为流行的网页视频播放无非3种:Flash,Windows Media Player,Silverlight,至于HTML5的先天支持那是后话。Video充分利用C#4.0默认参数的威力,使得生成一个视频标签也是手到擒来:

至于Windows Media Player和Silverlight就不多说了,大同小异,有兴趣可以研究Video.MediaPlayer(),Video.Silverlight()。

  • 社交网络操作的简化

天朝上不了Twitter,但是世界处处却留下了Twitter的影子……作为时下最火的社交网站,我等暴民经常爬出去上推,扯远了……Razor 提供了对诸如Twitter,Facebook,Gravator,ReCaptcha等一些社交网络经常提及的网站的简化,使得跨站点的资源调用更加方 便,用Reflector看了一下C:\Program Files\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\Assemblies下的Microsoft.WebPages.Helpers.Toolkit.dll,我们发现:

其中提供了很多有用的封装,不过,可惜,可惜……

看一个简单的例子:

运行如下:

小梯子一搭,走您的…………

总结

Razor作为传统ASP.NET视图引擎外的新选择,使得Web开发中“视图”部分更加的清爽。在这里我并不是在鼓吹新技术、新特性,或者是抱着new features抚摸来抚摸去,大家仁者见仁智者见智吧,毕竟这个新东西实在很简单,只是一个新的视图引擎。

在下一版本的ASP.NET MVC中,Razor也会被加入可选的视图引擎之一,而我在下面给出的链接中已经有人将这一想法提前实现了,我想MVC的表现力再加上Razor的简洁定会使开发更加的愉快。

相关链接

1. 为ASP.NET MVC 2.0添加Razor模板引擎 (on .NET4)重典

2. ASP.NET Web Pages with Razor Syntax

3. Microsoft WebMatrix in Context and Deploying Your First SiteScott Hanselman

4. WebMatrix

5. Introducing “Razor” – a new view engine for ASP.NETScott Guthrie

6. Introducing WebMatrixScott Guthrie

[转载]提搞网站访问速度可做哪些优化

mikel阅读(1110)

[转载]提搞网站访问速度可做哪些优化 – 熊哥 – 博客园.

1.Flex 图表组件介绍

在Flex 中提供了一系列图表组件,可以使用图表或图形来显示数据

Flex 中可以把表格数据分为条形图表(Bar),饼行图表(Pie),折线图表(Line).

2.Flex 支持的坐标轴

CategoryAxis: 对应一组数组值到坐标轴上面。

LinearAxis: 对应数字数据到坐标轴上

LogAxis: 对数的对象数字数据到坐标轴上.

DateTimeAxis:对应时间基础的数据到坐标轴上.

3.面积图表(AreaChart)

代码

1 <?xml version=”1.0″ encoding=”utf-8″?>
2 <mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”absolute” fontSize=”12″>
3 <mx:Script>
4 <![CDATA[
5 import mx.collections.ArrayCollection;
6
7 public var scores:ArrayCollection=new ArrayCollection([
8 {id:1,name:”贺臣”,Maths:98,Chinese:82},
9 {id:2,name:”菜包”,Maths:66,Chinese:77},
10 {id:3,name:”张三”,Maths:23,Chinese:99},
11 {id:4,name:”王五”,Maths:88,Chinese:55}
12 ]);
13
14 ]]>
15 </mx:Script>
16 <mx:Panel x=”98″ y=”40″ width=”485″ height=”392″ layout=”absolute”>
17 <mx:AreaChart x=”10″ y=”10″ id=”myChart” height=”248″ width=”431″ dataProvider=”{scores} showDataTips=”true”>
18 <mx:horizontalAxis>
19 <mx:CategoryAxis dataProvider=”{scores} categoryField=”name”/>
20 </mx:horizontalAxis>
21 <mx:series>
22 <mx:AreaSeries yField=”Maths” displayName=”数学”/>
23 <mx:AreaSeries yField=”Chinese” displayName=”中文”/>
24 </mx:series>
25 </mx:AreaChart>
26 <mx:Legend dataProvider=”{myChart} x=”10″ y=”289″ width=”431″/>
27 </mx:Panel>
28 </mx:Application>
29

上面的Areachart 图表控件,以学生名(name)作为x轴,以分数(score) 作为y轴,并定义了两个序列分别显示数学和中文成绩。

4.面积图表特性

xField: 定义x 坐标每个节点的数值

yField: 定义y 坐标每个节点的数值

minField: 定义y 坐标最低位置的数值

form: 定义图表显示的方式:curse(曲线),horizontal(水平),reverseStep(反向台阶),step(台阶),vertical(垂直)。

[转载]Flash 表报之 AreaChart

mikel阅读(1044)

[转载]Flash 表报之 AreaChart – 情缘 – 博客园.

1.Flex 图表组件介绍

在Flex 中提供了一系列图表组件,可以使用图表或图形来显示数据

Flex 中可以把表格数据分为条形图表(Bar),饼行图表(Pie),折线图表(Line).

2.Flex 支持的坐标轴

CategoryAxis: 对应一组数组值到坐标轴上面。

LinearAxis: 对应数字数据到坐标轴上

LogAxis: 对数的对象数字数据到坐标轴上.

DateTimeAxis:对应时间基础的数据到坐标轴上.

3.面积图表(AreaChart)

代码

1 <?xml version=”1.0″ encoding=”utf-8″?>
2 <mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”absolute” fontSize=”12″>
3 <mx:Script>
4 <![CDATA[
5 import mx.collections.ArrayCollection;
6
7 public var scores:ArrayCollection=new ArrayCollection([
8 {id:1,name:”贺臣”,Maths:98,Chinese:82},
9 {id:2,name:”菜包”,Maths:66,Chinese:77},
10 {id:3,name:”张三”,Maths:23,Chinese:99},
11 {id:4,name:”王五”,Maths:88,Chinese:55}
12 ]);
13
14 ]]>
15 </mx:Script>
16 <mx:Panel x=”98″ y=”40″ width=”485″ height=”392″ layout=”absolute”>
17 <mx:AreaChart x=”10″ y=”10″ id=”myChart” height=”248″ width=”431″ dataProvider=”{scores} showDataTips=”true”>
18 <mx:horizontalAxis>
19 <mx:CategoryAxis dataProvider=”{scores} categoryField=”name”/>
20 </mx:horizontalAxis>
21 <mx:series>
22 <mx:AreaSeries yField=”Maths” displayName=”数学”/>
23 <mx:AreaSeries yField=”Chinese” displayName=”中文”/>
24 </mx:series>
25 </mx:AreaChart>
26 <mx:Legend dataProvider=”{myChart} x=”10″ y=”289″ width=”431″/>
27 </mx:Panel>
28 </mx:Application>
29

上面的Areachart 图表控件,以学生名(name)作为x轴,以分数(score) 作为y轴,并定义了两个序列分别显示数学和中文成绩。

4.面积图表特性

xField: 定义x 坐标每个节点的数值

yField: 定义y 坐标每个节点的数值

minField: 定义y 坐标最低位置的数值

form: 定义图表显示的方式:curse(曲线),horizontal(水平),reverseStep(反向台阶),step(台阶),vertical(垂直)。

[转载]在项目中自定义MVC模板

mikel阅读(1028)

[转载]在项目中自定义MVC模板 – 概说 – BaconPeng – 博客园.

找到公用模板

$Microsoft Visual Studio 10.0$\Common7\IDE\ItemTemplates\CSharp\Web\MVC 2\CodeTemplates

VS2008一样

把这个目录拷贝到项目根目录下,出现的对话框点击“取消”。N次之后,模板被添加进来(那几个tt)。

这时,项目会使用CodeTemplates中的模板覆盖全局模板。

可以修改模板或者添加新的。最好是下载T4 Editor来编辑模板,会有语法高亮和Intelli sence

比如说你可以修改Controller.tt来添加自己经常会用到的action,或者修改原来的action成你自己的处理方式。

或者添加一个View Template,那样在Add View..菜单点击之后,会有多一个View可以选择。

比如我加了一个MyList.tt

那么在Add View…菜单中会多出一个View MyList

如果项目中有许多地方会用到模板里没有定义过的actionview

可以用这种方法自定义。

当然,如果你觉得MVC缺省模板本来就不好用,也可以直接修改本文开始处目录里的全局模板,这样机器上所有新建 的MVC程序都将使用你修改过的模板。

[转载]ASP.NET中Response.Redirect()方法深度剖析

mikel阅读(945)

[转载][原创]ASP.NET中Response.Redirect()方法深度剖析 – 天涯走狗 – 博客园.

本文中,我们将借助http分析工具Fiddler,来对Response.Redirect()方法的整个流程进行剖 析

首先在Visual Studio中新建一个网站,在Default页面的Page_Load事件中写下 Response.Redirect(“http://www.baidu.com”);

然后添加一个 Page_LoadComplete事件处理方法。

最终效果如下:

clip_image001

在12和17行设置了断点,方便对整个过程进行观 察。

打开Fiddler,用以观察整个过程中的HTTP数据。

clip_image002

点击“调试”按钮

clip_image003

程序开始执行。

这时Fiddler中出现了一条数据:

clip_image004

这是浏览器向http://localhost:53765/WebSite2/Default.aspx 发出了一个GET请求。

这条THHP GET请求导致服务器端的程序开始执行,执行到12行时遇到断点,于是停下,此时还没有执行Response.Redirect语句。

clip_image005

这时候服务器还没有对刚才浏览器发出的请求作出响 应,所以在Fiddler中,并没有读到这次HTTP请求的响应。

然后我在服务器 端按F5,使程序继续执行。当程序执行了Response.Redirect语句之后,在Fiddler中收到了服务器端的回应。

clip_image006

很明显,服务器端并没有返回给我们页面的 Default页面的html数据,而是给了一个302 Found,并在Location中给出了“http://www.baidu.com”, 这就是在告诉浏览器:请重新发出一个HTTP请求,所请求的URL为”http://www.baidu.com”

浏览器于是按照吩咐,重新发出了一个http的请求

clip_image007

这次是向百度的服务器发出了一个GET请求。

然后百度返回了如下数据:

clip_image008

这次是200 OK,content-type 是html,后边跟的是百度主页的html代码

然后浏览器根据这个返回数据,解析 html代码,在我们的屏幕上将百度的样子显示了出来

clip_image009

并 且,这个过程中我们注意到:Page_LoadComplete()方法并没有被执行,这说明当服务器执行到Response.Redirect语句时, 会立即中断页面的生命周期,直接向客户端返回信息,让客户端进行重定向操作。

整个过程就是这样了。

另外

ASP.NET 4 增加了一个RedirectPermanent方法,该方法同样是重定向,但生成的HTTP响应状态不是上边所演示的302,而是301(永久跳转)

301 是对搜索引擎最友好的重定向方式。

那么什么叫做对搜索引擎友好呢?

比 如你有个网站http://www.foo.com ,当人们访问http://www.foo.com 这个URL时,你就把他们重定向到http://www.foo.com/widgets/,那么当搜索引擎爬到http:www.foo.com这个网 址时,如果它不能很好地跟随重定向,则它将认为http://www.foo.com页面时没有内容的,所以这个页面的排名将会非常靠后。

如 果我们把一个地址采用301 跳转方式跳转的话,搜索引擎会把老地址的PageRank等信息带到新地址,同时在搜索引擎索引库中彻底废弃掉原先的老地址。

这只是很 简单的叙述,其实关于搜索引擎友好的问题很复杂,欲了解更多请自行搜索之。

参考:

<http://www.cnblogs.com/xl888/archive/2008/10/28/1320945.html>

<http://www.webconfs.com/redirect-check.php>

<http://www.webconfs.com/how-to-redirect-a-webpage.php>

<http://www.cnblogs.com/longgel/archive/2010/06/02/1749897.html>

[转载]Asp.net mvc 2中使用Ajax的三种方式

mikel阅读(1070)

[转载]Asp.net mvc 2中使用Ajax的三种方式 – 海纳百川 – 博客园.

ASP.NET MVC中,我们能非常方便的使用Ajax。这篇文章将介绍三种Ajax使用的方式,分别为原始的Ajax调用、JQuery、Ajax Helper。分别采用这三种方式结合ASP.NET mvc去实现一个史上最简单的留言板。

首先看一下原始的Ajax的调用的

定义CommentController,代码如下:

public class CommentController : Controller
{
    private IList<string> _comments = new List<string>();

    public ActionResult Index()
    {
        return View();
    }

    public void AddCommentServer()
    {
         string comment = Request["comment"].ToUpper();
        _comments.Add("<li>" + comment + "</li>");
        Response.ContentType = "text/html";
        Response.Write(string.Join("\n", _comments.ToArray()));
    }

}

ASP.NET MVC中添加一个custom_ajax.js,加入下面使用ajax的脚本代码,调用AddCommentServer方法。

function getXmlHttpRequest() {
      var xhr;
      //check for IE implementation(s)
      if (typeof ActiveXObject != 'undefined') {
          try {
              xhr = new ActiveXObject("Msxml2.XMLHTTP");
          } catch (e) {
              xhr = new ActiveXObject("Microsoft.XMLHTTP");
          }
      } else if (XMLHttpRequest) {
          //this works for Firefox, Safari, Opera    
          xhr = new XMLHttpRequest();
      } else {
          alert("对不起,你的浏览器不支持ajax");
      }

      return xhr;
  }
    
  function getMessage() {
      //get our xml http request object
      var xhr = getXmlHttpRequest();
  
      //prepare the request
      xhr.open("GET", "Comment/AddCommentServer?comment=" + document.getElementById("Comment").value, true)
      
      //setup the callback function
      xhr.onreadystatechange = function() {
          //readyState 4 means we're done
          if(xhr.readyState != 4) return;
              
          //populate the page with the result
          document.getElementById('comments').innerHTML = document.getElementById('comments').innerHTML + xhr.responseText;
      };
  
      //fire our request
      xhr.send(null);
  }

在View中引入此脚本,创建一个简单的表单,并添加触发的代码:

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h4>Comments</h4>    
    <ul id="comments">        
    </ul>
        <%= Html.TextArea("Comment", new{rows=5, cols=50}) %>
        <button type="submit" onclick="getMessage()">Add Comment</button>
             <span id="indicator" style="display:none"><img src="../../content/load.gif" alt="loading..." /></span>                                 

</asp:Content>

<asp:Content ID="Content3" ContentPlaceHolderID="headContent" runat="server">
    <script src="../../Scripts/custom_ajax.js" type="text/javascript"></script>
</asp:Content>
   效果如下:
3 
第二种方式:利用Jquery:
    在控制器中添加代码IndexJquery方法和AddComment方法的代码,CommentController代码如下所示
public class CommentController : Controller
{
    private IList<string> _comments = new List<string>();

    public ActionResult Index()
    {
        return View();
    }

    public ActionResult IndexJquery()
    {
        return View();
    }

    public ActionResult AddComment(string comment)
    {
        _comments.Add("<li>" + comment + "</li>");
        return Content(string.Join("\n", _comments.ToArray()));
    }

    public void AddCommentServer()
    {
        string comment = Request["comment"].ToUpper();

        _comments.Add("<li>" + comment + "</li>");

        Response.ContentType = "text/html";
        Response.Write(string.Join("\n", _comments.ToArray()));
    }

}
    根据IndexJquery,创建View表单IndexJquery.aspx:
    <h4>Comments</h4>    
    <ul id="comments">        
    </ul>
    
    <% using (Html.BeginForm("AddComment","Comment",FormMethod.Post,new {@class="hijax"})) { %>    
        <%= Html.TextArea("Comment", new{rows=5, cols=50}) %>
        <button type="submit">Add Comment</button>
             <span id="indicator" style="display:none"><img src="http://www.cnblogs.com/content/load.gif" alt="loading..." /></span>                                 
    <% } %>
    在View中引用Jquery:
    <script src="http://www.cnblogs.com/Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>

添加下面脚本:

    <script type="text/javascript">
        //execute when the DOM has been loaded
        $(document).ready(function () {
            //wire up to the form submit event
            $("form.hijax").submit(function (event) {
                event.preventDefault();  //prevent the actual form post
                hijack(this, update_sessions, "html");
            });
        });

        function hijack(form, callback, format) {
            $("#indicator").show();
            $.ajax({
                url: form.action,
                type: form.method,
                dataType: format,
                data: $(form).serialize(),
                completed: $("#indicator").hide(),
                success: callback
            });
        }

        function update_sessions(result) {
            //clear the form
            $("form.hijax")[0].reset();
            $("#comments").append(result);
        }
    
    </script>





效果:与方式一效果一样


第三种方式:Ajax Helper。
    将最简单的留言板修改成Ajax Helper的方式。

1、首先了解一下Ajax Helper下面四种方法。

a、Ajax.ActionLink():它将渲染成一个超链接的标签,类似于 Html.ActionLink()。当它被点击之后,将获取新的内容并将它插入到HTML页面中。

b、Ajax.BeginForm():它将渲染成一个HTML的Form表单,类似于 Html.BeginForm()。当它提交之后,将获取新的内容并将它插入到HTML页面中。

c、Ajax.RouteLink():Ajax.RouteLink()类似于 Ajax.ActionLink()。不过它可以根据任意的routing参数生成URL,不必包含调用的action。使用最多的场景是自定义的 IController,里面没有action。

d、Ajax.BeginRouteForm():同样 Ajax.BeginRouteForm()类似于Ajax.BeginForm()。这个Ajax等同于Html.RouteLink()。

这个例子中使用Ajax.BeginForm(),下面具体了解Ajax.BeginForm()的参数。看下面代码

    <% using (Ajax.BeginForm("AddComment", new AjaxOptions
                                            {
                                                HttpMethod = "POST", 
                                                UpdateTargetId = "comments",
                                                InsertionMode = InsertionMode.InsertAfter                                                
                                            })) { %>

actionName:AddComment(action的名 字)

controllerName:CommentController(Controller的名字)

ajaxOptions:

HttpMethod:Ajax的请求方式,这里为POST

UpdateTargetId :Ajax请求的结果显示的标签的ID,这里为comments

InsertionMode:将Ajax结果插入页面的方式,这里将ajax的结果放置到comments的后面

2、实现:

CommentController中 添加IndexAjaxHelp方法。

public ActionResult IndexAjaxHelp()
{
    return View();
}

根据IndexAjaxHelp生成View表单IndexAjaxHelp.aspx,定义表单:

    <h4>Comments</h4>    
    <ul id="comments">        
    </ul>
    
    <% using (Ajax.BeginForm("AddComment", new AjaxOptions
                                            {
                                                HttpMethod = "POST", 
                                                UpdateTargetId = "comments",
                                                InsertionMode = InsertionMode.InsertAfter                                                
                                            })) { %>
    
        <%= Html.TextArea("Comment", new{rows=5, cols=50}) %>
        <button type="submit">Add Comment</button>
                                            
    <% } %>

要在此View中添加下面两个脚本文件:

    <script src="http://www.cnblogs.com/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
    <script src="http://www.cnblogs.com/Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>

这样就行了,我们发现比用JQuery方便很多,但是使用jQuery将灵活很多。

3、效果:和方式一样。

总结:本文非常的简单,在asp.net mvc中实现了3中ajax的调用方式,实现了一个最简单的留言板程序。推荐使用jQuery和Ajax Helper这两种。Ajax Helper使用非常简单,Jquery比较灵活。

更新:三种方式都实现了一个最简单的留言板程序

参考:

ASP.NET MVC 2 In Action

Pro ASP.NET MVC 2 Framework, Second Edition

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

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

[转载]开发一个可绑定数据源的jQuery数据表格插件

mikel阅读(964)

[转载]开发一个可绑定数据源的jQuery数据表格插件 – 侯锋’s Blog – 博客园.

此文将实现一个的JQuery表格插件JQuery.DataGrid。

  1. 固定表头
  2. 列宽可调整
  3. 单击列头可排序
  4. 双击单元格可编辑
  5. 可绑定数据源

看下效果吧:

HTML – 模板代码:

<table  id=“test”>
<tr  class=“header”>
<td  style=“width: 100px;” sort=’true‘>
姓名
</td>
<td  style=“width: 100px;” sort=’true‘>
性别
</td>
<td  style=“width: 100px;” sort=’true‘>
年龄
</td>
<td  style=“width:200px;” sort=’true‘>
住址
</td>
</tr>
<tr  class=“itemtemplate”>
<td  editable=’true‘>
{姓 名}
</td>
<td  editable=’true‘>
{性别}
</td>
<td  editable=’true‘>
{年 龄}
</td>
<td  editable=’true‘>
{住址}
</td>
</tr>
</table>

jsascript代码:

//测试数据
var  dataJsonStr='{tablename:“”,rows:[{“姓名“:”曹 操“,”性别“:”“,”年龄“:”51“,”住址“:”许 昌“},{“姓名“:”诸 葛亮“,”性别“:”“,”年龄“:”40“,”住址“:”南 阳“},{“姓名“:”周 瑜“,”性别“:”“,”年龄“:”40“,”住址“:”江 东“},{“姓名“:”大 乔“,”性别“:”“,”年龄“:”30“,”住址“:”江 东“},{“姓名“:”小 乔“,”性别“:”“,”年龄“:”28“,”住址“:”江 东“},{“姓名“:”曹 操“,”性别“:”“,”年龄“:”51“,”住址“:”许 昌“},{“姓名“:”诸 葛亮“,”性别“:”“,”年龄“:”40“,”住址“:”南 阳“},{“姓名“:”周 瑜“,”性别“:”“,”年龄“:”40“,”住址“:”江 东“},{“姓名“:”大 乔“,”性别“:”“,”年龄“:”30“,”住址“:”江 东“},{“姓名“:”小 乔“,”性别“:”“,”年龄“:”28“,”住址“:”江 东”}]}’;

//清空数据
$(‘#test’).DataGridClear();
//设定行样式
$(‘#test’).DataGridSetItemClass(“tr1“,”tr2“,”trhover”);
//绑定数据,并设置宽度高度
$(‘#test’).DataGrid(“100%”,200,dataJsonStr);

结构示意图:

如何根据HTML模板创建DataGrid整个结构?

1.首先创建 表头 主体 等各区域:

TableBody.addClass(‘TableBody’);
TableBody.wrap(“<div id='”+MyTableId+“‘ class=’houfeng-table’></div>”);
var  MyTable=$(‘#’+MyTableId);
TableBody.data(‘MyTable’,MyTable);
TableBody.before(“<table class=’TableHead’ ></table>”);
var  TableHead=MyTable.find(“.TableHead”);
TableBody.data(‘TableHead’,TableHead);
TableBody.wrap(‘<div  class=“TableBodyArea”></div>’);
TableHead.wrap(“<div class=’TableHeadArea’ onselectstart=’return false;’></div>”);
var  TableBodyArea=MyTable.find(‘.TableBodyArea’);
var  TableHeadArea=MyTable.find(‘.TableHeadArea’);
TableBody.data(‘TableBodyArea’,TableBodyArea);
TableBody.data(‘TableHeadArea’,TableHeadArea);

上面代代中红色高亮 TableBody 为表主体, TableHead 为表头

2.创建表头

TableBody.find(‘.header’).clone().prependTo(TableHead);

TableBody 其实便是HTML模板Table , 将  .header 的行移到到表头表格中作为表头.

3.创建表主体

创建表主体,其实便是根据数据源及模板 循环创建每一行 , 这里用了 上篇文章提到的 Repeater 来创建, 详细 请看JavaScript实现Repeater.

4.处理当列过多时横向滚动条的问题

TableBodyArea.scroll(function  (){
var  ml=0-parseInt(TableBodyArea.attr(‘scrollLeft’));
TableHead.css(‘margin-left’,ml);
});

TableBodyArea 为TableBody外包裹的一个Div

5.如何实现单元格编辑

双击td时在td中动态插入一个文件本框为将td的innerHTML给文本框,在文本焦点失去时,将文本框值赋给td的innerHTML,将移 除文本框 代码如下:

TableBody.find(‘td’).live(‘dblclick’,function(){
var  td=$(this);
if(td.attr(‘editable’)==’true‘)
{
var  text=td.text();
var  html=“<input type=’text’ class=’TdEditTextBox’ value='”+$.trim(text)+“‘ />”;
td.html(html);
td.addClass(“tdediting”);
//
$(this).find(‘.TdEditTextBox’).focus().focus().focus().focus();
$(this).find(‘.TdEditTextBox’).blur(function(){
var  val=$(this).val();
td.html(val);
td.removeClass(“tdediting”);
});
}
});

6. 如何排序:

由时间问题请容我下回分解!!

源码下载:

请遵守 LGPL英文 LGPL中文 协议! 下载.

[转载]ASP.NET Mvc + NHibernate + Unity Application Block 示例程序

mikel阅读(1001)

[转载]ASP.NET Mvc + NHibernate + Unity Application Block 示例程序 – Assion Yang – 博客园.

今天无意间看到了Unity Application Block (以下简称Unity),感觉很不错,用起来挺方便的说。于是一时兴起写了这个留言本的小示例。数据库操作采用的NHibernate,UI直接用的

ASP.NET Mvc了。项目基于VS2010 + SQLServer 2005 ,就一个表的增删改查操作很简单。目的是为了体验下Unity的Ioc功能。

国际惯例,先上个项目结构图

项目只是演示使用,未建立公共类和配置项抽象出来等工作,各个项目如下:

Guestbook.Biz 业务层,具体业务实现。这里只实现了增删改查

Guestbook.Dal 持久层,基于NHibernate的ORM映射。实现增删改查

Guestbook.IBiz 业务层接口,给UI引用实现解藕。UI层不直接引用具体业务类,实现面向接口

Guestbook.IDal 持久层接口,给Biz引用实现解藕。方便更换不同数据库持久类(PS;虽然NHibernate 已经可以支持多库,这里纯为了娱乐)

Guestbook.Model 持久实体,NHibernate的映射文件也放到这个类库里面了

Guestbook.Unity 简单封装了一下Unity,传入相应接口即可New相应的在Web.Config中配置的具体业务类

Guestbook.Web UI层,ASP.NET Mvc项目。控制器直接引用的业务接口IBiz和Model还有Unity其它全部不引用

采取从下往上依次说各层的东西。首先从数据库。。。。(略)—从持久层说起吧。持久层采用了NHibernate基本配置和映射配置就不说了 (hkgoogle),首先在Guestbook.Dal中写了一个NHibernateHelper帮助类,代码如下:

代码

/// <summary>
/// NHibernate 操作辅助类
/// </summary>
public class NHibernateHelper
{
private ISessionFactory _sessionFactory;
public NHibernateHelper()
{
_sessionFactory
= GetSessionFactory();
}
private ISessionFactory GetSessionFactory()
{
Configuration cfg
= new Configuration();
ISessionFactory sf
=
cfg.Configure().BuildSessionFactory();
return sf;
}
public ISession GetSession()
{
ISession session
= _sessionFactory.OpenSession();
return session;
}
}

以上就是创建个NHibernate的Session。

接下来是在Guestbook.IDal定义持久层相关的接口,首先是一个通用的增删改查接口,如下:

代码

/// <summary>
/// 数据执 行类接口
/// </summary>
/// <typeparam name=”T”></typeparam>
public interface IDbObject<T>
{
void Save(T entity);
void Delete(T entity);
void Update(T entity);
T Load(
int sysNo);
IList
<T> GetList();
}

定义基本的增删改查,是个泛型接口,这样实现它的类可以接收所有实本类,实现通用的方法。

接下来在Guestbook.Dal 定义一个 DbObject<T>基类,实现IDbObject<T>的增删改查方法,并做具体的实现,像下面这样:

代码

/// <summary>
/// 数据执 行基础泛型类
/// </summary>
/// <typeparam name=”T”></typeparam>
public class DbObject<T>:IDbObject<T> where T:class
{
private ISession _session;
public DbObject()
{
NHibernateHelper nhbHelper
= new NHibernateHelper();
_session
= nhbHelper.GetSession();
}
#region IDbObject<T> 成员

public void Save(T entity)
{
_session.Save(entity);
_session.Flush();
}

public void Delete(T entity)
{
_session.Delete(entity);
_session.Flush();
}

public void Update(T entity)
{
_session.Update(entity);
_session.Flush();
}

public T Load(int sysNo)
{
return _session.Load<T>(sysNo);
}

public IList<T> GetList()
{
return _session.CreateCriteria<T>().AddOrder(NHibernate.Criterion.Order.Asc(SysNo)).List<T>();
}

#endregion

比如 Save(T entity) 方法,实现具体的_session.Save(entity);_session.Flush();方法。通过NHibernate操作数据库。接下来就 可以具体的持久业务类继承这个操作基类了。下面以Guestbook 为原型做相关讲解。为了数据层解藕,先建接口IGuestbookDal如下:

代码

/// <summary>
/// 留言本 数据操作接口
/// </summary>
public interface IGuestbookDal
{
void Save(GuestbookInfo entity);
void Delete(GuestbookInfo entity);
void Update(GuestbookInfo entity);
GuestbookInfo Load(
int sysNo);
IList
<GuestbookInfo> GetList();
}

然后在Guestbook.Dal中建一个具体持久类,这个类继承DbObject<GuestbookInfo>基类并实现 IGuestbookDal接口,代码如下:

/// <summary>
/// 留言本 数据处理类
/// </summary>
public class GuestbookDal:DbObject<GuestbookInfo>,IGuestbookDal
{

}

具体操作已经在泛型基类DbObject中实现了,所以这个类不用再实现什么操作即可。再加比如UserDal;ProductDal都可以直接 继承不用实现就可以了。大大减少了很多工作量(之前园子里有觉得应该取消泛型,这么好的东西给我留着吧。阿们)。这样持久层基本就完成了。接下来说说业务 类。

首先,一切为了解藕,一切为了面向接口。主阿,饶恕我吧。先在Guestbook.IBiz中定义个业务接口IGuestbookBiz吧:

代码

/// <summary>
/// 留言本 业务接口
/// </summary>
public interface IGuestbookBiz
{
void Save(GuestbookInfo entity);
void Delete(GuestbookInfo entity);
void Update(GuestbookInfo entity);
GuestbookInfo Load(
int sysNo);
IList
<GuestbookInfo> GetList();
}

这没啥说的了,再说大家都烦了。再紧跟着在Guestbook.Biz中建一个业务类GuestbookBiz 实现 以上接口:

代码

/// <summary>
/// 留言本 业务类
/// </summary>
public class GuestbookBiz:IGuestbookBiz
{
private IGuestbookDal _guestbookDal = UnityHelper.UnityToT<IGuestbookDal>(DalType);

#region IGuestbookBiz 成员
public void Save(GuestbookInfo entity)
{
_guestbookDal.Save(entity);
}

public void Delete(GuestbookInfo entity)
{
_guestbookDal.Delete(entity);
}

public void Update(GuestbookInfo entity)
{
_guestbookDal.Update(entity);
}

public GuestbookInfo Load(int sysNo)
{
return _guestbookDal.Load(sysNo);
}

public IList<GuestbookInfo> GetList()
{
return _guestbookDal.GetList();
}

#endregion
}

注意这句 private IGuestbookDal _guestbookDal = UnityHelper.UnityToT<IGuestbookDal>(“DalType”);,这里是业务层引用持久层,并不是直接 New的,而是通过持久接口IGuestbookDal定义的,通过Unity加载进来的。这样就实现了相当成份的解藕了,不是由使用者去引用并实例被引 用者,这个操作是由Ioc容器来做(这里是Unity)。这里用到了UnityHelper类了,它的写法如下(没有深入学习,只是基本操作):

代码

public static class UnityHelper
{
/// <summary>
/// 通过 Unity实组装对象泛型方法
/// </summary>
/// <typeparam name=”T”></typeparam>
/// <param name=”entity”></param>
/// <returns></returns>
public static T UnityToT<T>(string name)
{
IUnityContainer container
= CreateContainer();
T model
= container.Resolve<T>(name);
return model;
}
/// <summary>
/// 通过 Unity实组装对象泛型方法
/// </summary>
/// <typeparam name=”T”></typeparam>
/// <param name=”entity”></param>
/// <returns></returns>
public static T UnityToT<T>()
{
IUnityContainer container
= CreateContainer();
T model
= container.Resolve<T>();
return model;
}
/// <summary>
/// 通过配 置创建UnityContainer
/// </summary>
/// <returns></returns>
public static IUnityContainer CreateContainer()
{
IUnityContainer container
= new UnityContainer();
UnityConfigurationSection section
= (UnityConfigurationSection)
System.Configuration.ConfigurationManager.GetSection(
unity);
section.Containers[
Guestbook].Configure(container);
return container;
}
}

CreateContainer就是创建UnityContainer,它是Unity的核心所在。通过它就可以进行动态组装了。这里可以用代码创 建也可以通过配置文件。我选择配置文件。因为直接写代码里面侵入太强了,失去了很多灵活装配的意义。配置我直接写在了Web.config里面,也可以单 独写配置文件。我们在后面讲一下配置文件。UnityToT(string name)是我写的一个泛型方法,通过name查找相应的配置项去组装并反回接口的对象,T是我们的接口。使用就如上面:private IGuestbookDal _guestbookDal = UnityHelper.UnityToT<IGuestbookDal> (“DalType”);,<IGuestbookDal>就是接口,我们在配置里面有指定。”DalType”就是配置的名称。下面我们看 一下相关的配置项:

代码

<unity>
<containers>
<container name=”Guestbook”>
<types>
<type name=”BizType” type=”Guestbook.IBiz.IGuestbookBiz,Guestbook.IBiz” mapTo=”Guestbook.Biz.GuestbookBiz,Guestbook.Biz”/>
<type name=”DalType” type=”Guestbook.IDal.IGuestbookDal,Guestbook.IDal” mapTo=”Guestbook.Dal.GuestbookDal,Guestbook.dal”/>
</types>
</container>
</containers>
</unity>

type节就是我们的对应配置项,name是我们前面泛型方法要传入的name,type为接口,mapTo为具体的业务类。比如上面的 IGuestbookDal持久层接口对应的相应的GuestbookDal持久类,这样配置后Unity就会帮我们根据接口装配(实例化)实现类,并反 回相应的实例对象,我们就可以通过这个对象实现具体业务了,比如:_dao.Save(entity);。

这样我们的业务层也完成了,接下来就是UI层调用业务层就可以了。UI层我们一样通过Unity进行装配,UI层只引用实体类 Guestbook.Model和Guestbook.IBiz业务层接口(当然用Unity要引用相应的UnityHelper类了)。这样UI层对业 务层向下层次全部是弱依赖。UI我们基于的ASP.NET Mvc,所以我们在Controllers的里面进行业务层的装配并使用。我们以GuestbookInfo的列表显示为例,说一下。相应的Action 叫说GuestbookList,代码如下:

代码

private static IGuestbookBiz _biz = UnityHelper.UnityToT<IGuestbookBiz>(“BizType”);
public ActionResult GuestbookList()
{
IList
<GuestbookInfo> guestbookList = _biz.GetList();
return View(guestbookList);
}

private static IGuestbookBiz _biz = UnityHelper.UnityToT<IGuestbookBiz>(“BizType”);就是业务层装配了,我们通过业务接口 IGuestbookBiz进行引用。通过_biz.GetList()就取得了相应的IList<GuestbookInfo>了。最后在 相对应的View里面,指定Page Model ,像这样:Inherits=”System.Web.Mvc.ViewPage<IList< Guestbook.Model.GuestbookInfo>>”;然后在View中循环显示一下集合数据就可以了,大概像下面这样:

代码

<%foreach(var item in Model){ %>
<table width=”500″ border=”0″ cellpadding=”0″ cellspacing=”0″>
<tr>
<th>姓名</th>
<th style=”background-color:White”><%=item.GuestName %></th>
<th>性别</th>
<th style=”background-color:White”><%=item.Sex==1?: %></th>
</tr>
<tr>
<td colspan=”4″ height=”50″ valign=”top”>
<%=item.GuestMessage %>
</td>
</tr>
<tr>
<td colspan=”4″><%=Html.ActionLink(删除,Delete,new{sysno=item.SysNo}) %></td>
</tr>
</table>
<%} %>

最后放一张运行的图片,其它的Save,Delete方式其本相同,这里就不多讲了。大家可以在这里下载源码(没找到地上传)。

[转载]InfoQ: ASP.NET MVC的四种视图引擎

mikel阅读(944)

[转载]InfoQ: ASP.NET MVC的四种视图引擎.

继上周介绍了Razor之后,ASP.NET MVC 现在已有四种主要的视图引擎。其他三种引擎是Spark、NHaml和传统的ASPX文件模板。本文将大致介绍这四种引擎,并着重讨论新的Razor引 擎。

ASPX风格的视图引擎可以追溯到遥远的ASP。使 用<%= %>和<%: %>语法的占位符在这类风格中占据了统治地位。随着时间的推移,ASPC控件被加入进来,之后是母版页(Master Page),但这同时也带来 了昂贵的页面生命周期。

Spark,在Castle项目的MonoRail中也使用到,其采取 了稍微不同的做法。它既支持占位符,也可以用特殊的属性和标签不受限制地把HTML和代码混合在一起。它或许有些繁琐,但却拥有完全兼容 XML的优势。

NHamlHaml标记语言的.NET实现。这种语言根本不使用 XML式的语法。借助于一种速记语法,它免去了前一种风格(xml)中大量的语法噪音,比如结束标签等。

最新的视图引擎是微软的Razor。 虽然所有的模板系统都具有一些共同特征,但 Razor却和我们前面讨论的三种视图引擎截然不同。不同于NHaml,Razor仍然使用XML标记;但又不同于Spark,Razor在使用XML代 码方面没有走得那么极端。它也不完全类似于ASPX,因为它把那些比较笨重的占位符替换成@符号接表达式或者普通的控制块。因为不需要特殊的结束标记,所 以Razor最终的代码很简练。

默认情况下,从@表达式生成的所有文本都是HTML编 码过的【译注:从而防止XSS攻击】。@块里面的文本可以包含多个“HTML内容块”。当识别出任意的XML标签,Razor就会切换回HTML模式,与 传统ASP开发人员使用“%> html代码 <%=”的技巧非常相似。如果你实际不希望XML标签切换回HTML模式,你可以使用< text>作为一个占位符。

因为Razor使用了现有的VB或C#语法,微软预计它将很容易学习。任何文本编辑器都可以用来编辑Razor文件,而Visual Studio 2010也将更新加入对Razor文件智能提示的完整支持。

Razor的另一个重要特点是它与单元测试框架的兼容性。Razor模板不需要Controller或Web服务器作为宿主(host),所以用它 写出来的视图应该是充分可测的。对于ASPX,虽然理论上一 切皆可测试,但实际上却是相当困难;而其他两个引擎在各自的网站上面甚至都没有真正提到可测试性。

四个视图引擎都支持母版页的概念,所以在这方面没有太 多可谈的内容。对于把视图预编译进assembly文件,ASPX只提供了部分支持,而Razor和Spark都是完整地支持。NHaml目前把这项还是 放在需求特性的列表上面。特别有趣的是,Razor和Spark预编译出的视图可以用在无宿主的场景下,比如邮件合并引擎。
查看英文原文Four View Engines for ASP.NET MVC