[转载]Jquery+JSON消费REST WCF4.0 服务(带源码)

mikel阅读(1078)

[转载]Jquery+JSON消费REST WCF4.0 服务(带源码) – tyb1222 – 博客园.

作为一种以HTTP协议为基础的WCF 服务,只要客户端能模拟进行HTTP请求,都能成为服务的消费者。之前写过《对Jquery+JSON+WebService的一点认识》,觉得在REST是基于HTTP协议的,AJAX的操作也应该一样。但是事实上还是有些差别的。由于网上资源聊聊无几,因此记录下自己的个人体会。希望对你有些帮助!
本篇主要讲述的类容为在ASP.NET中,如何通过AJAX来消费REST服务。
使用JQuery框架模拟AJAX请求时,操作类型主要有GET、POST两种。本节也以这两种常用的方式来进行介绍。(type (String) : (默认: “GET”) 请求方式 (“POST” 或 “GET”), 默认为 “GET”。注意:其它 HTTP 请求方法,如 PUT 和 DELETE 也可以使用,但仅部分浏览器支持。摘自:JQuery 1.4 API手册)。

  • 本篇主要涉及的操作如下:
  • 1、GET请求
  • 2、POST请求,简单数据类型
  • 3、POST请求,复杂数据类型

Jq+JSON消费REST WCF4.0 服务时,对返回给客户端数据格式,以及客户端传递给服务端数据格式是通过ResponseFormat、RequestFormat 两个枚举类型的指定的。如下代码所示。

服务端实现代码:

01 public class AjaxService
02 {
03 [WebGet(UriTemplate = "/{id}"
04 ,ResponseFormat =WebMessageFormat.Json
05 , RequestFormat = WebMessageFormat.Json)]
06 public Person GetPerson(string id)
07 {
08 return new Person
09 {
10 Id = int.Parse(id),
11 Age = 27,
12 Name = "zhansan",
13 Phone = "01082667896"
14 };
15 }
16
17 [WebInvoke(UriTemplate = "/Post"
18 , BodyStyle = WebMessageBodyStyle.WrappedRequest
19 , ResponseFormat = WebMessageFormat.Json
20 , RequestFormat = WebMessageFormat.Json)]
21 public string UpdatePerson(Person person)
22 {
23 return person.Id + person.Name + person.Age + person.Phone;
24 }
25
26 [WebInvoke(UriTemplate = "/Rest/Post"
27 , BodyStyle = WebMessageBodyStyle.WrappedRequest
28 , ResponseFormat = WebMessageFormat.Json
29 , RequestFormat = WebMessageFormat.Json)]
30 public string Update(string message)
31 {
32 return string.Concat("hello", message);
33 }
34 }

客户端实现代码
1、GET请求。

1 $.ajax({
2 type: "get",
3 url: "AjaxService/36",
4 contentType: "application/json; charset=utf-8",
5 success: function (json) { alert(json.Name) },
6 error: function (error) {
7 alert("调用出错" + error.responseText);
8 }
9 });

效果如下图:

2、POST请求,简单数据类型。

01 var jsonMsg = { 'message': 'zhangsan' };
02 var message = JSON2.stringify(jsonMsg)
03 $.ajax({
04 type: "POST",
05 url: "AjaxService/Rest/Post",
06 contentType: "application/json",
07 data: message,
08 dataType: "text",
09 processData: false,
10 success: function (json) { alert(json) },
11 error: function (error) {
12 alert("调用出错" + error.responseText);
13 }
14 });

运行结果如下图:

3、POST请求,复杂数据类型
POST复杂数据类型与简单类型原理是一样的。在Web页面建构JSON数据对象,然后将其转换为JSON的字符串格式。
代码如下:

01 var jsonData = { 'person': { 'Id': '36', 'Name': 'zhangsan', 'Age': '27', 'Phone': '01082667896'} };
02 var message = JSON2.stringify(jsonData)
03 $.ajax({
04 type: "POST",
05 url: "AjaxService/Post",
06 contentType: "application/json; charset=utf-8",
07 data: message,
08 dataType: "json",
09 success: function (json) { alert(json) },
10 error: function (error) {
11 alert("调用出错" + error.responseText);
12 }
13 });

运行结果如下图:

如同在WebService中一样:客户端上传的JSON字符串格式的数据,会在服务端复杂数据类型中的相应字段中。
这样就通过JQ+JSON完成了与REST WCF的交互。但是有一点需要注意的是:在使用POST操作时,在客户端与服务端交互过程中,需要指定WebMessageBodyStyle、在GET操作时,不论格式,可以不必指定。用途是:指定是否包装参数和返回值。也就是在客户端与服务端的交互过程中,上传给服务端的参数以及服务端回传给客户端的返回值需要做怎样的包装操作。这一点非常重要,否则调用在消费服务是会有异常。
WebMessageBodyStyle的定义如下:

1 public enum WebMessageBodyStyle
2 {
3 Bare,
4 Wrapped,
5 WrappedRequest,
6 WrappedResponse
7 }

MSDN给出的说明如下:

  • Bare 不包装请求和响应。
  • Wrapped 包装请求和响应。
  • WrappedRequest 包装请求,但不包装响应。
  • WrappedResponse 包装响应,但不包装请求。

与WebService调用异同总结:

  • 1、调用方式一样。
  • 2、客户端发送给服务端数据格式略有差别。在WebService中可以通过形如:data: "{'name':'zhangsan'}",向服务端发送请求,但是这种字符串格式中RESTful中是不被支持的。
  • 3、WebService调用结果通过.d获取,即json.d。而在RESTful Service中,直接获取,即json。
  • 4、WebService不用指定客户端请求、服务端相应的格式。而在RESTful Service中需要指定

