<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_Otis's Technology Space</title><subtitle type="text"/><id>http://feed.cnblogs.com/blog/u/50718/rss</id><updated>2012-02-10T04:53:51Z</updated><author><name>Otis's Technology Space</name><uri>http://www.cnblogs.com/OtisBlog/</uri></author><generator>CNBlogs BlogServer</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/OtisBlog/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/50718/rss"/><entry><id>http://www.cnblogs.com/OtisBlog/archive/2012/01/30/2332175.html</id><title type="text">Linux crontab 详细介绍及执行php</title><summary type="text">Linux crontab 命令介绍 语法介绍 使用权限 : root用户和crontab文件的所有者 crontab格式 语法 : crontab [-e [UserName]|-l [UserName]|-r [UserName]|-v [UserName]|File ] 说明 : crontab 是用来让使用者在固定时间或固定间隔执行程式之用，换句话说，也就是类似...</summary><published>2012-01-30T08:46:00Z</published><updated>2012-01-30T08:46:00Z</updated><author><name>Otis's Technology Space</name><uri>http://www.cnblogs.com/OtisBlog/</uri></author><link rel="alternate" href="http://www.cnblogs.com/OtisBlog/archive/2012/01/30/2332175.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/OtisBlog/archive/2012/01/30/2332175.html"/><content type="html">&lt;p&gt;&lt;b&gt;Linux crontab 命令介绍&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;语法介绍&lt;/strong&gt;&lt;/p&gt; &lt;b&gt;使用权限&lt;/b&gt; : root用户和crontab文件的所有者   &lt;p&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/OtisBlog/201201/201201301646315373.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/OtisBlog/201201/201201301646317947.png" width="244" height="89" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;crontab格式&lt;/p&gt;  &lt;p&gt;语法&lt;/p&gt; :   &lt;p&gt;crontab [-e [UserName]|-l [UserName]|-r [UserName]|-v [UserName]|File ] &lt;/p&gt;  &lt;p&gt;&lt;b&gt;说明&lt;/b&gt; : &lt;/p&gt;  &lt;p&gt;crontab 是用来让使用者在固定时间或固定间隔执行程式之用，换句话说，也就是类似使用者的时程表。-u user 是指设定指定 user 的时程表，这个前提是你必须要有其权限(比如说是 root)才能够指定他人的时程表。如果不使用 -u user 的话，就是表示设定自己的时程表。 &lt;/p&gt;  &lt;p&gt;&lt;b&gt;参数&lt;/b&gt; : &lt;/p&gt;  &lt;p&gt;-e [UserName]: 执行文字编辑器来设定时程表，内定的文字编辑器是 VI，如果你想用别的文字编辑器，则请先设定 VISUAL 环境变数来指定使用那个文字编辑器(比如说 setenv VISUAL joe) &lt;/p&gt;  &lt;p&gt;-r [UserName]: 删除目前的时程表 &lt;/p&gt;  &lt;p&gt;-l [UserName]: 列出目前的时程表 &lt;/p&gt;  &lt;p&gt;-v [UserName]:列出用户cron作业的状态 &lt;/p&gt;  &lt;p&gt;&lt;b&gt;时程表的格式如下&lt;/b&gt; : &lt;/p&gt;  &lt;p&gt;f1 f2 f3 f4 f5 program &lt;/p&gt;  &lt;p&gt;其中 f1 是表示分钟，f2 表示小时，f3 表示一个月份中的第几日，f4 表示月份，f5 表示一个星期中的第几天。program 表示要执行的程式。 &lt;/p&gt;  &lt;p&gt;当 f1 为 * 时表示每分钟都要执行 program，f2 为 * 时表示每小时都要执行程式，其余类推 &lt;/p&gt;  &lt;p&gt;当 f1 为 a-b 时表示从第 a 分钟到第 b 分钟这段时间内要执行，f2 为 a-b 时表示从第 a 到第 b 小时都要执行，其余类推 &lt;/p&gt;  &lt;p&gt;当 f1 为 */n 时表示每 n 分钟个时间间隔执行一次，f2 为 */n 表示每 n 小时个时间间隔执行一次，其余类推 &lt;/p&gt;  &lt;p&gt;当 f1 为 a, b, c,... 时表示第 a, b, c,... 分钟要执行，f2 为 a, b, c,... 时表示第 a, b, c...个小时要执行，其余类推 &lt;/p&gt;  &lt;p&gt;使用者也可以将所有的设定先存放在档案 file 中，用 crontab file 的方式来设定时程表。 &lt;/p&gt;  &lt;p&gt;由于unix版本不一样，所以部分语法有差别，例如在hp unix aix 中设定间隔执行如果采用*/n 方式将出现语法错误，在这类unix中 ，间隔执行只能以列举方式，详请见例子。 &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;簡單使用方法：&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;crontab –e&amp;#160; &lt;/p&gt;  &lt;p&gt;後加入：&lt;/p&gt;  &lt;p&gt;*/1 * * * * /usr/local/curl/bin/curl &lt;a href="http://appbaike.com/"&gt;http://appbaike.com/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;每分鐘執行一次。&lt;/p&gt;  &lt;p&gt;然後 /sbin/service crond restart&amp;#160; 重新啟動&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;a name="3_2"&gt;&lt;/a&gt;詳細使用方法:&lt;/strong&gt;&lt;/p&gt; 用VI编辑一个文件 cronfile，然后在这个文件中输入格式良好的时程表。编辑完成后，保存并退出。   &lt;p&gt;在命令行输入 &lt;/p&gt;  &lt;p&gt;$: crontab cronfile &lt;/p&gt;  &lt;p&gt;这样就将cronfile文件提交给c r o n进程，同时，新创建cronfile的一个副本已经被放在/ v a r / s p o o l / c r o n目录中，文件名就是用户名。&lt;/p&gt;  &lt;p&gt;&lt;b&gt;以某一频率执行任务&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;linux缺省会启动crond进程，crond进程不需要用户启动、关闭。    &lt;br /&gt;crond进程负责读取调度任务并执行，用户只需要将相应的调度脚本写入cron的调度配置文件中。     &lt;br /&gt;cron的调度文件有以下几个：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;crontab &lt;/li&gt;    &lt;li&gt;cron.d &lt;/li&gt;    &lt;li&gt;cron.daily &lt;/li&gt;    &lt;li&gt;cron.hourly &lt;/li&gt;    &lt;li&gt;cron.monthly &lt;/li&gt;    &lt;li&gt;cron.weekly &lt;/li&gt; &lt;/ol&gt;  &lt;ul&gt;&lt;/ul&gt;  &lt;p&gt;如果用的任务不是以hourly monthly weekly方式执行，则可以将相应的crontab写入到crontab 或cron.d目录中。&lt;/p&gt;  &lt;p&gt;示例：    &lt;br /&gt;每隔一分钟执行一次脚本 /opt/bin/test-cron.sh     &lt;br /&gt;可以在cron.d新建脚本 echo-date.sh     &lt;br /&gt;内容为&lt;/p&gt;  &lt;p&gt;*/1 * * * * root&amp;#160; /opt/bin/test-cron.sh&lt;/p&gt;  &lt;p&gt;&lt;b&gt;在指定的时间运行任务&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;也可以通过at命令来控制在指定的时间运行任务&lt;/p&gt;  &lt;p&gt;如：&lt;/p&gt;  &lt;p&gt;at -f test-cron.sh -v 10:25    &lt;br /&gt;其中-f 指定脚本文件， -v 指定运行时间&lt;/p&gt;  &lt;p&gt;quote:ea946d690b=&amp;quot;lophyxp&amp;quot;]首先用    &lt;br /&gt;contab -l &amp;amp;gt;contabs.tmp     &lt;br /&gt;导出contab的配置。     &lt;br /&gt;然后编辑contabs.tmp文件。以一下格式添加一行：     &lt;br /&gt;分钟 小时 天 月 星期 命令     &lt;br /&gt;比如     &lt;br /&gt;10 3 * * 0,6 hello     &lt;br /&gt;就是每周六、周日的3点10分执行hello程序。     &lt;br /&gt;15 4 * * 4-6 hello     &lt;br /&gt;就是从周四到周六的4点15点执行hello程序。     &lt;br /&gt;然后用     &lt;br /&gt;contab contabs.tmp     &lt;br /&gt;命令导入新的配置。     &lt;br /&gt;一般不建议直接修改/etc/下的相关配置文件。 &lt;/p&gt;  &lt;p&gt;启动cron进程的方法&lt;strong&gt;：/etc/init.d/crond start&lt;/strong&gt;     &lt;br /&gt;&lt;strong&gt;开机就启动cron进程的设置命令：chkconfig --add crond&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;方法二：&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;把cron加入到启动脚本中：&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;# rc-update add vixie-cron default&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;crontab -l #查看你的任务&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;crontab-e#编辑你的任务&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;crontab-r#删除用户的crontab的内容&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;实例讲解二：&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;系统cron设定：/etc/crontab&lt;/strong&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; 通过 /etc/crontab 文件，可以设定系统定期执行的任务，当然，要想编辑这个文件，得有root权限&lt;/p&gt;  &lt;p&gt;0 7&amp;#160;&amp;#160; *&amp;#160;&amp;#160;&amp;#160; *&amp;#160;&amp;#160; *&amp;#160;&amp;#160;&amp;#160; root&amp;#160;&amp;#160;&amp;#160; mpg123 ~/wakeup.mp3    &lt;br /&gt;分 时 日 月 周&lt;/p&gt;  &lt;p&gt;示例：&lt;/p&gt;  &lt;p&gt;0 4&amp;#160; * * 0&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;strong&gt;root&lt;/strong&gt; &lt;strong&gt;emerge &lt;/strong&gt;--sync &amp;amp;&amp;amp; emerge -uD world&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; #每周日凌晨4点，更新系统     &lt;br /&gt;0 2 1 * *&amp;#160;&amp;#160;&amp;#160;&amp;#160; root&amp;#160;&amp;#160; &lt;strong&gt;rm&lt;/strong&gt; -f /tmp/*&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; #每月1号凌晨2点，清理/tmp下的文件     &lt;br /&gt;0 8 6 5 *&amp;#160;&amp;#160; root&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;strong&gt;mail&lt;/strong&gt;&amp;#160; robin &amp;lt; /home/galeki/happy.txt&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; #每年5月6日给robin发信祝他生日快乐&lt;/p&gt;  &lt;p&gt;假如，我想每隔2分钟就要执行某个命令，或者我想在每天的6点、12点、18点执行命令，诸如此类的周期，可以通过 “ / ” 和 “ , ” 来设置：&lt;/p&gt;  &lt;p&gt;*/2&amp;#160;&amp;#160; *&amp;#160;&amp;#160; *&amp;#160;&amp;#160; *&amp;#160;&amp;#160; *&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; root&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ...............&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; #每两分钟就执行........    &lt;br /&gt;0 6,12,18&amp;#160;&amp;#160; *&amp;#160;&amp;#160; *&amp;#160;&amp;#160; *&amp;#160;&amp;#160;&amp;#160; root&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ...............&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; #每天6点、12点、18点执行........&lt;/p&gt;  &lt;p&gt;每两个小时&lt;/p&gt;  &lt;p&gt;0 */2 * * * &lt;strong&gt;echo&lt;/strong&gt; &amp;quot;have a break now.&amp;quot; &amp;gt;&amp;amp;gt; /tmp/test.txt&lt;/p&gt;  &lt;p&gt;晚上11点到早上8点之间每两个小时，早上八点&lt;/p&gt;  &lt;p&gt;0 23-7/2，8 * * * echo &amp;quot;have a good dream：）&amp;quot; &amp;amp;gt;&amp;amp;gt; /tmp/test.txt&lt;/p&gt;  &lt;p&gt;每个月的4号与每个礼拜的礼拜一到礼拜三的早上11点&lt;/p&gt;  &lt;p&gt;0 11 4 * 1-3 command line&lt;/p&gt;  &lt;p&gt;1月1日早上4点&lt;/p&gt;  &lt;p&gt;0 4 1 1 * command line&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;cron 执行PHP的方法 &lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;要用 crontab 自動執行 php 程式，可以這樣做：    &lt;br /&gt;方法一     &lt;br /&gt;1. 在 php 程式的第一行加入：     &lt;br /&gt;#!/usr/local/php/bin/php -q     &lt;br /&gt;例如：&lt;/p&gt;  &lt;p&gt;Php代码 &lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;#!/usr/local/php/bin/php -q&amp;#160; &lt;/li&gt;    &lt;li&gt;&amp;lt;?php&amp;#160; &lt;/li&gt;    &lt;li&gt;$foo = 123;&amp;#160; &lt;/li&gt;    &lt;li&gt;?&amp;gt;&amp;#160;&amp;#160; &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;請留意，我的 php 是安裝在 /usr/local/php，請根據你的 php 執行檔位置作出修改。    &lt;br /&gt;2. 將 php 程式給予可執行權限：     &lt;br /&gt;chmod +x testing.php     &lt;br /&gt;3. 執行 crontab -e，然後加入以下內容：     &lt;br /&gt;00 00 * * * /path/to/testing.php &amp;gt; /dev/null 2&amp;gt;&amp;amp;2     &lt;br /&gt;以上語法會在每天的零時零分執行 /path/to/testing.php     &lt;br /&gt;方法二     &lt;br /&gt;另一個方法是不用在 php 程式的第一行加入 &amp;quot;#!/usr/local/php/bin/php -q&amp;quot;，可以省略第一步及第二步，直接執行 crontab -e，並輸入以下內容：     &lt;br /&gt;00 00 * * * usr/local/php/bin/php -q /path/to/testing.php &amp;gt; /dev/null 2&amp;gt;&amp;amp;2     &lt;br /&gt;這個方法的結果跟方法一的結果相同。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/OtisBlog/aggbug/2332175.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/OtisBlog/archive/2012/01/30/2332175.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/OtisBlog/archive/2010/04/30/1724577.html</id><title type="text">为您的.NET网站增加OpenID,Window Live,人人网等多种登录方式之一: 增加OpenID登录</title><summary type="text">OpenID在国外很流行. 在国内就不怎么样了.. 很多网站,论坛都不支持. 经常在网上逛的人,几乎都要注册很多帐号,记很多密码. 或者是帐号和密码都设定一样.呵. 我在想,如果国内大量的论坛都支持OpenID登录,那么,将会多爽!  不了解OpenID的朋友可以看中文,或英文http://www.openid.net 的介绍.  本人最近做的一个网站( http://www.86e0.com )...</summary><published>2010-04-29T16:13:00Z</published><updated>2010-04-29T16:13:00Z</updated><author><name>Otis's Technology Space</name><uri>http://www.cnblogs.com/OtisBlog/</uri></author><link rel="alternate" href="http://www.cnblogs.com/OtisBlog/archive/2010/04/30/1724577.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/OtisBlog/archive/2010/04/30/1724577.html"/><content type="html">&lt;p&gt;OpenID在国外很流行. 在国内就不怎么样了.. 很多网站,论坛都不支持. 经常在网上逛的人,几乎都要注册很多帐号,记很多密码. 或者是帐号和密码都设定一样.呵. 我在想,如果国内大量的论坛都支持OpenID登录,那么,将会多爽!&lt;/p&gt;  &lt;p&gt;不了解OpenID的朋友可以看&lt;a href="http://openid.net.cn/" target="_blank"&gt;中文&lt;/a&gt;,或英文&lt;a href="http://www.openid.net"&gt;http://www.openid.net&lt;/a&gt; 的介绍.&lt;/p&gt;  &lt;p&gt;本人最近做的一个网站( &lt;a href="http://www.86e0.com"&gt;http://www.86e0.com&lt;/a&gt; ) 有用到OpenID的登录(当然还有其它的登录方式,慢慢会说到). 一开始我也是狂找资料, 中文的,英文的都找过了.可惜的是,资料少得很. 下面总结一些经验和分享一些代码.&lt;/p&gt;  &lt;p&gt;.NET下使用OpenID,首先要去下载一个第三方组件:dotnetopenauth. 网址为: &lt;a href="http://www.dotnetopenauth.net/"&gt;http://www.dotnetopenauth.net/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;压缩包里会有示例. 由于我的项目是用Asp.NET MVC2,所以我直接看OpenIdRelyingPartyMvc 这个示例. 示例是Asp.net MVC1.0版的.很快我们就可以找出他的关键代码:   &lt;br /&gt;HTML为:&lt;/p&gt;  &lt;pre &gt;&amp;lt;form action=&amp;quot;Authenticate?ReturnUrl=&amp;lt;%=HttpUtility.UrlEncode(Request.QueryString[&amp;quot;ReturnUrl&amp;quot;]) %&amp;gt;&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;&#xD;
	&amp;lt;label for=&amp;quot;openid_identifier&amp;quot;&amp;gt;OpenID: &amp;lt;/label&amp;gt;&#xD;
	&amp;lt;input id=&amp;quot;openid_identifier&amp;quot; name=&amp;quot;openid_identifier&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;&#xD;
	&amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Login&amp;quot; /&amp;gt;&#xD;
	&amp;lt;/form&amp;gt;&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;Action为:&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;[ValidateInput(false)]&#xD;
		public ActionResult Authenticate(string returnUrl) {&#xD;
			var response = openid.GetResponse();&#xD;
			if (response == null) {&#xD;
				// Stage 2: user submitting Identifier&#xD;
				Identifier id;&#xD;
				if (Identifier.TryParse(Request.Form[&amp;quot;openid_identifier&amp;quot;], out id)) {&#xD;
					try {&#xD;
						return openid.CreateRequest(Request.Form[&amp;quot;openid_identifier&amp;quot;]).RedirectingResponse.AsActionResult();&#xD;
					} catch (ProtocolException ex) {&#xD;
						ViewData[&amp;quot;Message&amp;quot;] = ex.Message;&#xD;
						return View(&amp;quot;Login&amp;quot;);&#xD;
					}&#xD;
				} else {&#xD;
					ViewData[&amp;quot;Message&amp;quot;] = &amp;quot;Invalid identifier&amp;quot;;&#xD;
					return View(&amp;quot;Login&amp;quot;);&#xD;
				}&#xD;
			} else {&#xD;
				// Stage 3: OpenID Provider sending assertion response&#xD;
				switch (response.Status) {&#xD;
					case AuthenticationStatus.Authenticated:&#xD;
						Session[&amp;quot;FriendlyIdentifier&amp;quot;] = response.FriendlyIdentifierForDisplay;&#xD;
						FormsAuthentication.SetAuthCookie(response.ClaimedIdentifier, false);&#xD;
						if (!string.IsNullOrEmpty(returnUrl)) {&#xD;
							return Redirect(returnUrl);&#xD;
						} else {&#xD;
							return RedirectToAction(&amp;quot;Index&amp;quot;, &amp;quot;Home&amp;quot;);&#xD;
						}&#xD;
					case AuthenticationStatus.Canceled:&#xD;
						ViewData[&amp;quot;Message&amp;quot;] = &amp;quot;Canceled at provider&amp;quot;;&#xD;
						return View(&amp;quot;Login&amp;quot;);&#xD;
					case AuthenticationStatus.Failed:&#xD;
						ViewData[&amp;quot;Message&amp;quot;] = response.Exception.Message;&#xD;
						return View(&amp;quot;Login&amp;quot;);&#xD;
				}&#xD;
			}&#xD;
			return new EmptyResult();&#xD;
		}&#xD;
	}&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;&amp;#160;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;最后在HomeController 的Index Action(就是主页)增加 X-XRDS-Location 的Header. Xrds Action是输出上面的Xrds View.如下: 其中请注意xrds的地址. 代码如下.&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;public class HomeController : Controller {&#xD;
		public ActionResult Index() {&#xD;
			Response.AppendHeader(&#xD;
				&amp;quot;X-XRDS-Location&amp;quot;,&#xD;
				new Uri(Request.Url, Response.ApplyAppPathModifier(&amp;quot;~/Home/xrds&amp;quot;)).AbsoluteUri);&#xD;
			return View(&amp;quot;Index&amp;quot;);&#xD;
		}&#xD;
