[转载]5分钟快速建立项目SVN版本控制

mikel阅读(973)

[转载]5分钟快速建立项目版本控制 – Face Code,Brain bloom – 博客园.

无论是个人进行单独编码还是团体开发项目,项目的版本控制都是很重要的。就我所知的版本控制方式有两种。

  1. 最简单的版本控制就是保留软件不同版本的数份copy,并且适当编号。许多大型开发案都是使用这种简单技巧。虽然这种方法能用,但是很没效率。一 是因为保存的数份copy几乎完全一样,也因为这种方法要高度依靠开发者的自我纪律,而常导致错误。
  2. 使用版本控制工具。常用的windows平台下的版本控制工具有svn,cvs,vss。

如果您还没有用过版本控制工具构建项目管理,本文将带你快速入门,本文使用的工具是基于svn的。

  • 必备软件(这些软件目前是比较新的版本)
  1. tortoiseSVN 1.65
  2. Visual SVN Server 2.11(Visual SVN Server是自带Subversion和Apache的)
  3. Visual SVN 1.77, Crack 破解(Visual Studio插件)
  4. SVN 电子书(可选,如果想深入了解SVN,可以一读)

如果以上文件不能下载,请访问http://cid-d61a87db430d0cab.skydrive.live.com/browse.aspx/.Public/svn这 个地址,下载文件都放在这里了。

  • 安装过程

tortoiseSVN和Visual SVN的安装过程我就不赘述了,下面主要讲Visual SVN Server的安装过程。
01 02

下面的步骤就是next和install了。到此,软件环境就准备好了。

  • 如何创建一个使用版本控制的Hello World项目

1.建立SVN服务器版本库(Create Repository)

    • 创建用户

      05
      07
    • 创建版本库

      03 04
    • 分配权限

      08
      09

2.把项目导入到服务器版本库中(Import project to repository)

10 11 12 13 14 15

3. 客户端签出项目(check out the project)

16 17

签出以后,可以看到每个文件前都有绿色的小图标

18
19

[转载]表达式树基础

mikel阅读(1146)

[转载][翻译]表达式树基础 – 甜番薯 – 博客园.

原文来自Charlie CalvertExpression Tree Basics

表达式树基础

刚接触LINQ的人往往觉得表达式树很不容易 理解。通过这篇文章我希望大家看到它其实并不像想象中那么难。您只要有普通的LINQ知识便可以轻松理解本文。
表达式树提供一个将可执行代码转换成数据的方 法。如果你要在执行代码之前修改或转换此代码,那么它是非常有价值的。尤其是当你要将C#代码—-如LINQ查询表达式转换成其他代码在另一个程序 —-如SQL数据库里操作它。
但是我在这里颠倒顺序,在文章最后你很容易发现为什么将代码转换到数据中去很有用。首 先我需要提供一点背景知识。让我们开始看看相关的创建表达式树的简单语法。
表达式树的语法


考虑下面简单的 Lambda表达式:

Func<int, int, int> function = (a,b) => a + b;
这个语句包含三个部分:

  1. 一个声明: Func<int, int, int> function
  2. 一个等号: =
  3. 一个lambda表达式: (a,b) => a + b;


变量 function指向两个数字相加的原生可执行代码。上面三步的lambda表达式表示一个简短的如下的手写方法:

public int function(int a, int b)
{
return a + b;
}


上面的方法或 lambda表达式都可以这样调用:

int c = function(3, 5);


当方法调用后,变量c将 被设成3+5,即8。

上面声明中第一步委托类型Func是在System命名空间中为我们定义好的:

public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);
这个代码看上去很复杂,但它在这里只是用来帮我们定义变量function,变量 function赋值为非常简单的两个数字相加的lambda表达式。即使你不懂委托和泛型,你仍然应该清楚这是一个声明可执行代码变量引用的方法。在这 个例子里它指向一个非常简单的可执行代码。
将代码转换到数据中
在上一节,你看到怎么声明一个指向原生可执行 代码的变量。表达式树不是可执行代码,它是一种数据结构。那么我们怎么从表达式的原生代码转换成表达式树?怎么从代码转换成数据?
LINQ提供一个简单语法用来将代码转换到名 叫表达式树的数据结构。首先添加using语句引入Linq.Expressions命名空间:
using System.Linq.Expressions;


现在我们可以创建一个表 达式树:

Expression<Func<int, int, int>> expression = (a,b) => a + b;
跟上个例子一样的lambda表达式用来转换到类型为 Expression<T>的表达式树。标识expression不是可执行代码;它是一个名叫表达式树的数据结构。
Visual Studio 2008的samples包含一个叫ExpressionTreeVisualizer的程序。它可以用来呈现表达式树。图1你可 以看到一个展示上面简单表达式语句的对话框截图。注意,对话框上面部分显示的是lambda表达式,下面是用TreeView控件显示的其组成部分。

ExpressionTree


图1:
VS2008 C# Samples中的ExpressionTreeVisualizer创建一个表达式树的象征性的输出

编写代码来探索表达式树
我们的例子是一个Expression<TDelegate>。 Expression<TDelegate>类有四个属性:
  • Body: 得到表达式的主体。
  • Parameters: 得到lambda表达式的参数.
  • NodeType: 获取树的节点的ExpressionType。共45种不同值,包含所有表达式节点各种 可能的类型,例如返回常量,例如返回参数,例如取两个值的小值(<),例如取两个值的大值(>),例如将值相加(+),等等。
  • Type: 获取表达式的一个静态类型。在这个例子里,表达式的类型是Func<int, int, int>。
如果我们折叠图1的树节 点,Expression<TDelegate>的四个属性便显示得很清楚:
ExpressionTreeProperties
图2:将树节点折叠起来,你可以很容易的看到 Expression<TDelegate>类的四个主要属性。
你可以使用这四个属性开始探索表达式树。例如,你可以通过这样找到参数的名称:
Console.WriteLine(“参数1: {0}, 参数2: {1}”, expression.Parameters[0], expression.Parameters[1]);
这句代码输出值ab
参数1: a, 参数2: b
这个很容易在图1的ParameterExpression节点找到。
让我们在接下来的代码探索表达式的Body,在这个例子里是(a + b):
BinaryExpression body = (BinaryExpression)expression.Body;
ParameterExpression left = (ParameterExpression)body.Left;
ParameterExpression right = (ParameterExpression)body.Right;
Console.WriteLine(expression.Body);
Console.WriteLine(” 表达式左边部分: “ + “{0}{4} 节点类型: {1}{4} 表达式右边部分: {2}{4} 类型: {3}{4}”, left.Name, body.NodeType, right.Name, body.Type, Environment.NewLine);