这个过程也不复杂,有此类开发经验的人很容易。但是对初次接触REST开发的人来说还是需要费一番周折的。

参考:

http://www.west-wind.com/weblog/posts/2008/Apr/21/jQuery-AJAX-calls-to-a-WCF-REST-Service

jQuery1.4 API手册

MSDN

[转载]原型开发、模型构建和设计反馈在线工具

mikel阅读(887)

[转载]原型开发、模型构建和设计反馈在线工具 – 孟晨 – 博客园.

Lumzy
你在创建新的UI技术任何时候,在创建网站之前,你会需要创造出一个作为概念根据的原型或模型。当然,你也要测试这些新构想。
Lumzy是一个方便的UI界面模型构建和原型开发的小型在线工具。它能让你创建具有工作功能的原型,而不只是线框:

Mockingbird
另一个界面模型构建和原型开发工具,同时拥有在线团体合作开发工具:

UI Design Framework for Illustrator
一个为AI服务的用户界面元素和风格设置网站

Unique Mobile UI Design Elements
自由设置UI设计元素:

Android UI Elements Set
自由设置Android OS的UI元素:

OSX Leopard GUI Set
OSX Leopard的GUI元素:

ALL In One Web Elements Kit
提供你的网站的所需的一切PSD分层文件:

iPad GUI Set
提供你所需的任何iPad应用程序的主题的分层矢量PSD文件:

The Pencil Project
火狐的GUI原型构建插件:

Concept Feedback
发布你的设计和概念,并得到免费反馈的设计社区:

Landing Page Optimization
获得他人关于你目标页面5秒钟的真实印象反馈的网站:

[转载]微软ASP.NET站点部署指南(5):部署到IIS上作为测试环境

mikel阅读(1033)

[转载]微软ASP.NET站点部署指南(5):部署到IIS上作为测试环境 – 汤姆大叔 – 博客园.

1.  综述

开发程序的时候,通常我们是在Visual Studio 里测试,默认使用的是Visual Studio Development Server(Cassini),使用这个可以让我们开发测试工作更容易,但是在IIS上可能不一定能够正常工作。所以,结果可能是在Visual Studio 里运行正常,但是一旦部署到IIS上就会出错。

你可以通过下面一些方法来测试确保你的程序没问题:

  1. 开发的时候,使用IIS Express或者正式版IIS代替默认的Visual Studio Development Server来测试程序,这样可以更能确保在IIS下少出问题。但是这个方法不能测试你的部署流程是否正确,或者验证部署结构。
  2. 部署程序到你的开发机上的IIS,然后用同样的步骤部署到生产环境,这样验证你的部署流程和是否能在生产环境运行成功。
  3. 部署到和生产环境接近的测试环境,由于生产环境是第三方的提供商,所以最理想的测试环境就是提供商开放第二个账户(仅用于测试目的),这样就可以和正式的生产环境使用一样的部署步骤了。

本章节演示的是第二种方式,第三种方式可以在第七章尾部讲到,另外本章节的底部有第一种方式需要用的资源连接地址。

提醒:如果根据本章节所做的操作出现错误信息或一些功能不正常的话,请务必check Troubleshooting页面

2.  配置程序运行在Medium Trust上

安装IIS和部署之前,我们需要修改Web.config文件以便配置更能接近共享主机环境。主机提供商通常会让你的程序运行在medium trust级别上,那就是说有些事情是不允许做的,比如你不能访问注册表或者你程序之外的目录读写文件。本机默认情况下是运行在high trust上,也就是有些你可以做的事情在生产环境上可能做不到了。因此,为了确保部署到生产环境没问题,需要将测试环境的运行配置也改成medium trust

Web.config文件里,在system.web元素节点里添加<trust>元素,像下面一样:

<configuration>
  <!-- Settings -->
  <system.web>
    <trust level="Medium"/>
    <!-- Settings -->
  </system.web>
</configuration>

现在程序可以运行在medium trust上了,这样你可以尽早发现需要high trust才能运行的错误了。

3.  安装IIS和Web Deploy

你必须先安装IIS和Web Deploy 才能将程序部署到你开发机的IIS上。因为默认Windows 7是不安装这些组件的,如果你已经都安装了,那请忽略这个section。

强烈推荐使用Web Platform Installer安装IIS和Web Deploy,,因为会自动安装IIS的推荐配置和自动安装IIS和Web Deploy所需要的依赖软件。

使用Web Platform Installer安装IIS和Web Deploy,请使用下面的连接,如果你曾经安装过其中的一种或者是相关的依赖软件,那Web Platform Installer只会安装剩余的部分。

4.  设置默认的应用程序池为.Net4

安装IIS以后,运气IIS管理器(开始->运行,输入inetmgr,回车),确保默认程序池使用的.NET Framework版本是4。

连接Connections)面板,展开server节点选择应用程序池Application Pools),在右边的面板里,查看DefaultAppPool使用的.NET framework版本是否是v4.0,如果是,请忽略此section。

如果你只能看到2个应用程序池,并且都是.NET Framework 2.0的话,你需要在IIS里安装ASP.NET 4,然后再配置IIS才能使用。

打开一个command prompt窗口,右键选择以管理员身份运行(Run as Administrator),然后运行aspnet_regiis.exe来安装ASP.NET 4到IIS里。使用如下命令:

cd %windir%\Microsoft.NET\Framework\v4.0.30319
aspnet_regiis.exe –iru

上面的命名将会为.NET Framework 4创建2个应用程序池,但默认版本还是v2.0的。因为需要将程序部署到.NET 4的应用程序池上,所以需要修改它们的版本为NET 4。

重新运行IIS管理器,点击应用程序池,重新查看右边的面板,点击DefaultAppPool,然后在操作面板Actions)里点击基本设置Basic Settings)。