&#xD;
		public ActionResult Xrds() {&#xD;
			return View(&amp;quot;Xrds&amp;quot;);&#xD;
		}&#xD;
	}&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;&amp;#160;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;XRDS 的View为: &lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&amp;lt;%@ Page Language=&amp;quot;C#&amp;quot; Inherits=&amp;quot;System.Web.Mvc.ViewPage&amp;quot; ContentType=&amp;quot;application/xrds+xml&amp;quot; %&amp;gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&#xD;
&amp;lt;%--&#xD;
This page is a required for relying party discovery per OpenID 2.0.&#xD;
It allows Providers to call back to the relying party site to confirm the&#xD;
identity that it is claiming in the realm and return_to URLs.&#xD;
This page should be pointed to by the 'realm' home page, which in this sample&#xD;
is default.aspx.&#xD;
--%&amp;gt;&#xD;
&amp;lt;xrds:XRDS&#xD;
	xmlns:xrds=&amp;quot;xri://$xrds&amp;quot;&#xD;
	xmlns:openid=&amp;quot;http://openid.net/xmlns/1.0&amp;quot;&#xD;
	xmlns=&amp;quot;xri://$xrd*($v*2.0)&amp;quot;&amp;gt;&#xD;
	&amp;lt;XRD&amp;gt;&#xD;
		&amp;lt;Service priority=&amp;quot;1&amp;quot;&amp;gt;&#xD;
			&amp;lt;Type&amp;gt;http://specs.openid.net/auth/2.0/return_to&amp;lt;/Type&amp;gt;&#xD;
			&amp;lt;%-- Every page with an OpenID login should be listed here. --%&amp;gt;&#xD;
			&amp;lt;%-- We use the Authenticate action instead of Login because Authenticate&#xD;
			     is the action that receives OpenId assertions. --%&amp;gt;&#xD;
			&amp;lt;URI&amp;gt;&amp;lt;%=new Uri(Request.Url, Response.ApplyAppPathModifier(&amp;quot;~/user/authenticate&amp;quot;))%&amp;gt;&amp;lt;/URI&amp;gt;&#xD;
		&amp;lt;/Service&amp;gt;&#xD;
	&amp;lt;/XRD&amp;gt;&#xD;