这段代码产生如下输入:

(a + b)
表达式左边部 分: a
节点类型:  Add
表达式右边部分: b
类型: System.Int32

同样,你会发现很容易在图1的Body节点中 找到这些信息。

通过探索表达式树,我们可以分析表达式的各个部分发现它的组成。你可以看见,我们的 表达式的所有元素都展示为像节点这样的数据结构。表达式树是代码转换成的数据。
编译一个表达式:将数据转换回代码
如果我们可以将代码转换到数据,那么我们也应该能将数据转换回代码。这里是让编译器 将表达式树转换到可执行代码的简单代码。
int result = expression.Compile()(3, 5);
Console.WriteLine(result);
这段代码会输出值8,跟本文最初声明的lambda函数的执行结果一样。
IQueryable<T>和表达式树
现在至少你有一个抽象的概念理解表达式树,现在是时候回来理解其在LINQ中的关键 作用了,尤其是在LINQ to SQL中。花点时间考虑这个标准的LINQ to SQL查询表达式:
var query = from c in db.Customers
where c.City == “Nantes”
select new { c.City, c.CompanyName };
你可能知道,这里LINQ表达式返回的变量query是IQueryable类型。 这里是IQueryable类型的定义:
public interface IQueryable : IEnumerable
{
Type ElementType { get; }
Expression Expression { get; }
IQueryProvider Provider { get; }
}
你可以看见,IQueryable包含一个类型为Expression的属 性,Expression是Expression<T>的基类。IQueryable的实例被设计成拥有一个相关的表达式树。它是一个等同于 查询表达式中的可执行代码的数据结构。
花点时间考虑图3。你可能需要点击它使图片原尺寸显示。这是本节开始的查询表达式的 表达式树的可视化显示。此图使用ExpressionTreeVisualizer创建,就像我使用它在图1创建基础的 lambda表达式树一样。
LinqToSqlExpressionTree01
图3:此复杂的表达式树由上面的样例LINQ to SQL查询表达式生成。(点击图片看查看大图)

为什么要将LINQ to SQL查询表达式转换成表达式树呢?

你已经学习了表达式树是一个用来表示可执行代 码的数据结构。但到目前为止我们还没有回答一个核心问题,那就是为什么我们要做这样的转换。这个问题是我们在本文开始时提出来的,现在是时候回答了。

一个LINQ to SQL查询不是在你的C#程序里执行的。相反,它被转换成SQL,通过网络发送,最后在数据库服务器上执行。换句话说,下面的代码实际上从来不会在你的程 序里执行:

var query = from c in db.Customers

where c.City == “Nantes”

select new { c.City, c.CompanyName };

它首先被转换成下面的SQL语句然后在服务器 上执行:

SELECT [t0].[City], [t0].[CompanyName]

FROM [dbo].[Customers] AS [t0]
WHERE [t0].[City] = @p0
从查询表达式的代码转换成SQL查询语句 —-它可以通过字符串形式被发送到其他程序。在这里,这个程序恰好是SQL Server数据库。像这样将数据结构转换到SQL显然比直接从原生IL或可执行代码转换到SQL要容易得多。这有些夸大问题的难度,只要试想转换0和1 的序列到SQL!

现在是时候将你的查询表达式转换成SQL了, 描述查询的表达式树是分解并解析了的,就像我们在上一节分解我们的简单的lambda表达式树一样。当然,解析LINQ to SQL表达式树的算法比我们用的那个要复杂得多,但规则是一样的。一旦解析了表达式树的各部分,那么LINQ开始斟酌以最好的方式生成返回被请求的数据的 SQL语句。

表达式树被创建是为了制造一个像将查询表达式 转换成字符串以传递给其他程序并在那里执行这样的转换任务。就是这么简单。没有巨大奥秘,不需要挥舞魔杖。只是简单的:把代码,转换成数据,然后分析数据 发现其组成部分,最后转换成可以传递到其他程序的字符串。

由于查询来自编译器封装的抽象的数据结构,编 译器可以获取任何它想要的信息。它不要求执行查询要在特定的顺序,或用特定的方式。相反,它可以分析表达式树,寻找你要做的是什么,然后再决定怎么去做。至少在理论上,我们可 以自由的考虑各种因素,比如网络状况,数据库负载,结果集是否有效,等等。在实际中LINQ to SQL不考虑所有这些因素,但它理论上可以自由的做几乎所有想做的事。此外,人们可以通过表达式树将自己编写的代码,分析并转换成跟LINQ to SQL提供的完全不同的东西。

IQueryable<T>和 IEnumerable<T>
正如你可能知道的,LINQ to Objects的查询表达式返回IEnumerable<T>而不是IQueryable<T>。为什么LINQ to Objects使用IEnumerable<T>而LINQ to SQL使用IQueryable<T>?
这里是IEnumerable<T>的定义:
public interface IEnumerable<T> : IEnumerable
{
IEnumerator<T> GetEnumerator();
}
正如你看到的,IEnumerable<T>并不包含类型为 Expression的属性。这指出LINQ to Objects和LINQ to SQL的根本区别。后者大量使用了表达式树,但LINQ to Objects很少使用。
为什么表达式树不是LINQ to Objects的标准部分?虽然答案不一定会马上出现,但这是很有意义的一旦你发现这个问题。
考虑这个简单LINQ to Objects查询表达式:
List<int> list = new List<int>() { 1, 2, 3 };
var query = from number in list
where number < 3
select number;
这个LINQ查询返回在我们的list中比3小的数字;就是说,这里返回数字1和 2。显然没有必要将查询转换成字符串来顺序传递给其他程序并获取正确的结果。相反,可以直接转换查询表达式为可执行的.NET代码。这里并不需要将它转换 成字符串或对它执行任何其他复杂操作。
可是这有点理论化,在实际中某些特殊情况下其分隔线可能有些模糊,总体上讲规则相当 简单:
  • 如果代码可以在程序里执行那么可以使用名为 IEnumerable<T>的简单类型完成任务
  • 如果你需要将查询表达式转换成将传递到其他程序的字符串,那么应该使用 IQueryable<T>和表达式树。
LINQ to Amazon这样的项目需要将查询表达式转换成web service调用执行外部程序,通常使用IQueryable<T>和表达式树。LINQ to Amazon将它的查询表达式转换成数据,通过web service传递给另一个甚至不是C#写的程序。将C#代码转换成到某些能传递到web service的东西时,表达式树内在的抽象是非常有用的。要在程序内执行的代码,仍然可以经常使用而抛开表达式树。例如下面的查询使用 IEnumerable<T>,因为它调用到当前程序的.NET反射API:

var query = from method in typeof(System.Linq.Enumerable).GetMethods()

orderby method.Name

group method by method.Name into g

select new { Name = g.Key, Overloads = g.Count() };

概要

本文覆盖了表达式树的一些基本情况。通过将代 码转换成数据,这些数据结构揭示并描绘表达式的组成部分。从最小的概念上讲,理解表达式树是相当简单的。它获取可执行表达式并获取其组成部分放入树形数据 结构。例如,我们检测这个简单的表达式:

(a,b) => a + b;

通过研究来源于这个表达式的树,你能看到创建 树的基本规则,见图1。

你同样可以看到表达式树在LINQ to SQL里扮演非常重要的角色。尤其,他们是LINQ to SQL查询表达式用来获取逻辑的数据抽象。解析并分析此数据得到SQL语句,然后发送到服务器。

LINQ使查询C#语言的一个普通类即有类型 检查也有智能感知。其代码是类型检查和智能感知的,必须使用正确的C#语法,它能直接转换到可执行代码,就像任何其他C#代码一样被转换和执行。表达式树 使将可执行代码转换成能传递到服务器的SQL语句相对容易。

查询返回 IEnumerable<T>优于IQueryable<T>表示不使用表达式树。作为一般性规则,可以这么说:LINQ查询在 程序内执行时不需要表达式树,当代码在程序外执行时可以利用表达式树。
Download the source.

还可看看这篇文章:Using the Expression Tree Visualizer.

[转载]Apache中 RewriteCond 规则参数介绍

mikel阅读(988)

[转载]Apache中 RewriteCond 规则参数介绍 文章分类:服务器设置 52web.com — 为网站开发者加油!.

Apache模块 mod_rewrite 提供了一个基于正则表达式分析器的重写引擎来实时重写URL请求。它支持每个完整规则可以拥有不限数量的子规则以及附加条件规则的灵活而且强大的URL操 作机制。此URL操作可以依赖于各种测试,比如服务器变量、环境变量、HTTP头、时间标记,甚至各种格式的用于匹配URL组成部分的查找数据库。

此模块可以操作URL的所有部分(包括路径信息部分),在服务器级的(httpd.conf)和目录级的(.htaccess)配置都有效,还可以生成最终请求字 符串。此重写操作的结果可以是内部子处理,也可以是外部请求的转向,甚至还可以是内部代理处理。

这里着重介绍一下 RewriteCond 的规则以及参数说明。RewriteCond指令定义了规则生效的条件,即在一个RewriteRule指令之前可以有一个或多个RewriteCond 指令。条件之后的重写规则仅在当前URI与Pattern匹配并且满足此处的条件(TestString能够与CondPattern匹配)时才会起作 用。

【说明 】定义重写发生的条件
【语法】 RewriteCond TestString CondPattern [flags]
【作用域】 server config, virtual host, directory, .htaccess
【覆盖项】 FileInfo
【状态】 扩展(E)
【模块】 mod_rewrite

TestString是一个纯文本的字符串,但是还可以包含下列可扩展的成分:
1、RewriteRule反向引用 ,引用方法是:$N (0 <= N <= 9)引用当前(带有若干RewriteRule指令的)RewriteCond中的与Pattern匹配的分组成分(圆括号!)。
2、RewriteCond反向引用 ,引用方法是:%N (1 <= N <= 9)引用当前若干RewriteCond条件中最后符合的条件中的分组成分(圆括号!)。
3、RewriteMap扩展 ,引用方法是:${mapname:key|default} 细节请参见RewriteMap 指令
4、服务器变量 ,引用方法是:%{NAME_OF_VARIABLE} NAME_OF_VARIABLE可以是下表列出的字符串之一:

HTTP头 连接与请求
HTTP_USER_AGENT
HTTP_REFERER
HTTP_COOKIE
HTTP_FORWARDED
HTTP_HOST
HTTP_PROXY_CONNECTION
HTTP_ACCEPT
REMOTE_ADDR
REMOTE_HOST
REMOTE_PORT
REMOTE_USER
REMOTE_IDENT
REQUEST_METHOD
SCRIPT_FILENAME
PATH_INFO
QUERY_STRING
AUTH_TYPE
服务器自身 日期和时间 其它
DOCUMENT_ROOT
SERVER_ADMIN
SERVER_NAME
SERVER_ADDR
SERVER_PORT
SERVER_PROTOCOL
SERVER_SOFTWARE
TIME_YEAR
TIME_MON
TIME_DAY
TIME_HOUR
TIME_MIN
TIME_SEC
TIME_WDAY
TIME
API_VERSION
THE_REQUEST
REQUEST_URI
REQUEST_FILENAME
IS_SUBREQ
HTTPS

这些变量都对应于类似命名的HTTP MIME头、Apache服务器的C变量、Unix系统中的struct tm字段,其中的大多数在其他的手册或者CGI规范中都有说明。 其中为mod_rewrite所特有的变量如下:

IS_SUBREQ
如果正在处理的请求是一个子请求,它将包含字符串”true”,否则就是”false”。模块为了解析URI中的附加文件,可能会产生子请求。
API_VERSION
这是正在使用中的Apache模块API(服务器和模块之间内部接口)的版本, 其定义位于include/ap_mmn.h中。此模块API版本对应于正在使用的Apache的版本(比如在Apache 1.3.14的发行版中这个值是19990320:10)。 通常,对它感兴趣的是模块的开发者。
THE_REQUEST
这是由浏览器发送的完整的HTTP请求行(比如:”GET /index.html HTTP/1.1″)。它不包含任何浏览器发送的其它头信息。
REQUEST_URI
这是在HTTP请求行中所请求的资源(比如上述例子中的”/index.html”)。
REQUEST_FILENAME
这是与请求相匹配的完整的本地文件系统的文件路径名。
HTTPS
如果连接使用了SSL/TLS,它将包含字符串”on”,否则就是”off”(无论mod_ssl是否已经加载,该变量都可以安全的使用)。