编辑应用程序池Edit Application Pool)对话框里,将.NET Framework version里的项修改成.NET Framework v4.0.30319,然后点击确定OK)。

现在就可以将程序发布到IIS上了。

5.  发布到IIS

使用Visual Studio 2010和Web Deploy部署有几种方式:

  • 使用Visual Studio one-click发布
  • 创建部署包,然后使用IIS Manager 管理控制台安装,部署包是一个.zip文件,包含了所有需要部署到IIS上的文件和元数据
  • 创建部署包,然后使用命令行安装

前面的章节都提到了这三种方式的Visual Studio自动部署设置方式。本章节用的是第一种。更多使用部署包的信息,可以查看ASP.NET Deployment Content Map

发布之前,确保你的Visual Studio是运行在管理员模式下(开始菜单,右键Visual Studio 2010,选择以管理员身份运行)。

改变当前active的build配置是Test,你可以从工具栏选择(如下图),或者从编译(Build菜单里的配置管理器Configuration Manager)里选择。

Solution Explorer里,右键ContosoUniversity项目,选择发布(Publish),弹出Publish Web对话框。

设置profile名称为”Test”,如果没看到文本框,而是看到下拉菜单就选择new ,然后输入新名称。

Service URL里输入“localhost”

Site/application里输入”Default Web Site/ContosoUniversity”

选择上Mark as IIS application on destination。(有些情况不需要部署到IIS上,例如项目本身就不是个web程序,它仅仅包含了一些图片,XML文件等,这种情况就不用选择了,以便不建立IIS程序。)

点击发布(Publish),如果你收到如下信息框,请重新以管理员身份运行Visual Studio。

如果你关掉Visual Studio,例如以后的章节来重新打开它再发布的时候,请务必选择以管理员身份运行,如果不是管理员身份,发布程序不会提示出错框而是尝试发布,有时候可能会提示一个没有权限的错误信息。

如果是运行在管理员模式下,Output窗口会显示编译和发布成功的信息。

运行IIS管理器,在连接(Connections)面板里,你可以在默认站点(Default Web Site)下看到一个名字为ContosoUniversity的应用程序,如果之前都打开了IIS,你点击刷新(Refresh)。在操作(Actions)面板点击浏览(Browse *:80 (http))来验证是否可以打开你的首页。

不出错的话,浏览器就会显示Contoso University项目的首页了。

6.  在测试环境中测试

打开浏览器访问http://localhost/ContosoUniversity,重新运行首页,可以看到页面顶部显示的标示符是”(Test)”而不是”(Dev)”了,这就意味着Web.config的transformation结果是正确的。

打开Students页面验证部署的数据库里布包含任何students:

打开Instructors页面验证这些数据依然存在于数据库中:

Students菜单里选择Add Students,添加一个student,然后可以看到Students 页面显示了一个student,说明已经成功保存到数据库里了:

Courses菜单,选择Update Credits,因为该页面需要administrator权限,所以跳转到了Log In页,输入administrator账户信息(”admin” 和 “Pas$w0rd”)登录以后, Update Credits就显示了,这就验证了上个章节创建的administrator账户已经正确的部署到测试环境了。

检查Elmah文件夹是否存在并且值包含一个placeholder文件,这就验证了前面章节设置的忽略部署该文件夹的XML文件执行成功了。

打开C:\inetpub\wwwroot\ContosoUniversity 目录下的Web.config文件验证Code First数据库初始化参数值为Disabled:

现在,你成功将程序部署到你开发机的IIS上并且测试了,这验证了部署流程不仅仅只是copy程序内容(也可以排除不需要部署的内容了),另外Web Deploy也成功配置了IIS站点。下一章节你将测试另外一个还没搞定的部署任务:设置Elmah文件夹的写权限。

7.  更多信息

关于在Visual Studio 里运行IIS或IIS Express的更多信息,请查看下面列出的资源:

该帖提供了很多例子解释为什么使用Visual Studio Development Server (Cassini)测试不如使用IIS Express测试可靠,以及为什么在IIS Express里测试没有在IIS正式版里测试可靠的原因.

关于Visual Studio 2010里的自动化部署工具以及关于one-click发布和部署包更多的信息,请访问:ASP.NET Web Application Project Deployment Overview

关于主机提供商将程序运行在medium trust有可能引起的问题,请访问:Hosting ASP.NET Applications in Medium Trust

[转载]SQLServer行转列问题-pivot使用详解

mikel阅读(942)

[转载]老掉牙的行转列问题-pivot使用详解 – 屠龙解牛 – 博客园.

一背景设定

行转列的典型应用场景,比如报表,交叉表。还有一个就是:面试。。。

行转列是对单行值的拆分,拆分的途径比如利用聚合函数。拆分之后变成多列。

借用网上通用的样例,对,就是小王小明四门功课。有印象了吧。

data

CREATE  TABLE [StudentScores]
(
    [UserName]         NVARCHAR(20),        --学生姓名
    [Subject]          NVARCHAR(30),        --科目
    [Score]            FLOAT,               --成绩
)

INSERT INTO [StudentScores] SELECT 'Nick', '语文', 80

INSERT INTO [StudentScores] SELECT 'Nick', '数学', 90

INSERT INTO [StudentScores] SELECT 'Nick', '英语', 70

INSERT INTO [StudentScores] SELECT 'Nick', '生物', 85

INSERT INTO [StudentScores] SELECT 'Kent', '语文', 80

INSERT INTO [StudentScores] SELECT 'Kent', '数学', 90

INSERT INTO [StudentScores] SELECT 'Kent', '英语', 70

INSERT INTO [StudentScores] SELECT 'Kent', '生物', 85

SQLServer2005出现之前,一般的做法是用case when.

如下所示