&amp;lt;/xrds:XRDS&amp;gt;&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;&amp;#160;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;这样就OK啰. 这只是简单的用法. 因为这个只返回很少信息.&amp;#160; 一般只有两个,一个是:FriendlyIdentifierForDisplay ,就是用户名,一个是ClaimedIdentifier, 是用户的标识. 如果是这样用就OK,那我这文章也写得没什么意义了.呵. 因为一般我们还要抓到用户的Email,和个性图标.等等一些有用的东西.但是默认的是不返回的.&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;先看看可以返回什么信息. DotNetOpenAuth中有一个WellKnownAttributes 类, 这个类中定义了一系列可以返回的信息. 下面是这个类的抓图:&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/OtisBlog/WindowsLiveWriter/OpenIDWindowLiveOpenID_12BF5/image_7001c58b-da45-48f9-ade4-ccb3a348aa4a.png" width="540" height="725" /&gt; &lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;如何获取这些信息呢? 请看下面的示例代码 :&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;[AcceptVerbs(HttpVerbs.Post)]&#xD;
        public ActionResult Login(string openid_identifier)&#xD;
        {&#xD;
            try&#xD;
            {&#xD;
                var openid = new OpenIdRelyingParty();&#xD;
                IAuthenticationRequest request = openid.CreateRequest(Identifier.Parse(openid_identifier));&#xD;
&#xD;
&#xD;
                var fetch = new FetchRequest();&#xD;
                fetch.Attributes.AddRequired(WellKnownAttributes.Contact.Email);&#xD;
                fetch.Attributes.AddRequired(WellKnownAttributes.Name.Alias);&#xD;
                fetch.Attributes.AddRequired(WellKnownAttributes.Name.FullName);&#xD;
                fetch.Attributes.AddRequired(WellKnownAttributes.Media.Images.Default);&#xD;
                request.AddExtension(fetch);&#xD;
               &#xD;
&#xD;
                /*&#xD;
                request.AddExtension(new ClaimsRequest&#xD;
                {&#xD;
                    Email = DemandLevel.Require,&#xD;
                    FullName = DemandLevel.Require,&#xD;
                    Nickname = DemandLevel.Require&#xD;
                });*/&#xD;
                return request.RedirectingResponse.AsActionResult();&#xD;
            }&#xD;
            catch&#xD;
            {&#xD;
                ViewData[&amp;quot;ErrorMessage&amp;quot;] = &amp;quot;您输入的OpenID不正确或您的帐号的提供商不提供OpenID服务&amp;quot;;&#xD;
                &#xD;
                ViewData[&amp;quot;OpenIDLoginURL&amp;quot;] = openid_identifier;&#xD;
                return View();&#xD;
            }&#xD;
        }&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;这样创建请求就可以成功获取你想要的信息了, 这里是请求获取 Email, 姓名, 个性图标.&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;注意我注释了的代码, 一开始我也用这样,但是,这个无法获取个性图标.&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;最后,最后很关键喔.. 配置文件!! 对.. 一开始我因为没注意这个,花了不少时间.. ======&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://www.86e0.com"&gt;http://www.86e0.com&lt;/a&gt; 用的配置文件如下,基本是抄OpenIdRelyingPartyMvc 这个示例的.&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&amp;lt;dotNetOpenAuth&amp;gt;&#xD;
    &amp;lt;openid&amp;gt;&#xD;
      &amp;lt;relyingParty&amp;gt;&#xD;
        &amp;lt;security requireSsl=&amp;quot;false&amp;quot; /&amp;gt;&#xD;
        &amp;lt;behaviors&amp;gt;&#xD;
          &amp;lt;!-- The following OPTIONAL behavior allows RPs to use SREG only, but be compatible&#xD;
								 with OPs that use Attribute Exchange (in various formats). --&amp;gt;&#xD;
          &amp;lt;add type=&amp;quot;DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform, DotNetOpenAuth&amp;quot; /&amp;gt;&#xD;
        &amp;lt;/behaviors&amp;gt;&#xD;
      &amp;lt;/relyingParty&amp;gt;&#xD;
    &amp;lt;/openid&amp;gt;&#xD;
    &amp;lt;messaging&amp;gt;&#xD;
      &amp;lt;untrustedWebRequest&amp;gt;&#xD;
        &amp;lt;whitelistHosts&amp;gt;&#xD;
          &amp;lt;!-- since this is a sample, and will often be used with localhost --&amp;gt;&#xD;
          &amp;lt;add name=&amp;quot;localhost&amp;quot; /&amp;gt;&#xD;
        &amp;lt;/whitelistHosts&amp;gt;&#xD;
      &amp;lt;/untrustedWebRequest&amp;gt;&#xD;
    &amp;lt;/messaging&amp;gt;&#xD;
    &amp;lt;!-- Allow DotNetOpenAuth to publish usage statistics to library authors to improve the library. --&amp;gt;&#xD;
    &amp;lt;reporting enabled=&amp;quot;false&amp;quot; /&amp;gt;&#xD;
  &amp;lt;/dotNetOpenAuth&amp;gt;&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;&amp;#160;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;好了,现在基本没问题了.&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;剩下就是在登录成功后获取这些信息了. 相关的代码如下:&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&amp;#160;&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;switch (response.Status) {&#xD;
					case AuthenticationStatus.Authenticated:&#xD;
						string nickName = response.FriendlyIdentifierForDisplay;&#xD;
                            if (string.IsNullOrEmpty(nickName)) nickName = &amp;quot;匿名用户&amp;quot;;&#xD;
                            string email = string.Empty;&#xD;
                            string picIcon = string.Empty;&#xD;