其它注意事项:
1、SCRIPT_FILENAME和REQUEST_FILENAME包含的值是相同的——即Apache服务器内部的request_rec结构中的 filename字段。 第一个就是大家都知道的CGI变量名,而第二个则是REQUEST_URI(request_rec结构中的uri字段)的一个副本。
2、特殊形式:%{ENV:variable} ,其中的variable可以是任意环境变量。它是通过查找Apache内部结构或者(如果没找到的话)由Apache服务器进程通过getenv()得 到的。
3、特殊形式:%{SSL:variable} ,其中的variable可以是一个SSL环境变量的名字,无论mod_ssl模块是否已经加载都可以使用(未加载时为空字符串)。比如:% {SSL:SSL_CIPHER_USEKEYSIZE}将会被替换为128。
4、特殊形式:%{HTTP:header} ,其中的header可以是任意HTTP MIME头的名称。它总是可以通过查找HTTP请求而得到。比如:%{HTTP:Proxy-Connection}将被替换为Proxy- Connection:HTTP头的值。
5、预设形式:%{LA-U:variable} ,variable的最终值在执行一个内部(基于URL的)子请求后确定。 当需要使用一个目前未知但是会在之后的过程中设置的变量的时候,就可以使用这个方法。例如,需要在服务器级配置(httpd.conf文件)中根据 REMOTE_USER变量进行重写, 就必须使用%{LA-U:REMOTE_USER}。因为此变量是由URL重写(mod_rewrite)步骤之后的认证步骤设置的。 但是另一方面,因为mod_rewrite是通过API修正步骤来实现目录级(.htaccess文件)配置的, 而认证步骤先于API修正步骤,所以可以用%{REMOTE_USER}。
6、预设形式:%{LA-F:variable} ,variable的最终值在执行一个内部(基于文件名的)子请求后确定。 大多数情况下和上述的LA-U是相同的。

CondPattern是条件模式,即一个应用于当前TestString实例的正则表达式。TestString将被首先计算,然后再与 CondPattern匹配。

注意:CondPattern是一个perl兼容的正则表达式,但是还有若干增补:
1、可以在CondPattern串的开头使用’!'(惊叹号)来指定不匹配
2、CondPatterns有若干特殊的变种。除了正则表达式的标准用法,还有下列用法:

<CondPattern‘(词典顺序的小于)
将CondPattern视为纯字符串,与TestString按词典顺序进行比较。如果TestString小于CondPattern则为真。
>CondPattern‘(词典顺序的大于)
将CondPattern视为纯字符串,与TestString按词典顺序进行比较。如果TestString大于CondPattern则为真。
=CondPattern‘(词典顺序的等于)
将CondPattern视为纯字符串,与TestString按词典顺序进行比较。如果TestString等于CondPattern(两个字符串逐 个字符地完全相等)则为真。如果CondPattern是””(两个双引号),则TestString将与空字符串进行比较。
-d‘(目录)
将TestString视为一个路径名并测试它是否为一个存在的目录。
-f‘(常规文件)
将TestString视为一个路径名并测试它是否为一个存在的常规文件。
-s‘(非空的常规文件)
将TestString视为一个路径名并测试它是否为一个存在的、尺寸大于0的常规文件。
-l‘(符号连接)
将TestString视为一个路径名并测试它是否为一个存在的符号连接。
-x‘(可执行)
将TestString视为一个路径名并测试它是否为一个存在的、具有可执行权限的文件。该权限由操作系统检测。
-F‘(对子请求存在的文件)
检查TestString是否为一个有效的文件,而且可以在服务器当前的访问控制配置下被访问。它使用一个内部子请求来做检查,由于会降低服务器的性能, 所以请谨慎使用!
-U‘(对子请求存在的URL)
检查TestString是否为一个有效的URL,而且可以在服务器当前的访问控制配置下被访问。它使用一个内部子请求来做检查,由于会降低服务器的性 能,所以请谨慎使用!

注意:所有这些测试都可以用惊叹号作前缀(‘!’)以实现测试条件的反转。
3、还可以在CondPattern之后追加特殊的标记[flags]作为 RewriteCond指令的第三个参数。flags是一个以逗号分隔的以下标记的列表:

nocase|NC‘(忽 略大小写)
它使测试忽略大小写,扩展后的TestString和CondPattern中’A-Z’ 和’a-z’是没有区别的。此标记仅用于TestString和CondPattern的比较,而对文件系统和子请求的检查不起作用。
ornext|OR‘(或下一条件)
它以OR方式组合若干规则的条件,而不是隐含的AND。典型的例子如下:

RewriteCond %{REMOTE_HOST} ^host1.* [OR]
RewriteCond %{REMOTE_HOST} ^host2.* [OR]
RewriteCond %{REMOTE_HOST} ^host3.*
RewriteRule … 针对这3个主机的规则集 …如果不用这个标记,你就必须要书写三次条件/规则对。

举例
如果要按请求头中的”User-Agent:”重写一个站点的主页,可以这样写:

RewriteCond  %{HTTP_USER_AGENT}  ^Mozilla.*
RewriteRule  ^/$                 /homepage.max.html  [L]

RewriteCond  %{HTTP_USER_AGENT}  ^Lynx.*
RewriteRule  ^/$                 /homepage.min.html  [L]

RewriteRule  ^/$                 /homepage.std.html  [L]

解释:如果你使用的浏览器识别标志是’Mozilla’,则你将得到内容最大化的主页(含有Frames等等)。如果你使用的是(基于终端的)Lynx, 则你得到的是内容最小化的主页(不含table等等)。如果上述条件都不满足(使用的是其他浏览器),则你得到的是一个标准的主页。

[转载]发布FCKeditor语法高亮插件

mikel阅读(1004)

[转载]发布FCKeditor语法高亮插件 – Kend’s Blog.

语法高亮的插件已经使用一段时间了,感觉没什么大问题。现在也有网友问我什么时候可以下载,今天有点空,就把它打包放上来了。

使用方法:

1、在您的FCKeditor的配置文件中(一般为fckconfig.js或custom.config.js)

配置其中的FCKConfig.ToolbarSets,添加HighLighter。

如:

FCKConfig.ToolbarSets[“review”] = [

[&apos;HighLighter&apos;,&apos;Bold&apos;,&apos;Italic&apos;,&apos;Underline&apos;,&apos;StrikeThrough&apos;,&apos;Link&apos;,&apos;Unlink&apos;,&apos;Image&apos;,&apos;Rule&apos;,&apos;Smiley&apos;,&apos;TextColor&apos;,&apos;BGColor&apos;]

];

当然,你可以放到别的工具栏,不过记得注意大小写。

2、根据你指定的plugin目录,注册plugin

如:

// 代码语法高亮插件

FCKConfig.Plugins.Add( &apos;highlighter&apos;, &apos;zh-cn,en&apos; ) ;

3、OK,你会发现你的FCK工具栏的图片多了一个带有”ab”字母,黄底的图标。你就可以使用语法高亮显示功能了。

点击下载语法高亮的插件

通过