SELECT 
      UserName, 
      MAX(CASE Subject WHEN '语文' THEN Score ELSE 0 END) AS '语文',
      MAX(CASE Subject WHEN '数学' THEN Score ELSE 0 END) AS '数学',
      MAX(CASE Subject WHEN '英语' THEN Score ELSE 0 END) AS '英语',
      MAX(CASE Subject WHEN '生物' THEN Score ELSE 0 END) AS '生物'
FROM dbo.[StudentScores]
GROUP BY UserName

——————-以上可忽略不看——————-

二 PIVOT:how?

SQL2005推出了新的函数PIVOT.

pivot这个单词本身是旋转的意思,行转列本质上也一样,从魔方的这个面到另一个。

使用pivot做好 5 steps.

1从返回的字段名开始

2接下来跟上 子查询

3指定聚合列

4for指定要转化的行值

5对整个查询别名

SELECT username,语文,数学,英语,生物

--step1
FROM
(
 SELECT UserName,[Subject],Score FROM StudentScores
 
 ) AS  a 

--step2
PIVOT
(
 MAX(score)

--step3
 FOR [Subject] IN ([语文],[英语],[生物],[数学])

--step4
) AS b
ORDER BY UserName

--step5

ps:几点细节:step1中字符串不能加引号;step4中in后的列表只能加中括号,不能加引号;1和4的引用数目要一致,但和4的顺序无关

[转载]"返回"按钮的解决方案摸索

mikel阅读(1056)

[转载]”返回”按钮的解决方案摸索 – xxfss2 – 博客园.

做过网站或WEB系统的,肯定都曾在自己的页面中用过“返回”按钮。我也不例外,在多次的开发中,我曾经思索:这个小小的“返回”按钮,应该以怎样的代码实现比较好。

先说说自己最常使用的,也是最常见最无脑的。如:

1         protected void Back()
2         {
3             Response.Redirect("CurrList.aspx");
4         }

有时候,当返回的页面的是一个带分页的页面时,则需要在进入页面时传入分页信息,然后在返回时取出这些值。比如:

1     private void Goback()
2     {
3         string size = Request.QueryString["size"];
4         string index = Request.QueryString["index"];
5            Response.Redirect("SellInfoDisplay.aspx?size=" + size + "&index=" + index );
6     }

用的最多的,无非以上了。

有的时候,再复杂一些,比如一个页面可以从不同的页面跳入,那么,还得再记录哪个页面来的,返回的时候,再判断判断。

再有的时候,A页面跳到B页面,B页面再跳到C页面,这个时候想要连着两次返回到A页面,要写的代码就多了。

那么,这个小小的“返回”按钮有没有什么好的方法去处理呢?

首先我尝试了这样的方法:

1 history.go(-1);

曾经在某些页面中用过这样的方法,似乎也没什么问题。但这个方法是有使用范围限制的,通常它适合用在静态页面。另外,当跳转之前页面执行了某个脚本,而这个脚本中alert了一下,此时用这个方法跳转回来的时候,我发现它又alert了一下,这显然不行。

接着我又尝试了这样的方法:

 1     protected void SaveCurrURL()
 2     {
 3         Session["prevURL"] = Request.UrlReferrer.PathAndQuery;
 4     }
 5 
 6     protected string  GetCurrURL()
 7     {
 8         return Session["prevURL"].ToString();
 9     }
10 
11     protected void Back()
12     {
13         Response.Redirect(this.GetCurrURL());
14     }

前两个方法写在自定义的页面基类中,并且我约定了系统中总是将分页,查询,排序等参数信息保存在URL中。接着我制作了对应的分页控件,正当我沾沾自喜,以为大功告成的时候,又一个问题出现了。

Request .UrlReferrer .PathAndQuery  这句代码似乎会有失灵的时候。

经过几次尝试,发现问题是这样的:

假设从A页面跳转至B页面,那么A页面的方式如果是以脚本的方式进行跳转的话,那么在B页面调用SaveCurrURL方法是获取不到预期的值的,比如(location.href=。。。。),而在A页面以超链接的方式进行跳转的话,则可以顺利获取到。

这是何故?又怎麽办呢?我们知道,用户点击超链接属于用户主动行为,而脚本触发,则属于被动行为,有时候某些被动行为会因为安全方面的考虑而受到重重阻碍。我们可以以脚本的方式触发超链接元素的onclick事件,确很难模拟用户直接点击超链接的效果(我认为是不能)。

后来我决定退一步,牺牲一下性能,将代码改成Session[“prevURL”] = Request.Url.PathAndQuery;

并且为了支持两级的返回,最后的代码是这样的

 1     protected void SaveCurrURL(bool first)
 2     {
 3         if (Session["prevURL"] == null)
 4             Session["prevURL"] = new string[3];
 5         string[] urls = (string[])Session["prevURL"];
 6         if (first)
 7         {
 8             urls[0] = Request.Url.PathAndQuery;
 9             urls[1] = null;
10             urls[2] = null;
11         }
12         else
13         {
14             if (urls[1] == null)
15                 urls[1] = Request.Url.PathAndQuery;
16             else
17                 urls[2] = Request.Url.PathAndQuery;
18         }
19         Session["prevURL"] = urls;
20     }
21     ///<summary>
22 /// 获取上次保存的URL
23 ///</summary>
24 ///<returns></returns>
25     protected string  GetCurrURL()
26     {
27         string[] urls = (string[])Session["prevURL"];
28         for (int i = 2; i >= 0; i--)
29         {
30             if (urls[i] != null)
31             {
32                 string url = urls[i-1];
33                 urls[i] = null;
34                 urls[i - 1] = null;
35                 Session["prevURL"] = urls;
36                 return url;
37             }
38         }
39         throw new Exception("");
40     }

最终的代码费了我不少心思,为了使session保持小巧,我用了string数组,而不是string list,为了支持两级返回,我将数组的长度设为3,这是有原因的。