&#xD;
                            if (nickName.Length &amp;gt; 50) { nickName = nickName.Substring(0, 50); }&#xD;
&#xD;
                            var claim = response.GetExtension&amp;lt;ClaimsResponse&amp;gt;();&#xD;
                            var fetch = response.GetExtension&amp;lt;FetchResponse&amp;gt;();&#xD;
                           &#xD;
                            string picKey = WellKnownAttributes.Media.Images.Default;&#xD;
&#xD;
                            if (fetch !=null &amp;amp;&amp;amp; fetch.Attributes != null &amp;amp;&amp;amp; fetch.Attributes.Contains(picKey))&#xD;
                            {&#xD;
                                var picAttr = fetch.Attributes[picKey];&#xD;
                                if (picAttr != null &amp;amp;&amp;amp; picAttr.Values.Count &amp;gt; 0) { picIcon = picAttr.Values[0]; }&#xD;
                            }&#xD;
							 if (claim != null)&#xD;
                            {&#xD;
                                nickName = claim.Nickname;&#xD;
&#xD;
                                if (string.IsNullOrEmpty(nickName))&#xD;
                                {&#xD;
                                    int ttIndex = claim.Email.IndexOf(&amp;quot;@&amp;quot;);&#xD;
                                    if (ttIndex &amp;gt; 0)&#xD;
                                    {&#xD;
                                        nickName = claim.Email.Substring(0, ttIndex);&#xD;
                                    }&#xD;
                                    else&#xD;
                                    {&#xD;
                                        nickName = claim.Email;&#xD;
                                    }&#xD;
                                }&#xD;
                                email = claim.Email;&#xD;
                            }&#xD;
// 最后授权,入库等.&#xD;
					case AuthenticationStatus.Canceled:&#xD;
						ViewData[&amp;quot;Message&amp;quot;] = &amp;quot;Canceled at provider&amp;quot;;&#xD;
						return View(&amp;quot;Login&amp;quot;);&#xD;
					case AuthenticationStatus.Failed:&#xD;
						ViewData[&amp;quot;Message&amp;quot;] = response.Exception.Message;&#xD;
						return View(&amp;quot;Login&amp;quot;);&#xD;
				}&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;&amp;#160;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;OK了. 上面的这么多&amp;#160; if是因为抓出来的资料会有 null的情况.. 这个应该是用户没设定那些资料.&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;最后,个人博客的话, 不用这么麻烦,比如说老赵的个人博客,直接用&lt;a title="https://rpxnow.com/" href="https://rpxnow.com/"&gt;https://rpxnow.com/&lt;/a&gt;的服务就好了.呵.&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;感兴趣的朋友欢迎去&lt;a href="http://www.86e0.com"&gt;http://www.86e0.com&lt;/a&gt; 体验. &lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;这个系列应该会写三四个. 第二个应该是加入Window live 的登录. 因为Live官方的OpenID登录还在开发中.. 所以不得不用 live sdk 的方式去做. &lt;/p&gt;&lt;img src="http://www.cnblogs.com/OtisBlog/aggbug/1724577.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/OtisBlog/archive/2010/04/30/1724577.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/OtisBlog/archive/2010/04/29/1723895.html</id><title type="text">淘优惠上线测试！</title><summary type="text">淘优惠简介：  你是否每天都在关注淘宝促销频道和paipai的秒杀呢？ 你是否会因为抢不到某样促销商品而感到可惜？ 其实，淘宝网上的优惠商品数目非常庞大，几乎你想要买的商品，都可以在任何时间内找到优惠信息，显示在淘宝促销频道上的只是很小一部分而已！ 淘优惠，就是能让你轻松找到大量优惠商品的工具！抢不到商品，没关系，用淘优惠搜一搜，或许能给你惊喜！买东西时也用淘优惠搜一搜，你会发现有更多更好的选择！...</summary><published>2010-04-29T07:01:00Z</published><updated>2010-04-29T07:01:00Z</updated><author><name>Otis's Technology Space</name><uri>http://www.cnblogs.com/OtisBlog/</uri></author><link rel="alternate" href="http://www.cnblogs.com/OtisBlog/archive/2010/04/29/1723895.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/OtisBlog/archive/2010/04/29/1723895.html"/><content type="html">&lt;p&gt;&lt;strong&gt;淘优惠简介：&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;你是否每天都在关注淘宝促销频道和paipai的秒杀呢？ &lt;/p&gt;  &lt;p&gt;你是否会因为抢不到某样促销商品而感到可惜？ &lt;/p&gt;  &lt;p&gt;其实，淘宝网上的优惠商品数目非常庞大，几乎你想要买的商品，都可以在任何时间内找到优惠信息，显示在淘宝促销频道上的只是很小一部分而已！ &lt;/p&gt;  &lt;p&gt;淘优惠，就是能让你轻松找到大量优惠商品的工具！抢不到商品，没关系，用淘优惠搜一搜，或许能给你惊喜！买东西时也用淘优惠搜一搜，你会发现有更多更好的选择！ &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;淘优惠特色功能：&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;一键搜索淘宝网所有优惠商品，包括包邮、打折销售、特价销售、特惠销售、特卖展销、普通促销、冲钻促销、冲皇促销、开业促销、疯狂秒杀和淘宝批发等，并自动把搜索到的优惠商品按人气、信用、价格排序，供您挑选。 &lt;/li&gt;    &lt;li&gt;可使用信用范围，价格，区域，是否有正品保障，分类等等过虑功能筛选商品，搜索结果除一般信息外还显示商品30天销量和掌柜信用，让你更快做出选择。 &lt;/li&gt;    &lt;li&gt;采用后台自动预先加载的方式，动画滚动方式浏览商品；点商品图片可在页内直接查看宝贝，店铺信息，无需来回切换窗口，带给你更舒服，流畅的购物体验。 &lt;/li&gt;    &lt;li&gt;自动保存你常用的分类，带搜的关键字，让你搜索宝贝时更方便！ &lt;/li&gt;    &lt;li&gt;贴心的暂存架功能。看到有喜欢的商品，但还想找更好的怎么办？ 将它加放暂存架吧！之后再从暂存架中再挑选！暂存架也是在内页直接显示的喔，无跳页！为了提升搜索和购物体验，我们做了很多考虑，查了很多技术，花了大量的时间！ &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;以下为用淘优惠查询n97 mini的优惠商品的结果. 和淘宝对比:&lt;/p&gt;  &lt;div&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="" border="0" alt="" src="http://images.cnblogs.com/cnblogs_com/OtisBlog/WindowsLiveWriter/a544e353ffb6_129D3/image_7016c37d-5757-4bb5-9fd6-511b81b1d88a.png" width="721" height="361" /&gt; &lt;/div&gt;  &lt;p&gt;如上图选择排序为人气从高到低,分类为手机,关键字为n97 mini,类型为全部的结果如下图:&lt;/p&gt;  &lt;div&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="" border="0" alt="" src="http://images.cnblogs.com/cnblogs_com/OtisBlog/WindowsLiveWriter/a544e353ffb6_129D3/image3.png" width="971" height="703" /&gt;     &lt;p&gt;&lt;/p&gt;    &lt;p&gt;淘宝的结果如下: &lt;/p&gt; &lt;/div&gt;  &lt;div&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="" border="0" alt="" src="http://images.cnblogs.com/cnblogs_com/OtisBlog/WindowsLiveWriter/a544e353ffb6_129D3/image11.png" width="753" height="732" /&gt; &lt;/div&gt;  &lt;p&gt;可以看出,淘优惠是老老实实地把结果显示出来了. 而淘宝的,是经过优化的最好的结果. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;淘优惠网址: &lt;a href="http://www.86e0.com/taoyouhui"&gt;http://www.86e0.com/taoyouhui&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/OtisBlog/aggbug/1723895.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/OtisBlog/archive/2010/04/29/1723895.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/OtisBlog/archive/2010/04/29/1723832.html</id><title type="text">导购频道全新改版并改名为快乐淘宝！</title><summary type="text">前几天看到淘宝开放平台的公告说Top已经升级到2.0,而且1.0版将要废了! 接着就马上发现了top4net2.0的发布信息!  因为导购频道(现在是快乐淘宝了)用的是1.0的Top, 因为当时top4net一直都是1.0版. 淘优惠也是用1.0版的.所以就很悲剧中.  终于,经过几天几夜的奋斗,导购频道全新改版了!!  考虑到&amp;quot;导购频道&amp;quot;这个名称太平凡,还有就是总站名为&amp;qu...</summary><published>2010-04-29T06:26:00Z</published><updated>2010-04-29T06:26:00Z</updated><author><name>Otis's Technology Space</name><uri>http://www.cnblogs.com/OtisBlog/</uri></author><link rel="alternate" href="http://www.cnblogs.com/OtisBlog/archive/2010/04/29/1723832.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/OtisBlog/archive/2010/04/29/1723832.html"/><content type="html">&lt;p&gt;前几天看到淘宝开放平台的公告说Top已经升级到2.0,而且1.0版将要废了! 接着就马上发现了top4net2.0的发布信息!&lt;/p&gt;  &lt;p&gt;因为导购频道(现在是快乐淘宝了)用的是1.0的Top, 因为当时top4net一直都是1.0版. 淘优惠也是用1.0版的.所以就很悲剧中.&lt;/p&gt;  &lt;p&gt;终于,经过几天几夜的奋斗,导购频道全新改版了!!&lt;/p&gt;  &lt;p&gt;考虑到&amp;quot;导购频道&amp;quot;这个名称太平凡,还有就是总站名为&amp;quot;快乐E行&amp;quot;.所以就起了一个现在相当火的名字:快乐淘宝.&lt;/p&gt;  &lt;p&gt;这次升级是N多功能了. 以下是最重要的:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;1.商品搜索和筛选功能统一了. &lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;之前是先搜索,然后下面有个筛选区域可以进一步筛选商品. 比如我搜索&amp;quot;连衣裙&amp;quot;:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="" border="0" alt="" src="http://images.cnblogs.com/cnblogs_com/OtisBlog/WindowsLiveWriter/e55ce14d7c4a_121C9/image_3.png" width="695" height="93" /&gt; &lt;/p&gt;  &lt;p&gt;列出相关商品后,下面再可以筛选,排序等.&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="" border="0" alt="" src="http://images.cnblogs.com/cnblogs_com/OtisBlog/WindowsLiveWriter/e55ce14d7c4a_121C9/image_6681c4cc-f10e-4c3e-8952-441d78ab2b05.png" width="719" height="233" /&gt; &lt;/p&gt;  &lt;p&gt;现在统一了,并且不用进&amp;quot;打折销售&amp;quot;栏(现在是:秒杀/特价/促销) 就可以直接查询 秒杀,特价等优惠商品. 如图.&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="" border="0" alt="" src="http://images.cnblogs.com/cnblogs_com/OtisBlog/WindowsLiveWriter/e55ce14d7c4a_121C9/image_ad645210-b430-4e6a-b18e-1ad7f3d9a560.png" width="782" height="203" /&gt; &lt;/p&gt;  &lt;p&gt;还增加了保存常用分类和搜关键字的功能.如图:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/OtisBlog/WindowsLiveWriter/e55ce14d7c4a_121C9/image_8a472998-11c3-43cb-9275-4cdd72c9be7a.png" width="636" height="364" /&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2.增加了只查询某一掌柜商品的功能. &lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;有些朋友可能只喜欢去熟悉的掌柜购物. 现增加了这个功能,此外还增加了自动保存您常去的店铺的功能. 如图:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/OtisBlog/WindowsLiveWriter/e55ce14d7c4a_121C9/image_ad976977-d545-4221-9421-d175a654dbfa.png" width="685" height="332" /&gt; &lt;/p&gt;  &lt;p&gt;此外:还可快速搜寻该掌柜下秒杀,特价,包邮和促销商品. 如图为搜寻&amp;quot;&lt;a href="http://www.86e0.com/t/shop?nick=%E6%B0%94%E8%B4%A8%E6%B7%91%E5%A5%B3&amp;amp;key=&amp;amp;yh=tejia&amp;amp;sort=volume:desc&amp;amp;start_price=&amp;amp;end_price=" target="_blank"&gt;气质淑女&lt;/a&gt;&amp;quot; 掌柜下的所有特价商品:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/OtisBlog/WindowsLiveWriter/e55ce14d7c4a_121C9/image_879ee596-dd51-4454-a233-4321dff4ab4b.png" width="697" height="547" /&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;3.改进了排版,优化了速度. 新版比旧版更易用,速度更快了.还有N处小改进. &lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;86E0网址: &lt;a href="http://www.86e0.com/t" target="_blank"&gt;快乐淘宝-快乐E行&lt;/a&gt; (&lt;a href="http://www.86e0.com/t"&gt;http://www.86e0.com/t&lt;/a&gt;)&lt;/p&gt;&lt;img src="http://www.cnblogs.com/OtisBlog/aggbug/1723832.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/OtisBlog/archive/2010/04/29/1723832.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/OtisBlog/archive/2010/03/22/1691676.html</id><title type="text">Asp.net MVC2 使用经验，性能优化建议</title><summary type="text">这个月一直在用 asp.net MVC2 做http://www.86e0.com/t 这个网站，用的时候是 aps.net MVC2 RC2,然后现在Asp.net MVC2正式版已经是发布了。 在MVC的使用上，有一些心得。下面作一下总结，希望对大家有用，也欢迎大家讨论。1.关于缓存缓存上，数据层上的缓存是必须的，这点不必多说了。另一个很重要的是：视图片段缓存。我参考了老赵的写的三篇关于片段缓...</summary><published>2010-03-22T07:51:00Z</published><updated>2010-03-22T07:51:00Z</updated><author><name>Otis's Technology Space</name><uri>http://www.cnblogs.com/OtisBlog/</uri></author><link rel="alternate" href="http://www.cnblogs.com/OtisBlog/archive/2010/03/22/1691676.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/OtisBlog/archive/2010/03/22/1691676.html"/><content type="html">&lt;p&gt;这个月一直在用 asp.net MVC2 做&lt;a href="http://www.86e0.com/t"&gt;http://www.86e0.com/t&lt;/a&gt; 这个网站，用的时候是 aps.net MVC2 RC2,然后现在Asp.net MVC2正式版已经是发布了。 在MVC的使用上，有一些心得。下面作一下总结，希望对大家有用，也欢迎大家讨论。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;strong&gt;1.关于缓存&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;缓存上，数据层上的缓存是必须的，这点不必多说了。&lt;/p&gt;&#xD;