[转载]在Asp.net MVC使用thickbox

mikel阅读(1193)

[转载]在Asp.net MVC使用thickbox实现调用页面的Ajax更新 – 打造可持续发展的事业 – 博客园.

MVC模式中,通常都是Controller处理请求并生成数据,选 择一个合适的View来显示结果给用户。虽然ASP.NET MVC已经有非常丰富的ActionResult来满足不同情况下的需求,但是有了Ajax的利器,我们希望有更流畅的交互方式。我们希望能够在一个界面完成列表的显示,编辑或者新增,并完成 刷新。借助JQuery的一个扩展thickbox我们能够达到这个效果。

本文的灵感来自于一篇博文:MVC AJAX Form with Ajax.BeginForm() and JQuery Thickboxhttp://geekswithblogs.net/michelotti/archive/2009/08/31/mvc-ajax-form-with-ajax.beginform-and-jquery-thickbox.aspx

和该文的差异在于thickbox中提交后,他更新的是thickbox中的内容,而不是加载thickbox的页面(即thickbox后 面的那个页面)。

我演示的场景如下

点击“新建角色”弹出一个新建的角色thickBox输入窗口,填入相 应的信息后,将利用Ajax更新角色列表

假设你已经非常了解ASP.NET MVC了。

这里我们不讨论MVC中的Model层, 假设Model数据可以通过Service层获取。

在这个例子里,我们需要3ViewRoleList.aspxRoleNameList.ascxRoleCreate.ascx。后两个PartialView

RoleController需要处理以下几个请求:

[get] RoleNameList():显示Role列表,返回RoleNameList.ascx这个PartialView.

[get] RoleCreate():显示Create的输入界面RoleCreate.ascx等待用户输入相关的信息。

[post]ReleCreate(Role role):处理Create的提交,并返回RoleNameList.ascx

看看代码
<%@ Page Title=”” Language=”C# MasterPageFile=”~/Views/Shared/Site.Master” Inherits=”System.Web.Mvc.ViewPage %>

<asp:Content ID=”Content1″ ContentPlaceHolderID=”TitleContent” runat=”server”>

RoleList

asp:Content>

<asp:Content ID=”Content2″ ContentPlaceHolderID=”MainContent” runat=”server”>

<div id=”rolenamelist” class=”LeftPanel”>

<% Html.RenderPartial(“RoleNameList”, Model.allRoles); %>

div>

<div class=”RightPanel”>

div>

<div class=”clear”>

asp:Content>

RoleNameList.ascx

<%@ Control Language=”C# Inherits=”System.Web.Mvc.ViewUserControl>” %>

<h2>

系统角色h2>

<ul>

<% foreach (var item in Model)

{ %>

<li>

<%=Html.ActionLink (“RoleEdit”, new { id = item.Id })%>

<%=Html.ActionLink“RoleDetail”, new { id = item.Id })%>

<%=Html.ActionLink (“RoleDelete”, new { id = item.Id })%>

  

<%= Html.Encode(item.name) %>

li>

<% } %>

ul>

<div id=”SamDiv”>

div>

<p>

<%= Html.ActionLink新建角色”, “RoleCreate”, new { height = 200, width = 300, modal = true }, new { @class = “thickbox” })%>

p>

其中RoleList.aspx

其中将最后一个ActionLinkclass设置为thickboxthickbox将 会自动以ajax的方式请求到相应链接的内容并显示在一个类似于弹出对话 框的层里面。

结合参考的文档,我曾经天真地想,是不是在RoleCreate.ascx,将UpdateTargetId置为父窗口的相应DIV ID即可。如是

<%@ Control Language=”C#” Inherits=”System.Web.Mvc.ViewUserControl<RealMVC.Data.DO_RoleInfo>” %>

<% using (Ajax.BeginForm(“RoleCreate”,“Role” , new AjaxOptions { HttpMethod = “post”, InsertionMode = InsertionMode.Replace, UpdateTargetId = “rolenamelist” }))

{%>

<fieldset>

<legend>创建新的角色</legend>

<div class=”editor-label”>

<%= Html.LabelFor(model => model.name)%>

</div>

<div class=”editor-field”>

<%= Html.TextBoxFor(model => model.name)%>

<%= Html.ValidationMessageFor(model => model.name)%>

</div>

<div class=”editor-label”>

<%= Html.LabelFor(model => model.comment)%>

</div>

<div class=”editor-field”>

<%= Html.TextBoxFor(model => model.comment)%>

<%= Html.ValidationMessageFor(model => model.comment)%>

</div>

<p>

<input type=”submit” value=”Create” />

</p>

</fieldset>

<% } %>

你可以试一下,这时候会出现问题,thickbox不会关闭,更谈不上更新后面的页面。

如是我试图将AjaxOptions的OnBegin设置为tb_remove试图先关闭thickbox但是产生 错误,无法正确执行AjaxForm产生的代码。究其原因可能是tb_remove返回了false,浏览器终止了后续的请求,于是我修改了 thickbox代码。

右边是我修改之后的代码。

这个时候RoleCreate.ascx代码如下:

<% using (Ajax.BeginForm(“RoleCreate”, “Role”, new AjaxOptions { HttpMethod = “post”, InsertionMode = InsertionMode.Replace, UpdateTargetId = “rolenamelist”, OnBegin = “tb_remove_return_true” }))

再附上RoleController中对这个Ajax请求的处理方法:

[AcceptVerbs(HttpVerbs.Post)]

public ActionResult RoleCreate(DO_RoleInfo role)

{

try

{

// TODO: Add insert logic here

RoleService.Save(role);

if(Request.IsAjaxRequest())

return PartialView(“RoleNameList”,RoleService.ListAllRoles());

else

return RedirectToAction(“RoleList”);

}

catch

{

return View();

}

}

总结一下:

l 先阅读MVC AJAX Form with Ajax.BeginForm() and JQuery Thickboxhttp://geekswithblogs.net/michelotti/archive/2009/08/31/mvc-ajax-form-with-ajax.beginform-and-jquery-thickbox.aspx

l 创建链接ActionLink,将class设置为thickbox,以便在thickbox中显示RoleCreate View。

l CreateView中使用AjaxForm,设置OnBegin调用tb_remove来关闭thickbox

l 关键是重写一个tb_remove使其返回一个true而不是false

[转载]ASP.NET MVC 2 RC 2 发布

mikel阅读(878)

[转载]ASP.NET MVC 2 RC 2 发布 – TNT2(SZW)’s Blog @ .net – 博客园.