它们是这样的使用方式,假设有A\B\C 3个页面,

A可以跳到B,B可以跳到C,C可以返回B,B可以返回A。

那么在A页面,这是一个起点页面,调用SaveCurrURL传入TRUE参数,B和C页面的参数为FALSE,注意C页面也要调用,这属于一个瑕疵。

在B和C的返回按钮中,不论他们是不是从A跳过来的,也不论他们处与第2个页面还是第3个页面,统统调用

Response.Redirect(this.GetCurrURL ());

最后,别忘了在if (!IsPostBack)中调用Save函数.

以上便是我对“返回”功能的小小尝试,只能说支持一定的使用范围,有一定的简化作用和通用的处理方式。当然它没有经过严格的测试,也希望大牛们能提供更好的方案。

[转载]ASP.NET MVC3 20个秘方-(5)发送欢迎邮件

mikel阅读(1036)

[转载]【译】MVC3 20个秘方-(5)发送欢迎邮件 – 技术弟弟 – 博客园.

场景
很多网站要求人们先注册再去访问内容或者发表评论.网站如牛毛,怎么可能让人们记住每个他们注册过的网站。在注册的过程中,可以发送一个电子邮件来提醒用户他们刚刚注册了,这样,他们可能一会还会返回到你的网站。

解决方案

在用户注册之后使用SmtpClient和MailMessage发送邮件通知。

讨论

发送一个邮件之前,你需要配置一个SMTP服务器,端口,用户名和密码。为了使配置简单化,我建议你在web.config的appsetting中配置。

<appSettings>

<add key="webpages:Version" value="1.0.0.0"/>

<add key="ClientValidationEnabled" value="true"/>

<add key="UnobtrusiveJavaScriptEnabled" value="true"/>

<add key="smtpServer" value="localhost"/>

<add key="smtpPort" value="25"/>

<add key="smtpUser" value=""/>

<add key="smtpPass" value=""/>

<add key="adminEmail" value="no-reply@no-reply.com"/>

</appSettings>

必要时可以去更新这些value 去反射你的SMTP server,port,username 和password

提示:你也可以使用Visual studio的ASP.NET配置工具去配置。

选择应用程序-> 配置 SMTP 电子邮件设置

为了便于组织项目的结构,我们需要创建一个新的文件夹和新的类去包含必要的发送邮件函数。

右击项目,添加->新建文件夹并且命名问Uitls。右击新建一个类命名为MailClient.cs.

MailClient类及其函数将被定义成static便于使用。日后他被整合到新的功能里时,也不需要为它创建新的实例。下边是一个完整的MailClient 类:

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Web;

namespace MvcApplication.Utils
{

    public static class MailClient
    {
        private static readonly SmtpClient Client;
        static MailClient()
        {
            Client = new SmtpClient
            {
                Host =
                ConfigurationManager.AppSettings["SmtpServer"],
                Port =
                Convert.ToInt32(
                ConfigurationManager.AppSettings["SmtpPort"]),
                DeliveryMethod = SmtpDeliveryMethod.Network
            };
            Client.UseDefaultCredentials = false;
            Client.Credentials = new NetworkCredential(
            ConfigurationManager.AppSettings["SmtpUser"],
            ConfigurationManager.AppSettings["SmtpPass"]);
        }
        private static bool SendMessage(string from, string to,
        string subject, string body)
        {
            MailMessage mm = null;
            bool isSent = false;
            try
            {
                // Create our message
                mm = new MailMessage(from, to, subject, body);
                mm.DeliveryNotificationOptions =
                DeliveryNotificationOptions.OnFailure;
                // Send it
                Client.Send(mm);
                isSent = true;
            }
            // Catch any errors, these should be logged and
            // dealt with later
            catch (Exception ex)
            {
                // If you wish to log email errors,
                // add it here...
                var exMsg = ex.Message;
            }
            finally
            {
                mm.Dispose();
            }
            return isSent;
        }
        public static bool SendWelcome(string email)
        {
            string body = "Put welcome email content here...";
            return SendMessage(
            ConfigurationManager.AppSettings["adminEmail"],
            email, "Welcome message", body);
        }
    }
}

一开始,通过webconfig的配置创建一个新的SmtpClient 实例。然后创建一个SendMessage的函数。这个函数是私有的,不应该直接调用这个函数。这个函数在实际执行发送的时候调用。它创建了一个新的 MailMessage对象,并通过前边歘构建的SmtpClient对象发送它。最后SendWelcome函数是创建接受电子邮件的地址。它生成一个 通用的消息去发送你的电子邮件。它通过SendMessage函数发送。

为了在注册之后发送邮件通知。在Account controller中的register action必须在用户成功创建账户后调用SendWelcome方法。