&lt;p&gt;另一个很重要的是：视图片段缓存。&lt;/p&gt;&#xD;
&lt;p&gt;我参考了老赵的写的三篇关于片段缓存的文章：&lt;/p&gt;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;&lt;a href="http://www.cnblogs.com/JeffreyZhao/archive/2009/09/17/aspnet-mvc-fragment-cache-1.html"&gt;适合ASP.NET MVC的视图片断缓存方式（上）：起步&lt;/a&gt; &lt;/li&gt;&#xD;
&lt;li&gt;适合ASP.NET MVC的视图片断缓存方式（中）：更实用的API &lt;/li&gt;&#xD;
&lt;li&gt;&lt;a href="http://www.cnblogs.com/JeffreyZhao/archive/2009/09/22/aspnet-mvc-fragment-cache-3-rendering-principle.html"&gt;适合ASP.NET MVC的视图片断缓存方式（下）：页面输出原则&lt;/a&gt; &lt;/li&gt;&#xD;
&lt;/ul&gt;&#xD;
&lt;p&gt;本想用老赵的了，但是我发现Asp.net MVC2 的有一个新功能： Html.Partial可以返回生成的HTML, 返回的类型是：MvcHtmlString. 虽然要利用Partial View才能生成Html片段，但是我想这个已经够我用的了， 所以我做了一个这样一个Helper，主要是将生成的HTML片段缓存到Memcached里。代码如下：&lt;/p&gt;&#xD;
&lt;pre &gt;public static class MvcHtmlHelper&#xD;
    {&#xD;
         public static MvcHtmlString MemcacheHtmlPartial(this HtmlHelper htmlHelper,int duration, string partialViewName, object model, ViewDataDictionary viewData)&#xD;
        {&#xD;
            object obaear = htmlHelper.ViewContext.RouteData.DataTokens["area"];&#xD;
              string area=string.Empty;&#xD;
              if (obaear != null) area = obaear.ToString();&#xD;
            string key = string.Format("MemcacheHtmlPartial_{0}{1}", area, partialViewName);&#xD;
            object ob = DistCache.Get(key);&#xD;
            if (ob == null)&#xD;
            {&#xD;
                MvcHtmlString mstr = htmlHelper.Partial(partialViewName, model, viewData);&#xD;
                DistCache.Add(key, mstr.ToString(), TimeSpan.FromSeconds(duration));&#xD;
                return mstr;&#xD;
            }&#xD;
            else&#xD;
            {&#xD;
                 return MvcHtmlString.Create((string)ob);&#xD;
            }&#xD;
        }&#xD;
}&lt;/pre&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;然后，我觉得，这样，在每次请求时，还是要在Controller 里把数据取出来，然后再传到 Partial View里。 既然已经缓存了，就应该不用每次请求都要在Controller里把数据取出来才对！虽然数据层会有缓存。&lt;/p&gt;&#xD;
&lt;p&gt;所以我，能不能再省下去Controller取数据的消耗，于是又有了以下代码，其功能是：缓存Action生成的HTML到Memcached里。&lt;/p&gt;&#xD;
&lt;pre &gt;public static MvcHtmlString MemcacheHtmlRenderAction(this HtmlHelper htmlHelper, int duration, string actionName,string controllerName, RouteValueDictionary routeValues)&#xD;
          {&#xD;
              object obaear = htmlHelper.ViewContext.RouteData.DataTokens["area"];&#xD;
              string area = string.Empty;&#xD;
              if (obaear != null) area = obaear.ToString();&#xD;
              string key = string.Format("MemcacheHtmlRenderAction_{0}{1}{2}", area, controllerName,actionName);&#xD;
              object ob = DistCache.Get(key);&#xD;
              if (ob == null)&#xD;
              {&#xD;
                  &#xD;
                 // htmlHelper.RenderAction(actionName, controllerName, routeValues);&#xD;
                  StringWriter writer = new StringWriter(CultureInfo.CurrentCulture);&#xD;
                  ActionHelper(htmlHelper, actionName, controllerName, routeValues, writer);&#xD;
                  string wStr = writer.ToString();&#xD;
                  DistCache.Add(key, wStr,TimeSpan.FromSeconds(duration));&#xD;
                  MvcHtmlString mstr = MvcHtmlString.Create(wStr);&#xD;
                  &#xD;
                  return mstr;&#xD;
              }&#xD;
              else { return MvcHtmlString.Create((string)ob); }&#xD;
          }&lt;/pre&gt;&#xD;