下载地址:http://www.microsoft.com/downloads/details.aspx?FamilyID=7aba081a-19b9-44c4-a247-3882c8f749e3&displaylang=en

目前次版本只支持的IDE只有VS2008(.NET3.5),针对VS 2010的RC版本将会在不久后提供下载。这次RC2的升级主要修复了一些bug,添加了一些API以及改进了了一些而方法。

ASP.NET MVC 2 RC 1到RC 2变化主要如下:

1、在RC1中新增的ASP.NET MVC 2 validation(对ViewData中Model数据验证)功能,现在已 经由 model-validation 取代了 input-validation 。也就是说,如果你使用 model binding (将Model属性自动绑定到View中,并自动绑定从View中Post回Controller的值),那么所有的属性都将被验证一遍,而不仅仅是变更 后的数据。

(注:个人认为这在某些情况下反而会带来不便,比如当你只想绑定一个模型中部分属性,以此作为一个暂时的“容器”的时候,可能会使 ModelState.IsValid变成false。不知是否可以有选择性地使用新的特性)

2、新的“强类型HTML(<input>标签)的辅助方法”,现在支持了Lambda表达式,从而可以使你使用到数组(array)或者集 合索引(collection indexes)。例如现在可以这么做:Html.EditorFor(m=>m.Orders[i]) ,这段代码将会生成以序列i为name、具体数组中的值为value的<input>标签。

(注:这一点在DropDownList中将极为有用。)

3、重新调整过的Html.EditorFor() 和 Html.DisplayFor() 扩展方法,在默认情况下将自动对应简单属性。这使得自动构造Form表单变为更加简单了。

(注:终于有点像某些“前辈”MVC的Form了,希望这种改进可以来得更猛烈些)

4、model验证所使用的客户端脚本中的id现在更清晰了。在RC1中,id会像这样:form0_ prefix,现在id改为了以属性名称为前缀,如:unitPrice_validationMessage

(注:这点变化可以使前台开发人员对页面的控制更加完整)

5、Html.ValidationSummary() 方法增加了一个参数,可以控制汇总信息显示的级别,是整个Model级别,或是单个属性级别。

(注:变的更人性化了,有的页面我们只需要让它显示一个tip就可以了,不需要把所有的都重复列出来)

6、AccountController中使用默认的ASP.NET MVC Web Application模板更加整洁了。

7、脚手架(scaffolding)功能现在提供了在Controller中的Delete方法,以及对的View页面(模板)。

8、JQuery 1.4.1被包含到了项目中,取代了原先的1.3.2版本。同步更新的还有用来智能提示的vsdoc文件。

9、其他一些很有意义的改进,比如第2点中所说的“强类型HTML(<input>标签)的辅助方法”现在更快了。

次版本的源代码可以在这里下载到:http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=39978

http://szw.cnblogs.com/
研究、探讨ASP.NET
转载请注明出处和作者,谢谢!

[转载]企业应用下的业务组件开发实践

mikel阅读(1206)

[转载]企业应用下的业务组件开发实践 – Anders小明的Blog – 博客园.

作者:  Anders小明


什么是企业应用下的业务组件

首先,这是一个组件,这 意味着它需要在容器里运行,因此不包括任何中间件服务,同时以一定结构(文件结构或者压缩格式)组成,被容器识别;其次,这是一个业务组件,即提供的是应 用服务,而非技术服务;第三,这是企业应用,在业务上包括功能和服务(Service,当前最时髦的说法,你可以理解为API),技术上(以J2EE来讲)包括:UI资 源(JSFJSPJSCSS等)、应用程序(Java)资源和配置文件、数据库表定义、初始化数据和存储过程。

为什么要企业应用下的业务组件

组件技术从提出到现在已 经有20多年了,为什么要提企业应用业务组件?因为现有的组件技术不支持 企业应用环境下的组件要求,J2EEEJB不支持,.NETDLL也不支持。

如前所述,一个企业应用 通常包括了交互界面、应用代码以及数据库结构,而不论是EJB还是DLL只支持应用代码,都不包括交互界面和数据库结构。

如果说EJB不是,那么J2EEEAR或者WAR是否算 是一个组件?答案也不是,EAR或者WAR部署的是一个企业应用,请注意EJB规范中明确说:The Enterprise JavaBeans architecture is a architecture for the development and deployment of component-based (distributed) business applications(EJB 2.x3.x唯一的区别 是2.xdistributed),它们有自己的应用域,彼此相互隔离(简单的看,它们有各自独立的会话管理)。.NET也是有自己的应用域概念。

更进一步,基于应用的部 署导致了三个隔离问题:交互(界面)隔离程序访问隔离数据隔 离(请注意这三个问题分别对应了企业应用业务组件的三个技术内容)。交互隔离导致了企业用户必须访问不同界面,代码访问隔离导致了点对 点的集成以及诸如性能、事务和异步处理等各种非功能性问题,而数据隔离导致了数据有效性、一致性等等问题。所有这些都进而导致了维护的问题。

为了解决这些问题,大厂 商们都提出了各种解决方案:Portal来解决交互隔离问题,通过ESB来解决代码访问隔离问题,以及通过所谓的信息服务(Information Service)来解决数据隔离问题。

那么OSGi技术或者SCA技 术能否满足要求?答案是目前不能,OSGi最初开发的目的就不是为了企业 应用,只是这几年开始成熟,并向企业应用方向发展。09年推出的企业版 (草案)刚刚提出针对程序访问问题的方案,如远程服务、事务管理等;交互隔离问题上规范并没有提出相应方案,只有EclipseEquinox提 出了界面的扩展点机制,但这也不能解决B/S环境的问题;而数据隔离问题 就没有任何方案。SCA从一开始就是面向企业应用,不过不解决交互隔离和 数据隔离问题。

此外,对于行业ISV来说,除企业用户面临的这些种种问题,还面临着其它问题。企业用户毕竟只是面对自己的需求,行业ISV却面临着多个企业用户的需求,面临定制化带来的维护问题,特别是业务和技术的隔离问题(即如何保持 构建业务组件的所使用技术的平稳升级)。

组件的容器

既然要企业应用下的业务 组件,而现有的组件技术又无法支撑,那么就需要一个新的组件容器了(当然,作为一个普通开发人员,我们无法新建一个公开标准的组件体系,也独立维护一个私 有的)。新的组件容器完全使用现有的中间件技术,并加上一些新的内容,包括如下:

  1. 组 件框架,识别组件,以及组件(文件)结构和各个技术工件。
  2. 技术框架,提供业务无关的技术支持,以便于技术的平稳升级切换。
  3. 运行容器,采用现有中间件技术,包括Tomcat、应用服务器和数据库服务等;
  4. 工具,包括打包以及部署工具等。