[HttpPost]
        public ActionResult Register(RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                MembershipCreateStatus createStatus;
                Membership.CreateUser(model.UserName, model.Password, model.Email, null, null, true, null, out createStatus);

                if (createStatus == MembershipCreateStatus.Success)
                {
                    MailClient.SendWelcome(model.Email);
                    FormsAuthentication.SetAuthCookie(model.UserName, false /* createPersistentCookie */);
                    return RedirectToAction("Index", "Home");
                }
                else
                {
                    ModelState.AddModelError("", ErrorCodeToString(createStatus));
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

前边的代码是一个基本的例子。在当今社会,以自动化的形式处理存在的应用程序是一个好主意。

你可以进一步扩展这个例子。在你发送的欢迎邮件中附带一个验证消息。这样可以验证用户电子邮件地址的有效性。让他点击在欢迎邮件的链接。然后他才可能登陆。

另请参阅

SmtpClient and MailMessage

译者注:在.NET 4.0中,微软有提供了一个新的helper “Webmail”。更加方便。

[转载]java pdf 转 swf

mikel阅读(1042)

[转载]java pdf 转 swf – 肖秋峰 – 博客园.

Java Process.exitValue & Process.waitFor()

Process.exitValue() 采用非阻塞的方式返回,如果没有立即拿到返回值,则抛出异常

Process.waitFor() 当前线程等待,如有必要,一直要等到由该 Process 对象表示的进程已经终止。但是如果我们在调用此方法时,如果不注意的话,很容易出现主线程阻塞,Process也挂起的情况。在调用waitFor() 的时候,Process需要向主线程汇报运行状况,所以要注意清空缓存区,即InputStream和ErrorStream,在网上,很多只提到处理 InputStream,忽略了ErrorStream。以下一段代码,贴出来,仅做参考。

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;

/*
* PDF转SWF工具
* @author tangs
*
*/
public class Converter {
    public static int convertPDF2SWF(String sourcePath, String destPath, String fileName) throws IOException {
////目标路径不存在则建立目标路径
        File dest = new File(destPath);
        if (!dest.exists()) dest.mkdirs();
        
        //源文件不存在则返回
        File source = new File(sourcePath);
        if (!source.exists()) return 0;
        
        //调用pdf2swf命令进行转换
//        String command = "D:\\swftools\\pdf2swf.exe" + " -o \"" + destPath  + fileName +"\"  <SPAN style='COLOR: #ff0000'>-s languagedir=D:\\xpdf\\xpdf-chinese-simplified</SPAN> -s flashversion=9 \"" + sourcePath + "\"";
//        String command = "D:\\swftools\\pdf2swf.exe" + " -o \"" + destPath  +  fileName +"\" -s flashversion=9 \"" + sourcePath + "\"";
        String command= "D:/SWFTools/pdf2swf.exe  -t \""+destPath+"\\Java.pdf\" -o  \""+destPath+"\\test.swf\" -s flashversion=9 -s languagedir=D:\\xpdf\\xpdf-chinese-simplified ";  
        System.out.println("cmd:"+command);
//        Process pro = Runtime.getRuntime().exec(command);
        Process process = Runtime.getRuntime().exec(command); // 调用外部程序   
        final InputStream is1 = process.getInputStream();   
        new Thread(new Runnable() {   
            public void run() {   
                BufferedReader br = new BufferedReader(new InputStreamReader(is1));    
                try {
                    while(br.readLine()!= null) ;
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }   
            }   
        }).start(); // 启动单独的线程来清空process.getInputStream()的缓冲区   
        InputStream is2 = process.getErrorStream();   
        BufferedReader br2 = new BufferedReader(new InputStreamReader(is2));    
        StringBuilder buf = new StringBuilder(); // 保存输出结果流   
        String line = null;   
        while((line = br2.readLine()) != null) buf.append(line); // 循环等待ffmpeg进程结束   
        System.out.println("输出结果为:" + buf);
        
//        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(pro.getInputStream()));
        while (br2.readLine() != null); 
        
        try {
            process.waitFor();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        return process.exitValue();

        
    }

    
    public static void main(String []args) throws IOException {
        String sourcePath = "D:\\Java.pdf";
        String destPath = "D:\\";
        String fileName = "Javssa.swf";
        try{
        Converter.convertPDF2SWF(sourcePath, destPath, fileName);
        
        }catch(Exception ex)
        {
            System.out.println("error");
        }
        System.out.println("success");
    
        
        
    }
}

工具准备
swftools.exe 下载
http://www.swftools.org/download.html
安装至D盘
SWFTools提供了一系列将各种文件转成swf的工具:
font2swf.exe
gif2swf.exe
jpeg2swf.exe
pdf2swf.exe
png2swf.exe
wav2swf.exe
这里我们只使用pdf2swf.exe

flexpaper下载
http://code.google.com/p/flexpaper/
这里我们使用已经编译好的FlexPaper的flash版本

[转载]ASP.NET MVC3 20个秘方-(3)验证用户的输入

mikel阅读(949)

[转载]【译】MVC3 20个秘方-(3)验证用户的输入 – 技术弟弟 – 博客园.

场景
你要确保你的表单捕获的数据包含你预期的数据,这些数据是基于你的数据库或模型设计。

解决方案

.NET 4.0 包含了一个新的数据注解命名空间,提供了一些有用的元数据属性类。这些类已经被应用到MVC3。

对于验证表单输入,下面的属性类可以用来提供各种各样
验证选 项:RequiredAttribute,RegularExpressionAttribute,RangeAttribute和 DataTypeAttribute。当需要自定义的验证的时候,MVC的3还支持改进ValidationAttribute类,允许开发人员定义的验 证。

讨论

接下来的例子是要去扩展“code-first book“model,这个model是在前一“秘方”中创建的。

这个model将按照以下条件被更新:

1. 书名是必须的

2. ISBN是合法的

3. 书的摘要是必须的

4. 作者是必须的

5. 合法的价格(美元)

6. 合法的出版日期

以上6个验证中的5个可以由MVC 3 的内置方法完成。然而,第5个验证需要用一种不同的格式化-它需要一个自定义验证方法。

 public class Book
    {
        public int ID { get; set; }
        [Required]
        public string Title { get; set; }
        [Required]
        [IsbnValidation]
        public string Isbn { get; set; }
        [Required]
        public string Summary { get; set; }
        [Required]
        public string Author { get; set; }
        public string Thumbnail { get; set; }
        [Range(1, 100)]
        public double Price { get; set; }
        [DataType(DataType.Date)]
        [Required]
        public DateTime Published { get; set; }
    }
    public class BookDBContext : DbContext
    {
        public DbSet<Book> Books { get; set; }
    }

在上边的例子,[Required]数据注解被附加在每个字段上,表明这个字段是必须由用户提供。在ISBN number上 [IsbnValidation]特性也被添加了,这是通知MVC 3 IsbnValidation 必须调用IsValid操作,这个操作即将被创建.为了验证价格,[Range] 注解被应用。对于价格的验证,我们也可以用正则表达式特性 [RegularExpression] 来完成。

如下:

[RegularExpression (@”(\b[\d\.]*)”)]

public double Price { get; set; }

最后,对于published date(出版日期)的验证,DataType特性告诉MVC这个字段的类型是一个日期类型。

一个合法ISBN的定义是:10-13个字符。为何合理的组织代码,自定义验证类将被放在一个单独的文件夹里。

右键点击项目:添加->新建文件夹。我们为这个文件夹命名为:Validations.在该文件夹点击右键。添加类:IsbnValidationAttribute.cs

代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text.RegularExpressions;

namespace MvcApplication.Validations
{
    [AttributeUsage(AttributeTargets.Field |
 AttributeTargets.Property, AllowMultiple = false,
 Inherited = true)]
    public class IsbnValidationAttribute :
System.ComponentModel.DataAnnotations.ValidationAttribute
    {
        /**
        * This class is courtesy:
        * http://www.java2s.com/Open-Source/CSharp/
        * Inversion-of-Control-Dependency-Injection/Spring.net/
        * Spring/Validation/Validators/ISBNValidator.cs.htm
        *
        * This class is used for demonstration purposes
        * of performing an ISBN validation. Should you
        * wish to use this in your project, please
        * consult the license agreement here:
        * http://www.apache.org/licenses/LICENSE-2.0
        **/
        private static readonly String SEP = "(?:\\-|\\s)";
        private static readonly String GROUP = "(\\d{1,5})";
        private static readonly String PUBLISHER = "(\\d{1,7})";
        private static readonly String TITLE = "(\\d{1,6})";
        static readonly String ISBN10_PATTERN =
        "^(?:(\\d{9}[0-9X])|(?:" + GROUP + SEP + PUBLISHER +
        SEP + TITLE + SEP + "([0-9X])))$";
        static readonly String ISBN13_PATTERN =
        "^(978|979)(?:(\\d{10})|(?:" + SEP + GROUP + SEP +
        PUBLISHER + SEP + TITLE + SEP + "([0-9])))$";
        public IsbnValidationAttribute() :
            base("Invalid ISBN number")
        {
        }
        public override bool IsValid(object value)
        {
            // Convert to string and fix up the ISBN
            string isbn = value.ToString();
            string code = (isbn == null)
            ? null :
            isbn.Trim().Replace("-", "").Replace("", "");
            // check the length
            if ((code == null) || (code.Length < 10
            || code.Length > 13))
            {
                return false;
            }
            // validate/reformat using regular expression
            Match match;
            String pattern;
            if (code.Length == 10)
            {
                pattern = ISBN10_PATTERN;
            }
            else
            {
                pattern = ISBN13_PATTERN;
            }
            match = Regex.Match(code, pattern);
            return match.Success && match.Index == 0 &&
            match.Length == code.Length;
        }
    }
}

创建完这个类记得在 book.cs添加命名空间引用:using MvcApplication.Validations;

上边的例子包含了一个标准的ISBN验证。这个验证是来自CSharp Open Source example。如果ISBN符合2个正则表达式中的一个。验证函数将返回true。否则返回false。需要用户重新输入

如果你在你的浏览器里转到图书创建页面。当你点击提交按钮。验证就被会触发。

另请参阅

DataAnnotations Namespace

译者注

关于用户验证,可以有更多方法,支持客户端/服务器端验证。

由于是翻译,我会尽量和原著保持一致,关于其他的验证方法会在后续的其他系列写出。

[转载]jQuery Mobile 开源框架对 Windows Phone 更好支持

mikel阅读(979)

[转载]jQuery Mobile 开源框架对 Windows Phone 更好支持 – MSDN 中文网站 – 博客园.

本篇博客原文jQuery Mobile Open Source Framework Support for Windows Phone选自Scott Hanselman的博客,由MSDN中文网站进行了汉化。

Web 和移动开发人员,大家好!

正如您可能已经注意到,JQuery Mobile 版本 1.0 已于本周公布。我们很高兴在这一激动人心的时刻再次强调我们对支持流行的开源移动框架的承诺。

在最近的活动中,我想强调的是在支持 PhoneGap 方面所进行的工作,我们增加了 PhoneGap 对 Windows Phone7.5 (Mango) 的支持,并且现在正在进一步改善在 Windows Phone7.5 中对 JQuery Mobile 的支持。

您可能已经知道,jQuery Mobile 框架是基于 JavaScript HTML5,面向移动设备平台的用户界面系统,构建于 JQueryjQuery UI 基础之上。

虽然今天的版本 1 和最近的 RC 版本包含了许多功能,但我们想花一分钟强调我们与 jQuery Mobile 团队开始的协作。在过去几周里,我们将注意力放在支持 Kin Blas 和社区中的其他人,以改善 Windows Phone7.5 的性能。

具体地讲,正如本周早些时候公布的 RC3 博客 指出的那样,如两个示例应用程序所示,Windows Phone 的性能已经有相当显著的改善:

  • 窗体图库的渲染改善了 226%,将它从 5 秒缩短到 2.2 秒
  • 渲染复杂的 400 项列表视图的时间从 60 秒缩短到 3 秒,速度提高了 20 倍

jQuery 团队还在更改日志中记录了更多针对 Windows Phone 的性能优化技巧,这将节省特定场景中的执行时间。

我们因这种进步而深受鼓舞,并将继续与社区合作,为 Windows Phone 带来更高水平的 jQuery 功能和性能的支持 …… 敬请关注,并再次祝贺 jQuery Mobile 团队!

Abu Obeida Bakhach

互操作性战略项目经理

[转载]在 jQuery Repeater 中检索过滤数据

mikel阅读(1040)

[转载]在 jQuery Repeater 中检索过滤数据 – 麦丝平方 – 博客园.

很多时候, 我们都会用到搜索的功能, 这次将向大家介绍 Repeater 如何设置检索数据.

示例代码下载: http://zsharedcode.googlecode.com/files/JQueryElementDemo.rar

本文将详细的讲解如何在 Repeater 中检索数据信息, 目录如下:

* 准备

* 设置 FilterTemplate

* 设置 FilterField 和 FilterFieldDefault

* 调用 setfilter 和 filter 函数

准备

请先查看 30 分钟掌握无刷新 Repeater 或者准备一节的内容.

设置 FilterTemplate

RepeaterFilterTemplate 属性中, 包含用于填写搜索条件的元素, 比如文本框, 日期框等. 此外, 也可以包含搜索按钮:

<je:Repeater ID="productList" runat="server"        ...    >

    <FilterTemplate>
        <tr>
            <td>
                <input type="text" size="10"
                    je-id="productname"
                    je-value="productname"/>
            </td>
            <td>
                <input type="text" size="5"
                    je-id="model"
                    je-value="model"/>
            </td>
            <td>
                <input type="text" size="4"
                    je-id="price1"
                    je-value="price1"/>
                -
                <input type="text" size="4"
                    je-id="price2"
                    je-value="price2"/>
            </td>
            <td>
                <input type="text" size="3"
                    je-id="amount"
                    je-value="amount"/>
            </td>
            <td>
                <input type="text" size="10"
je-datepicker="dateFormat='yy-mm-dd';changeMonth=true;changeYear=true"
                    je-id="manufactureDate1"
                    je-value="manufactureDate1"/>
                -
                <input
je-datepicker="dateFormat='yy-mm-dd';changeMonth=true;changeYear=true"
                    type="text" size="10"
                    je-id="manufactureDate2"
                    je-value="manufactureDate2"/>
            </td>
        </tr>
        <tr je-class="{highlight}">
            <td colspan="5" align="right">
                <span je-button=";" onclick="javascript:clearCondition();">清空</span>
                <span je-button=";" je-onclick="filter">搜索</span>
            </td>
        </tr>
    </FilterTemplate>

</je:Repeater>

代码中, 使用了 input 元素来添加文本框和日期框, 通过 je-id 来与 FilterField 属性中的搜索字段关联, je-value 则是表示使用指定搜索条件来初始化.

上面还使用了 je-datepicker 创建日期框, 至于如何使用 je-<JQueryUI 插件名> 创建更多 JQueryUI 插件, 可以参考 在 jquery repeater 中添加设置日期,下拉,复选框等控件.

通过 je-buttonje-onclick, 创建了用于搜索的按钮, je-onclick 被指定为 filter, 也就是将执行 repeaterfilter 方法, 可以参考 30 分钟掌握无刷新 Repeater 的特殊绑定一节.

设置 FilterField 和 FilterFieldDefault

FilterField 中设置的字段名, 将作为参数传递给服务器端的方法:

<je:Repeater ID="productList" runat="server"
    FilterField="['productname','price1','price2']"
    FilterFieldDefault="['',-1,-1]"
    FillAsync-Url="product.asmx"
    FillAsync-MethodName="GetProductList">

    <FilterTemplate>
        <tr>
            <td>
                <input type="text" size="10"
                    je-id="productname" je-value="productname"/>
            </td>

            <td>
                <input type="text" size="4"
                    je-id="price1" je-value="price1"/>
                -
                <input type="text" size="4"
                    je-id="price2" je-value="price2"/>
            </td>

        </tr>
    </FilterTemplate>

</je:Repeater>

代码中, 通过 FilterField 设置了 3 个用于搜索的字段 productname, price1, price2, 并通过 FilterFieldDefault 来设置这些搜索条件的默认值, 因此服务器端方法 GetProductList 可以采用如下的形式:

public SortedDictionary<string, object> GetProductList (
    int pageindex, int pagesize,
    string productname, float price1, float price2 )
{

        if ( price1 != -1 )
            ...

        if ( price2 != -1 )
            ...

}

如果 price1 和 price2 等于 -1, 则表示用户没有设置关于价格的搜索条件. 至于服务器端返回数据的格式, 请参考 30 分钟掌握无刷新 Repeater 的请求/返回数据的格式一节.

调用 setfilter 和 filter 函数

经过上面简单的设置, 已经可以通过 FilterTemplate 中的搜索按钮来检索数据, 此外, 还可以使用另一个方法:

<input id="myproductname" type="text" size="10"/>

<je:Button ID="cmdSearch" runat="server" Label="搜索 2" Click="
function(){
    productList.__repeater('setfilter', 'productname', $('#myproductname').val());
    productList.__repeater('filter');
}
">
</je:Button>

上面的示例中, id 为 myproductname 的文本框用来输入搜索的产品名称, 而在按钮的 Click 事件中, 调用 repeatersetfilter 方法来将 myproductname 中的值设置到 repeater 的过滤条件中, 调用 filter 方法来检索数据.

JQueryElement 是开源共享的代码, 可以在 http://code.google.com/p/zsharedcode/wiki/Download 页面下载 dll 或者是源代码.

实际过程演示: http://www.tudou.com/programs/view/HJmCQRpGQEg/, 建议全屏观看.

欢 迎访问 panzer 开源项目, http://zsharedcode.googlecode.com/ , 其中包含了 IEBrowser 控制 WebBrowser 执行各种 js 和 jQuery 脚本以及录制功能 和 jQueryUI 的 ASP.NET 控件 jQueryElement.