&lt;p&gt;说明一下，Actionhelper的方法是在MVC原代码里提取出来的。 因为MVC2里的 Html.RenderAction方法并没有返回 MvcHtmlString的重载版。那位有更好的方法？&lt;/p&gt;&#xD;
&lt;p&gt;其实，MVC里的Action有输出缓存，所以直接在View里用 Html.RenderAction都可以解决很多问题了。这个主要是可以用程序管理缓存。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;strong&gt;2.关于静态内容的放置&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;习惯上，静态内容会放在 mvc程序所在的目录下，比如说js,css,上传的图片等。但是这样的话，所有的静态请求都要经过 aspnet_isapi 处理，这样是非常不合算的。所以静态内容一般都会放在另外的子域上。&lt;a href="http://www.86e0.com/t"&gt;http://www.86e0.com/t&lt;/a&gt; 是放在 cdn.86e0.com上。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;strong&gt;3.关于强类型ViewModel&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;我基本上看了老赵的Asp.net MVC最佳实践。 其中有一点，就是强烈推荐使用强类型的ViewModel. 我试了一些页面，发现用强类型的ViewModel,现阶段并不适用于我。因为我是用NbearLite,从数据库抓出来的大多是DataTable. 我是觉得DataTable+NbearLite蛮方便的,虽然没有动态语言的数据访问来得方便，但是比用Entity,ViewModel, DTO,等等来说，还是可以省下很多代码。然后，最重要的是，由于我这种站经常会修改，所以数据库改变，加字段，减字段是很经常性的事。但是，用NbearLite + DataSet,DataTable,却非常方便。&lt;/p&gt;&#xD;
&lt;p&gt;所以我觉得，做Asp.net MVC,如果你不是用DDD,DDT的话，用DataTable还是可以的。因为DDD,DDT学习起来还是要点成本的。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;strong&gt;4.关于URL生成&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;URL生成， 老赵写了一系列文章：&lt;/p&gt;&#xD;
&lt;li&gt;&lt;a href="http://www.cnblogs.com/JeffreyZhao/archive/2009/10/30/several-ways-of-generating-url-benchmark.html"&gt;各种URL生成方式的性能对比&lt;/a&gt; &lt;/li&gt;&#xD;
&lt;li&gt;&lt;a href="http://www.cnblogs.com/JeffreyZhao/archive/2009/11/02/several-ways-of-generating-url-benchmark-result.html"&gt;各种URL生成方式的性能对比（结论及分析）&lt;/a&gt; &lt;/li&gt;&#xD;
&lt;li&gt;&lt;a href="http://www.cnblogs.com/JeffreyZhao/archive/2009/11/03/fluent-interface-for-url-generation.html"&gt;为URL生成设计流畅接口（Fluent Interface）&lt;/a&gt; &lt;/li&gt;&#xD;
&lt;li&gt;URL生成方式性能优化结果&#xD;
&lt;p&gt;我直接选择 &lt;/p&gt;&#xD;
&lt;p&gt;Raw方式了， 速度最快的，才是适合我的。呵。 而不是强类型的才是适合我的。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;strong&gt;最后，分享一个很实用的Asp.net MVC 分页Helper.&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这个Helper引自重典老大的blog:&lt;a href="http://www.cnblogs.com/chsword/" title="http://www.cnblogs.com/chsword/"&gt;http://www.cnblogs.com/chsword/&lt;/a&gt; . 我在之前做了少少修改，现已经在&lt;a href="http://www.86e0.com/t"&gt;http://www.86e0.com/t&lt;/a&gt; 上使用了。 &lt;/p&gt;&#xD;
&lt;p&gt;效果如下： &lt;/p&gt;&#xD;
&lt;p&gt;&lt;img height="118" width="555" src="http://images.cnblogs.com/cnblogs_com/OtisBlog/WindowsLiveWriter/b3fdb01651fe_B351/image_b8895a55-4225-4a8d-9703-3236c17ac66b.png" alt="image" border="0" title="image" style="display: inline; border-width: 0px;" /&gt; &lt;/p&gt;&#xD;
&lt;p&gt;请大家注意生成的 URL, 是用 ?参数=页码 的方式。代码如下：&lt;/p&gt;&#xD;
&lt;pre &gt;/// &amp;lt;summary&amp;gt;&#xD;
        /// 分页Pager显示&#xD;
        /// &amp;lt;/summary&amp;gt;&#xD;
        /// &amp;lt;param name="html"&amp;gt;&amp;lt;/param&amp;gt;&#xD;
        /// &amp;lt;param name="currentPageStr"&amp;gt;标识当前页码的QueryStringKey&amp;lt;/param&amp;gt;&#xD;
        /// &amp;lt;param name="pageSize"&amp;gt;每页显示&amp;lt;/param&amp;gt;&#xD;
        /// &amp;lt;param name="totalCount"&amp;gt;总数据量&amp;lt;/param&amp;gt;&#xD;
        /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&#xD;
        public static string Pager(this HtmlHelper html, string currentPageStr, int pageSize, int totalCount)&#xD;
        {&#xD;
            var queryString = html.ViewContext.HttpContext.Request.QueryString;&#xD;
            int currentPage = 1; //当前页&#xD;
            if(!int.TryParse(queryString[currentPageStr], out currentPage)) currentPage = 1; //与相应的QueryString绑定&#xD;
            var totalPages = Math.Max((totalCount + pageSize - 1) / pageSize, 1); //总页数&#xD;
            var dict = new RouteValueDictionary(html.ViewContext.RouteData.Values);&#xD;
&#xD;
            var output = new StringBuilder();&#xD;
&#xD;
            foreach (string key in queryString.Keys)&#xD;
                if (queryString[key] != null &amp;amp;&amp;amp; !string.IsNullOrEmpty(key))&#xD;
                    dict[key] = queryString[key];&#xD;
            if (totalPages &amp;gt; 1)&#xD;
            {&#xD;
                if (currentPage != 1)&#xD;
                {//处理首页连接&#xD;
                    dict[currentPageStr] = 1;&#xD;
                    output.AppendFormat("&amp;lt;span class=\"p_home\"&amp;gt;{0}&amp;lt;/span&amp;gt;", html.RouteLink("首页", dict));&#xD;
                }&#xD;
                if (currentPage &amp;gt; 1)&#xD;
                {//处理上一页的连接&#xD;
                    dict[currentPageStr] = currentPage - 1;&#xD;
                    output.AppendFormat("&amp;lt;span class=\"p_up\"&amp;gt;{0}&amp;lt;/span&amp;gt;", html.RouteLink("上一页", dict));&#xD;
                }&#xD;
                else&#xD;
                {&#xD;
                    output.AppendFormat("&amp;lt;span class=\"p_disable\"&amp;gt;{0}&amp;lt;/span&amp;gt;","上一页");&#xD;
                }&#xD;
                int currint = 5;&#xD;
                for (int i = 0; i &amp;lt;= 10; i++)&#xD;
                {//一共最多显示10个页码，前面5个，后面5个&#xD;
                    if ((currentPage + i - currint) &amp;gt;= 1 &amp;amp;&amp;amp; (currentPage + i - currint) &amp;lt;= totalPages)&#xD;
                        if (currint == i)&#xD;
                        {//当前页处理&#xD;
                            output.Append(string.Format("&amp;lt;span class=\"p_current\"&amp;gt;{0}&amp;lt;/span&amp;gt;", currentPage));&#xD;
                        }&#xD;
                        else&#xD;
                        {//一般页处理&#xD;
                            dict[currentPageStr] = currentPage + i - currint;&#xD;
                            output.AppendFormat("&amp;lt;span class=\"p_num\"&amp;gt;{0}&amp;lt;/span&amp;gt;",html.RouteLink((currentPage + i - currint).ToString(), dict));&#xD;
                        }&#xD;
                }&#xD;
                if (currentPage &amp;lt; totalPages)&#xD;
                {//处理下一页的链接&#xD;
                    dict[currentPageStr] = currentPage + 1;&#xD;
                    output.AppendFormat("&amp;lt;span class=\"p_down\"&amp;gt;{0}&amp;lt;/span&amp;gt;", html.RouteLink("下一页", dict));&#xD;
                }&#xD;
                else&#xD;
                {&#xD;
                    output.AppendFormat("&amp;lt;span class=\"p_disable\"&amp;gt;{0}&amp;lt;/span&amp;gt;", "下一页");&#xD;
                }&#xD;
                if (currentPage != totalPages)&#xD;
                {&#xD;
                    dict[currentPageStr] = totalPages;&#xD;
                    output.AppendFormat("&amp;lt;span class=\"p_last\"&amp;gt;{0}&amp;lt;/span&amp;gt;",html.RouteLink("末页", dict));&#xD;
                }&#xD;
            }&#xD;
            output.AppendFormat("&amp;lt;span class=\"p_count\"&amp;gt;第{0}页/共{1}页&amp;lt;/span&amp;gt;", currentPage, totalPages);//这个统计加不加都行&#xD;
            return output.ToString();&#xD;
        }&lt;/pre&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;另： &lt;a href="http://www.86e0.com/t"&gt;http://www.86e0.com/t&lt;/a&gt; 是做淘宝客类应用的。园子里还有谁在做淘宝客类网站么？ 有的话多交流。^_^&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;/li&gt;&lt;img src="http://www.cnblogs.com/OtisBlog/aggbug/1691676.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/OtisBlog/archive/2010/03/22/1691676.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/OtisBlog/archive/2010/03/01/1675734.html</id><title type="text">log4net使用相关要点汇总</title><summary type="text">1，写log之前一定要初始化配置文档，相关代码如下：  &amp;#160;  2.配置文件样本3. layout节点的配置说明</summary><published>2010-03-01T06:29:00Z</published><updated>2010-03-01T06:29:00Z</updated><author><name>Otis's Technology Space</name><uri>http://www.cnblogs.com/OtisBlog/</uri></author><link rel="alternate" href="http://www.cnblogs.com/OtisBlog/archive/2010/03/01/1675734.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/OtisBlog/archive/2010/03/01/1675734.html"/><content type="html">&lt;p&gt;1，写log之前一定要初始化配置文档，相关代码如下：&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;pre &gt;log4net.Config.XmlConfigurator.Configure(); //默认的 &#xD;