关于数据隔离问题,在EIP中提到了各种解决方案,这里采用的共享数据库方式,即各个组件都共用一个数据库,各个组件只提供数 据库定义和初时数据(如同EJB/OSGi一样,运行时环境由容器提 供)。

组件的关系

组件的关系分为两种:依 赖和联动。依赖关系在已有的组件技术上已经广为认知,而联动则是新创造的(肯定不是第一个创建的,只不过不同人有不同的叫法)。

联动和依赖的区别是:如 果有组件B和组件A联动,则组件B可以 在没有组件A的情况下运行,并提供相应功能。

针对三种不同技术工件 (即三个隔离问题)呈现不同特点,如下:

1. UI资源(交互隔 离问题),依赖是指UI资源的嵌入、引用和替换,联动是指UI资源的新增。

2. 应用程序(程序访 问隔离),依赖是指API/模型依赖,联动是指消息(传统消息和JMS消息)以及SPI实 现。其中,无论是依赖或者联动都涉及到相应的非功能性需求,包括:异步、事务控制和服务时限等。

3. 数据库资源(数据 隔离),依赖是指外键关联和级联操作,无明显的联动关系。

这里,需要关注应用程序 的依赖和联动

1. SPIAPI存在业务不匹配问题。

虽然组件A依赖组件B,但是 不代表组件B提供的服务完全匹配组件A的要求。有时组件A所 需要的数据需要组件B的多个API组成,为了开发方便或者组件A所需要的性能问题,可能会在组件B新写一个接口给组件A使用,注意该接口不是组件BAPI,该接口仅适用于组件A

2. 尽可能的使用SPI集成方式

SPI集成方式是相对于API集成方式,API集 成方式就是,组件B直接调用其它组件的API及其模型。SPI集 成方式(类似于依赖倒置),组件B定义其所需要的接口及其模型,由组件A或者胶水层代码来实现。

这个点对于行业ISV尤为明显。对于企业用户来说,依赖是明确的,组件A依赖/联动于组件B,但对于行业ISV, 则面临着定制化问题,虽然组件A依赖/联动于组件B,但是 在某个定制化项目中,由于客户已有系统C,而需要组件A依赖/联动于客户 已有系统C。此时采用SPI方式。

在开源世界里采用SPI方式更是广泛。很多框架为了兼容(同一功能)不同实现的类库,都是先定义框架所需接口,并同时提供 不同类库的胶水代码。

不论是EJB/OSGi/SCA都没有对SPI集 成方式的支持。

3. 依赖和联动的非功 能性需求。

事实上,非功能性需求都 是在集成时才存在的。以事务管理为例,除了及其少数的例子外,大部分事务只能在处理流程才被决定(注意,EJB在这方面着是定义在API上的,这样的设计是不适应需求的),而组件AAPI在用例1中需要被 异步调用,而在用例2中需要被同步调用是常见的。即便是OSGi规范,也在这方面没有任何处理。

组件的定制化

定制化问题只针对于行业ISV有效,对于企业用户来说,除非是那种跨国企业在面临不同国度的业务模式、法律监管和会计制度等差 异,存在定制化需要,即使如此,ISV和企业用户对于同一问题的解决方式 也是不同的。

既然我们已经将原有的应 用采用组件化方式开发,那么应用的定制化问题就转化为组件的定制化问题。同样,应用的定制化手段也就转化为组件的定制化手段。

组件框架

罗罗嗦嗦的说了半天,有人就说了:这不就是把UIJava和数据 库三个东东一打包,然后说这就是一个企业应用下的业务组件,有啥新意呢,不就是模块化开发嘛,一直一来大家都是就是这么搞的嘛,何必搞个怪名词来忽悠。

是的,就是把UIJava和数据库 三个东东整合在一起,组件容器说提到的技术框架很多的开发队伍都有一套,运行容器更是有无数开源商业的,打包部署工具更是写了无数。

这确确实实就是我们常说 的模块化开发。但是模块化开发不同于组件开发,模块化开发只是在逻辑上做了切分,物理上(开发出的系统代码)通常并没有真正意义上的隔离,一切都只是在文 档中。

我们需要一点干货,只有 实实在在的组件框架才能组件化开发真正落地的(如同OSGi框架那样): 我们需要一个类似于Equinox的界面扩展框架来支持UI资源的依赖和联动;我们需要一个集成框架来支持应用程序的依赖和联动,解决所面临的种种问题(业务 不匹配、SPI集成以及各种非功能性需求);我们需要一个打包部署工具 (类似Spring DM)提供部署UI资源、应用程序和数据库定义资源(Spring DM提供了基于Web资 源的部署能力)。

其它问题

对于采用J2EEB/S环境的组 件应用还面临一个问题,即现有Servlet规范只允许一个web.xml,不支持组件各自定义私有的FilterServlet, 不过这个问题不是很严重,在现有技术框架已经支持一份简单的web.xml, 而新的Servlet规范已经允许多个web.xml

分布式部署以及集群部署 问题,这其实不是个问题。基于应用的我们有很多手段和技术,那么基于组件的也一样有办法。

[转载]ASP.NET的SEO:目录

mikel阅读(1147)

[转载]ASP.NET的SEO:目录 – 自由飞 – 博客园.

ASP.NET 的SEO:基础知识

ASP.NET 的SEO:Global.asax和HttpModule中的RewritePath()方法——友好的URL

ASP.NETSEO:正则表达式

ASP.NET 的SEO:服务器控件背后——SEO友好的Html和JavaScript

ASP.NET的SEO:使用.ashx文件——排除重复内容

ASP.NET 的SEO:HTTP报头状态码—内容重定向

ASP.NET 的SEO:Linq to XML—网站地图和RSS Feed

ASP.NETSEOSEO Hack

这 个系列可以算是我的一个读书笔记—WROX红皮书系列之《搜索引擎优化高级编程》(Professional Search Engine Optimization with ASP.NET:A Developer’s Guide to SEO)。我觉得蛮不错的,第一是比较系统和权威;第二是不同于一般的SEO的理论介绍,它着重于asp.net技术的实现!推荐一下。另外,因为是老外 的书,所以所谓的搜索引擎,其实没有包括百度,主要针对的是Google和Yahoo。但博客中也有很多知识只是我自己的理解,欢迎大家指正讨论。