&#xD;
log4net.Config.XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo(System.Web.HttpContext.Current.Server.MapPath(&amp;quot;../Log4Net.config&amp;quot;)));&lt;/pre&gt;&#xD;
&#xD;
&lt;pre &gt;&amp;#160;&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;2.配置文件样本&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;Log4net.config配置文件的内容：&#xD;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&#xD;
&amp;lt;log4net&amp;gt;&#xD;
  &amp;lt;logger name=&amp;quot;KangarooLog&amp;quot;&amp;gt;&#xD;
    &amp;lt;!--control log level: ALL|DEBUG|INFO|WARN|ERROR|FATAL|OFF--&amp;gt;&#xD;
    &amp;lt;!--如果没有定义LEVEL的值，则缺省为DEBUG--&amp;gt;&#xD;
    &amp;lt;level value=&amp;quot;ALL&amp;quot; /&amp;gt;&#xD;
    &amp;lt;!--&amp;lt;appender-ref ref=&amp;quot;SmtpAppenderKangaroo&amp;quot;&amp;gt;&amp;lt;/appender-ref&amp;gt;--&amp;gt;&#xD;
    &amp;lt;appender-ref ref=&amp;quot;FileAppenderKangaroo&amp;quot;&amp;gt;&amp;lt;/appender-ref&amp;gt;&#xD;
  &amp;lt;/logger&amp;gt;&#xD;
  &amp;lt;appender name=&amp;quot;SmtpAppenderKangaroo&amp;quot; type=&amp;quot;log4net.Appender.SmtpAppender&amp;quot;&amp;gt;&#xD;
    &amp;lt;to value=&amp;quot;Kangaroo@800best.com&amp;quot;&amp;gt;&amp;lt;/to&amp;gt;&#xD;
    &amp;lt;from value=&amp;quot;Kangaroo@800best.com&amp;quot; /&amp;gt;&#xD;
    &amp;lt;subject value=&amp;quot;Kangaroo Log Message&amp;quot; /&amp;gt;&#xD;
    &amp;lt;smtpHost value=&amp;quot;smtp.800best.com&amp;quot; /&amp;gt;&#xD;
    &amp;lt;username value=&amp;quot;Kangaroo&amp;quot; /&amp;gt;&#xD;
    &amp;lt;password value=&amp;quot;Kangaroo&amp;quot; /&amp;gt;&#xD;
    &amp;lt;bufferSize value=&amp;quot;2048&amp;quot; /&amp;gt;&#xD;
    &amp;lt;!--超长部分是否丢弃--&amp;gt;&#xD;
    &amp;lt;lossy value=&amp;quot;false&amp;quot; /&amp;gt;&#xD;
    &amp;lt;!--evaluator时好时坏,靠不住,还是用filter实在--&amp;gt;&#xD;
    &amp;lt;!--&amp;lt;evaluator type=&amp;quot;log4net.Core.LevelEvaluator&amp;quot;&amp;gt;&#xD;
      &amp;lt;threshold value=&amp;quot;ERROR&amp;quot;/&amp;gt;&#xD;
    &amp;lt;/evaluator&amp;gt;--&amp;gt;&#xD;
    &amp;lt;!--&amp;lt;evaluator type=&amp;quot;log4net.Core.LevelEvaluator,log4net&amp;quot;&amp;gt;&#xD;
      &amp;lt;threshold value=&amp;quot;WARN&amp;quot; /&amp;gt;&#xD;
    &amp;lt;/evaluator&amp;gt;--&amp;gt;&#xD;
    &amp;lt;!--将导致不能写日志--&amp;gt;&#xD;
    &amp;lt;!--&amp;lt;filter type=&amp;quot;log4net.Filter.DenyAllFilter&amp;quot; /&amp;gt;--&amp;gt;&#xD;
    &amp;lt;!--输出级别在定义之间的日志--&amp;gt;&#xD;
    &amp;lt;filter type=&amp;quot;log4net.Filter.LevelRangeFilter&amp;quot;&amp;gt;&#xD;
      &amp;lt;param name=&amp;quot;LevelMin&amp;quot; value=&amp;quot;ALL&amp;quot; /&amp;gt;&#xD;
      &amp;lt;param name=&amp;quot;LevelMax&amp;quot; value=&amp;quot;OFF&amp;quot; /&amp;gt;&#xD;
    &amp;lt;/filter&amp;gt;&#xD;
    &amp;lt;layout type=&amp;quot;log4net.Layout.PatternLayout&amp;quot;&amp;gt;&#xD;
      &amp;lt;conversionPattern value=&amp;quot;%newline%date [%thread] %-5level %logger [%property{NDC}] : %newline%message%newline&amp;quot; /&amp;gt;&#xD;
    &amp;lt;/layout&amp;gt;&#xD;
  &amp;lt;/appender&amp;gt;&#xD;
 &#xD;
 &amp;lt;appender name=&amp;quot;FileAppenderKangaroo&amp;quot; type=&amp;quot;log4net.Appender.RollingFileAppender&amp;quot;&amp;gt;&#xD;
    &amp;lt;!--绝对路径--&amp;gt;&#xD;
    &amp;lt;!--&amp;lt;file value=&amp;quot;D:\KangarooLog.txt&amp;quot;&amp;gt;&amp;lt;/file&amp;gt;--&amp;gt;&#xD;
    &amp;lt;param name=&amp;quot;File&amp;quot; value=&amp;quot;./Log/KangarooLog.log&amp;quot; /&amp;gt;&#xD;
    &amp;lt;param name=&amp;quot;AppendToFile&amp;quot; value=&amp;quot;true&amp;quot; /&amp;gt;&#xD;
    &amp;lt;!--相对路径,在项目的根目录下--&amp;gt;&#xD;
    &amp;lt;!--以最后一个路径为准,所以上面的绝对路径下不会写日志--&amp;gt;&#xD;
    &amp;lt;!--&amp;lt;file value=&amp;quot;./Log/Kangaroo.txt&amp;quot;&amp;gt;&amp;lt;/file&amp;gt;--&amp;gt;&#xD;
    &amp;lt;!--防止多线程时不能写Log,官方说线程非安全--&amp;gt;&#xD;
    &amp;lt;!--实际使用时,本地测试正常,部署后有不能写日志的情况--&amp;gt;&#xD;
    &amp;lt;lockingModel type=&amp;quot;log4net.Appender.FileAppender+MinimalLock&amp;quot; /&amp;gt;&#xD;
    &amp;lt;appendToFile value=&amp;quot;true&amp;quot; /&amp;gt;&#xD;
    &amp;lt;!--可以为:Once|Size|Date|Composite--&amp;gt;&#xD;
    &amp;lt;!--Composite为Size和Date的组合--&amp;gt;&#xD;
    &amp;lt;rollingStyle value=&amp;quot;composite&amp;quot; /&amp;gt;&#xD;
    &amp;lt;!--日志最大个数,都是最新的--&amp;gt;&#xD;
    &amp;lt;!--rollingStyle节点为Date时,该节点不起作用--&amp;gt;&#xD;
    &amp;lt;!--rollingStyle节点为Size时,只能有value个日志--&amp;gt;&#xD;
    &amp;lt;!--rollingStyle节点为Composite时,每天有value个日志--&amp;gt;&#xD;
    &amp;lt;maxSizeRollBackups value=&amp;quot;10&amp;quot; /&amp;gt;&#xD;
    &amp;lt;!--当备份文件时,为文件名加的后缀--&amp;gt;&#xD;
    &amp;lt;!--后缀为*.txt时,例:AX.txt_2008-07-24.PxP  应该是程序上的一个bug--&amp;gt;&#xD;
    &amp;lt;!--后缀为*.TXT时,例:AX.txt_2008-07-25.TXT--&amp;gt;&#xD;
    &amp;lt;datePattern value=&amp;quot;_yyyy-MM-dd.TXT&amp;quot; /&amp;gt;&#xD;
    &amp;lt;!--可用的单位:KB|MB|GB--&amp;gt;&#xD;
    &amp;lt;!--不要使用小数,否则会一直写入当前日志--&amp;gt;&#xD;
    &amp;lt;maximumFileSize value=&amp;quot;2MB&amp;quot; /&amp;gt;&#xD;
    &amp;lt;!--置为true,当前最新日志文件名永远为file节中的名字--&amp;gt;&#xD;
    &amp;lt;staticLogFileName value=&amp;quot;true&amp;quot; /&amp;gt;&#xD;
    &amp;lt;!--输出级别在INFO和ERROR之间的日志--&amp;gt;&#xD;
    &amp;lt;filter type=&amp;quot;log4net.Filter.LevelRangeFilter&amp;quot;&amp;gt;&#xD;
      &amp;lt;param name=&amp;quot;LevelMin&amp;quot; value=&amp;quot;INFO&amp;quot; /&amp;gt;&#xD;
      &amp;lt;param name=&amp;quot;LevelMax&amp;quot; value=&amp;quot;ERROR&amp;quot; /&amp;gt;&#xD;
    &amp;lt;/filter&amp;gt;&#xD;
    &amp;lt;!--必须结合起来用,第一个只过滤出WARN,第二个拒绝其它其它日志输出--&amp;gt;&#xD;
    &amp;lt;filter type=&amp;quot;log4net.Filter.LevelMatchFilter&amp;quot;&amp;gt;&#xD;
      &amp;lt;param name=&amp;quot;LevelToMatch&amp;quot; value=&amp;quot;WARN&amp;quot; /&amp;gt;&#xD;
    &amp;lt;/filter&amp;gt;&#xD;
    &amp;lt;filter type=&amp;quot;log4net.Filter.DenyAllFilter&amp;quot; /&amp;gt;&#xD;
    &amp;lt;layout type=&amp;quot;log4net.Layout.PatternLayout&amp;quot;&amp;gt;&#xD;
      &amp;lt;conversionPattern value=&amp;quot;%date [%thread] %-5level %logger [%ndc] - %message%newline&amp;quot; /&amp;gt;&#xD;
    &amp;lt;/layout&amp;gt;&#xD;
  &amp;lt;/appender&amp;gt;&#xD;
&amp;lt;/log4net&amp;gt;&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;3. layout节点的配置说明&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&amp;lt;!--                                                                        Made By AX      --&amp;gt;&#xD;
&amp;lt;!--        %m(message):输出的日志消息，如ILog.Debug(…)输出的一条消息                          --&amp;gt;&#xD;
&amp;lt;!--        %n(new line):换行                                                                   --&amp;gt;&#xD;
&amp;lt;!--        %d(datetime):输出当前语句运行的时刻                                                 --&amp;gt;&#xD;
&amp;lt;!--        %r(run time):输出程序从运行到执行到当前语句时消耗的毫秒数                           --&amp;gt;&#xD;
&amp;lt;!--        %t(thread id):当前语句所在的线程ID                                                  --&amp;gt;&#xD;
&amp;lt;!--        %p(priority): 日志的当前优先级别，即DEBUG、INFO、WARN…等                           --&amp;gt;&#xD;
&amp;lt;!--        %c(class):当前日志对象的名称，例如：                                                --&amp;gt;&#xD;
&amp;lt;!--               模式字符串为：%-10c -%m%n                                                    --&amp;gt;&#xD;
&amp;lt;!--               代码为：                                                                     --&amp;gt;&#xD;
&amp;lt;!--        ILog log=LogManager.GetLogger(“Exam.Log”);                                        --&amp;gt;&#xD;
&amp;lt;!--        log.Debug(“Hello”);                                                               --&amp;gt;&#xD;
&amp;lt;!--            则输出为下面的形式：                                                            --&amp;gt;&#xD;
&amp;lt;!--        Exam.Log       - Hello                                                              --&amp;gt;&#xD;
&amp;lt;!--        %L：输出语句所在的行号                                                              --&amp;gt;&#xD;
&amp;lt;!--        %F：输出语句所在的文件名                                                            --&amp;gt;&#xD;
&amp;lt;!--        %-数字：表示该项的最小长度，如果不够，则用空格填充                                  --&amp;gt;&#xD;
&amp;lt;!--        例如，转换模式为%r [%t]%-5p %c - %m%n 的 PatternLayout 将生成类似于以下内容的输出： --&amp;gt;&#xD;
&amp;lt;!--        176 [main] INFO  org.foo.Bar - Located nearest gas station.                         --&amp;gt;&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;4.有用的连接： &lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://www.cnblogs.com/wmj/archive/2008/06/26/1230782.html"&gt;日志维护一点心得&lt;/a&gt;一&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.cnblogs.com/wmj/archive/2008/06/28/1231405.html"&gt;日志维护一点心得二&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/OtisBlog/aggbug/1675734.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/OtisBlog/archive/2010/03/01/1675734.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/OtisBlog/archive/2009/08/24/1552815.html</id><title type="text">UCHome二次开发规范 - 不同于Manyou的开发模式</title><summary type="text">本文为转载， 原网址为： http://www.raychou.com/chou/posts/276.htm  注意：此文和UCHome的Manyou开发模式不同，Manyou是利用Discuz的开放平台MYOP开发公共插件，可供所有基于UCHome的网站使用；而此文涉及的开发模式与Manyou不同，是在本地开发，以插件的形式扩展UCHome原有功能。  UCHome是Discuz的一款SNS程序...</summary><published>2009-08-24T05:05:00Z</published><updated>2009-08-24T05:05:00Z</updated><author><name>Otis's Technology Space</name><uri>http://www.cnblogs.com/OtisBlog/</uri></author><link rel="alternate" href="http://www.cnblogs.com/OtisBlog/archive/2009/08/24/1552815.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/OtisBlog/archive/2009/08/24/1552815.html"/></entry><entry><id>http://www.cnblogs.com/OtisBlog/archive/2009/08/14/1546026.html</id><title type="text">CodeIgniter 技巧：在NetBeans 下为CodeIgniter 添加智能提示</title><summary type="text">习惯了VS 2008的智能提示功能，现在写php智能提示不是很好，有点不习惯。。今天找到了一个为CodeIgniter添加智能提示的快捷，简单，方便的方法（原网址：http://codeigniter.org.cn/forums/thread-401-1-1.html），先看效果： 如何添加？很简单，只要在CI的Controller和Model类的类申明下加入以下代码即可：//加入以下代码到CI的...</summary><published>2009-08-14T04:51:00Z</published><updated>2009-08-14T04:51:00Z</updated><author><name>Otis's Technology Space</name><uri>http://www.cnblogs.com/OtisBlog/</uri></author><link rel="alternate" href="http://www.cnblogs.com/OtisBlog/archive/2009/08/14/1546026.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/OtisBlog/archive/2009/08/14/1546026.html"/></entry><entry><id>http://www.cnblogs.com/OtisBlog/archive/2009/08/11/1543912.html</id><title type="text">QQ开心农场外挂软件设计思路</title><summary type="text">今天玩了一下QQ的开心农场，我有一堆朋友在玩。每次去偷别人的东西时，都要一个一个地点选，看看是否有可摘的东西。然后还要一个个地点摘取，这样才算偷到，感觉好像有点太麻烦了。 有时候朋友的东西可摘了，但是我没时间去看（总不能每XX分钟查一次，每次查全部的朋友的吧。。@@，那样会累死。。)然后我就想，如果有一软件，可以自动去自己的好友的地里偷东西。每隔十分钟查一次，如果好友的地里有东西可以摘，就把它偷回...</summary><published>2009-08-11T12:39:00Z</published><updated>2009-08-11T12:39:00Z</updated><author><name>Otis's Technology Space</name><uri>http://www.cnblogs.com/OtisBlog/</uri></author><link rel="alternate" href="http://www.cnblogs.com/OtisBlog/archive/2009/08/11/1543912.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/OtisBlog/archive/2009/08/11/1543912.html"/></entry><entry><id>http://www.cnblogs.com/OtisBlog/archive/2009/07/13/1522547.html</id><title type="text">技巧：让Eclipse或Flex Builder 支持自动换行。</title><summary type="text">今天找一半天，发现功能超强的Eclipse竟然没有自动换行的功能。真的是让人郁闷呀。。 而Visual Studio的自动换行功能却做得很棒！！  Google了N分钟，发现Eclipse要装上一插件才支持自动换行功能。  这个插件的安装网址是： http://ahtik.com/eclipse-update/  插件很小，装上了重启Eclipse就可以自动换行了。  方法是在编辑器里右点，选择:...</summary><published>2009-07-13T07:18:00Z</published><updated>2009-07-13T07:18:00Z</updated><author><name>Otis's Technology Space</name><uri>http://www.cnblogs.com/OtisBlog/</uri></author><link rel="alternate" href="http://www.cnblogs.com/OtisBlog/archive/2009/07/13/1522547.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/OtisBlog/archive/2009/07/13/1522547.html"/></entry></feed>