SEO, 搜索引擎优化,简单的理解,就是一种让网站能尽可能的被搜索引擎收录而且排名靠前的技术。可能很多程序员并不是很看重或者了解,但对于无数的草根站长(包 括垃圾站长,呵呵)和众多希望进行网络营销的中小企业而言,SEO是简直是一个入门的基本功。但关于SEO的基础知识,我也就点到即止,因为类似的文章网 上太多了。而且是在博客园里面,我会把重点放在技术层面上。

所涉及的技术其实比较“底层”,对于直接学习 ASP.NET2.0甚至是3.5的同学来说,应该还是很有帮助的,如:
1. 应用程序生命周期事件,如Global.asax和HttpModule;

3. 正则表达式;(以上都关系到URLRewrite)

4. Http报头信息中的状态码:404、301、500等;(主要用于站点重定向)

5. XML文件生成;(关系到网站地图,RSS)

6. HttpHandler;(动态的生产验证码、Robert.txt文件,用于排除重复内容)

[转载]ASP.NET的SEO:Linq to XML---网站地图和RSS Feed

mikel阅读(1102)

[转载]ASP.NET的SEO:Linq to XML—网站地图和RSS Feed – 自由飞 – 博客园.

本 系列目录

网站地图的作用是让搜索引擎尽快的,更多的收录网站的各个网页。

这里我们首先要明白一个基本的 原理,搜索引擎的爬行方式。整个互联网就像一张纵横交错的“网”:网的各个节点就是各个网页,而各个网页之间通过url相互连接。蜘蛛可以从一个网页出 发,通过该网页上的url,爬到另一个网页;再通过另一个网页上的url,再爬到更多的网页……,以此类推。但如果是一个新发布的网站,可能就没有其他 url指向它,那么它就永远不会被“爬到”(收录)。为了解决这个问题,新站可以自己主动向搜索引擎提交url,申请蜘蛛前来抓取(Google申请网 址:),但申请时一般只会提交一个主页的url。

为了让所有的url(尤其是动态生成的)都能被蜘蛛快捷便利的检索到,我们就需要提供一 个全面完整、架构清晰和更新及时的网站地图。(网站地图的更多信 息)。

和处理重复内容的robots.txt文件,我们通过.ashx文件来生成一个基于sitemaps.org的 xml格式的网站地图。网站地图生成之后,我们就可以向Google等搜索引擎提交。大量的文章证实,提交网站地图将极大的提高网站的收录速度和深度。其 他几乎所有的SEO方法,都有可能效果难以证实、失效甚至带来副作用,但提交网站地图除外!

Linq to XML为我们带来了近乎完美的操作体验。

WebSite

<%@ WebHandler Language=C# Class=website %>

using System;
using System.Web;
using System.Xml;
using System.Xml.Linq;
using System.Linq;

public class website : IHttpHandler {

public void ProcessRequest (HttpContext context) {

context.Response.ContentType = text/xml;

//文件的声明信息, 第第三个参数standalone的值yes 表示这个 XML 文档是自包含的(self-contained)而不依赖于外部所定义的一 个 DTD.
XDeclaration declaration = new XDeclaration(1.0, UTF-8, yes);
context.Response.Write(declaration);

//XML文件的命名空间
XNamespace ns = http://www.google.com/schemas/sitemap/0.84;
XElement siteMap = new XElement(ns + urlset);

string fixedUrl = http://www.freeflying.com/article;
string wholeUrl = string.Empty;

//循环取出数据,转换成XML节点
foreach (var item in Articles.GetArticles())
{
XElement url = new XElement(url);

wholeUrl = string.Format({0}?id={1}&catelog={2},fixedUrl,item.ID,item.Catelog);
XElement loc = new XElement(loc, wholeUrl);
XElement lastmod = new XElement(lastmod, item.LastMod.AddDays(23).ToShortDateString());
XElement changefreq = new XElement(changefreq, item.Frequency);
XElement priority = new XElement(priority, item.Weight);

url.Add(loc, lastmod, changefreq, priority);

siteMap.Add(url);
}

//最后输出整个xml文件
context.Response.Write(siteMap);
}

public bool IsReusable {
get {
return false;
}
}

}

同 样还将使用到xml技术的还有RSS

RSS

<%@ WebHandler Language=C# Class=rss %>

using System;
using System.Web;
using System.Xml;
using System.Xml.Linq;

public class rss : IHttpHandler {

public void ProcessRequest (HttpContext context) {
context.Response.ContentType = text/xml;

context.Response.Write(<?xml version=\1.0\ encoding=\UTF8\ ?>);

XElement rssFeed = new XElement(rss, new XAttribute(version,2.0));

string fixedUrl = http://www.freeflying.com/article;
string wholeUrl = string.Empty;

XElement channel = new XElement(channel,
new XElement(title, freeflying),
new XElement(link, fixedUrl),
new XElement(description,the website for dream flying freely),
new XElement(pubDate,DateTime.Now.ToString())
);

foreach (var article in Articles.GetArticles())
{
XElement item = new XElement(item);

XElement title = new XElement(title, article.Title);

wholeUrl = string.Format({0}?id={1}&catelog={2}, fixedUrl, article.ID, article.Catelog);
XElement link = new XElement(link, wholeUrl);

XElement description = new XElement(description, article.Description);

XElement pubDate = new XElement(pubDate, article.LastMod.ToString());

item.Add(title,link,description,pubDate);

channel.Add(item);
}

rssFeed.Add(channel);

context.Response.Write(rssFeed);

}

public bool IsReusable {
get {
return false;
}
}

}

模拟数据

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Web.UI.MobileControls;
using System.Collections.Generic;

/// <summary>
/// Summary description for Articles
/// </summary>
public class Articles
{
public Articles()
{
//
// TODO: Add constructor logic here
//
}

public static List<Article> GetArticles()
{
return new List<Article>(){
new Article(234, blog, DateTime.Now.AddDays(23), Freq.none, 0.8, ASP.NET SEO, articles about SEO in ASP.NET),
new Article(267, blog, DateTime.Now.AddDays(245), Freq.daily, 0.6, ado.net pro,about the dataset usage),
new Article(653, news, DateTime.Now.AddDays(45), Freq.daily, 1,CLR via C#,notebook about this book)
};
}

}

public class Article
{
public int ID;
public string Catelog;
public DateTime LastMod;
public double Weight;
public Freq Frequency;
public string Title;
public string Description;

public Article(int id, string catelog, DateTime lastMod, Freq frequency, double weight, string title, string description)
{
ID = id;
Catelog = catelog;
LastMod = lastMod;
Weight = weight;
Frequency = frequency;
Title = title;
Description = description;
}
}

public enum Freq
{
none = 1,
daily = 2,
weekly = 3,
}