[转载]VS 2010 和 .NET 4.0 系列之《ASP.NET 4以及ASP.NET MVC 2中对输出进行HTML编码的新句法》篇

mikel阅读(885)

[转载]VS 2010 和 .NET 4.0 系列之《ASP.NET 4以及ASP.NET MVC 2中对输出进行HTML编码的新句法》篇-Scott Guthrie 博客中文版.

【原文地址】 New <%: %>Syntax for HTML Encoding Output in ASP.NET 4 (and ASP.NET MVC 2)
【原文发表日期】 Tuesday, April 06, 2010 11:57 PM

除了写博客外,我现在还使用Twitter发短贴和共享链接。请通过twitter.com/scottgu跟随我。

这是我针对即将发布的VS 2010 和 .NET 4所撰写的 贴子系列的第十九篇。

今天的贴子讨论ASP.NET 4中引进的一个很小,但非常有用的新句法特性,即能自动到代码片段中对输出进行HTML编码的功能。这有助于保护你的应用和网站免受跨站脚本攻击(XSS)和HTML注入攻击,而且允许你使用一个非常简洁的句法来实现。

HTML编码

跨 站脚本注入(XSS)和HTML编码攻击是网站和应用频受其害的2个最常见的安全问题。它们是在黑客找到方法,把客户端脚本或HTML标识注入网页,然后 这些网页被访问网站的其他访问者浏览时发生的。这可以用来糟蹋一个网站,以及允许黑客运行客户端代码来偷窃cookie数据或者利用用户在网站上的身份做 坏事。

帮助减少跨站脚本攻击的一个方法是确保网页上显示的输出是被HTML编码过了的,这帮助确保任何由终端用户输入或修改过的内容无法在向网页输出时含有象<script> 或 <img>这样的元素。

今天是如何对内容进行HTML编码的

ASP.NET 应用(特别是那些使用ASP.NET MVC的应用)经常依赖使用 <%= %> 代码片段表达式来显示输出。开发人员今天经常在这些表达式内使用Server.HtmlEncode() 或 HttpUtility.Encode()辅助方法在显示输出之前对输出进行HTML编码。这可以用象下面这样的代码来实现:

image

虽然这正常工作,但有2个小缺点:

  1. 有点冗长
  2. 开发人员经常忘了调用Server.HtmlEncode方法,而且没有简单的方法可以对整个应用来核实其用法

新的代码片段句法: <%: %>

在ASP.NET 4中,我们引进了一个新的代码表达式句法,<%:  %>,象<%= %>一样显示输出,但在显示前,会对输出自动进行HTML编码。这免掉了象上面例子那样显式地对内容进行HTML编码的需要,你只要编写象下面这样 更为简洁的代码即可实现完全一样的事:

image

我们选择 <%: %> 句法,是因为很容易快速地替换现有的 <%= %> 代码段实例,它还允许你轻松地在你的代码库查询 <%= %> 元素,发现并核实任何你在应用中没有使用HTML编码的地方,以确保其行为之正确性。

避免双重编码

虽然对内容进行HTML编码通常是个好的最佳实践,但有时你输出的内容就是HTML或者已经编码过了,在这样的情形下,你不想要再做HTML编码。

ASP.NET 4 引进了一个新的 IHtmlString接口 (以及一个具体实现: HtmlString),你可以将其在类型上实现,来表示它的值用来显示HTML时,已经恰当地编码过了(或者已经检查过了),因此它的值不该再作HTML编码了。<%: %>代码片段句法会检查内中代码表达式的值是否实现了IHtmlString 接 口,如果实现了的话,就不再对其输出进行HTML编码。这允许开发人员避免需要每每做决定是用<%= %> 还是用 <%: %>代码片段,而你总可以使用<%: %>代码片段,然后让已经HTML编码过了的任何属性或数据类型实现 IHtmlString接口。

在 <%: %> 中使用ASP.NET MVC HTML辅助方法

举一个这个HTML编码替换机制非常有用的实际例子,考虑一下你在ASP.NET MVC中使用HTML辅助方法的场景。这些辅助方法一般返回HTML。例如,Html.TextBox()辅助方法返回象 <input type=”text”/> 这样的标识。在ASP.NET MVC 2中,这些辅助方法现在默认返回HtmlString类型,表明返回的字符串内容显示是安全的,<%: %>不必再编码了。

这允许你将这些方法在 <%= %> 代码块中:

image

以及 <%: %> 代码块中使用:

image

在上面两种情形中,从辅助方法返回的HTML内容是作为HTML在客户端显示的, <%: %> 会避免做双重编码。

这 允许你在应用中默认使用 <%: %> 代码片段,而不是<%= %>代码块。如果你要是固执(hardcore)的话,你甚至可以创建一个编译规则,在应用中查询 <%= %> 用例,如果发现,将其标记为出错,来强制HTML编码总是发生。

ASP.NET MVC 2 视图的脚手架(Scaffolding)

在 你使用VS 2010 (或者免费的 Visual Web Developer 2010 Express版本)建造ASP.NET MVC 2应用时,你会发现使用“添加视图”对话框生成的视图在输出任何内容时,现在是默认使用 <%: %> 代码块的。例如,下面,我为 Article 对象生成了一个简单的“编辑”视图。注意其中标签,文本框和验证消息的三个 <%: %> 代码片段用例(都是使用HTML辅助方法输出的):

image

结语

新的 <%: %> 句法 提供了一个简洁的方式来自动对内容进行HTML编码,并将其显示为输出。它允许你减少代码的冗长,可以轻松地检查/核实整个网站上的内容都是HTML编码过了的。这可以帮助你的应用免受跨站脚本注入(XSS)和HTML注入攻击。

希望本文对你有所帮助,

Scott

[转载]C#生成CHM文件(中级篇)

mikel阅读(1076)

[转载]C#生成CHM文件(中级篇) – Alexis – 博客园.

在上篇《C#生成CHM文件(入门篇)》中,我们利用微软自带的hhc.exe以编程的方式创建一个CHM文件,而且调用的是一个静态的HMTL文件。

在中篇中,实现以下几个目标
1.将在线的网页保存为CHM文件
2.我们将对我们进行编译的CHM文件进行反编译,使用的还是微软自带的一个exe(hh.exe)。
3.以编程的方式将CHM文件转换为Word

在中篇中,把界面稍微调整了下,如下图

一、将在线的网页保存为CHM文件
曾尝试直接使用网址来编译html文件,结果一直报错,于是就放弃了。现在实现的方法的思想是这样的:先将输入的url地址的网页保存到本地,然后利用 上一篇中的方法生成CHM文件。不过经测试,这样的效率还是比较低的,主要的花费在将htm文件下载到本地,如果带宽不够的话,将会很慢,不过总归是种方 法,大家如果有更好的解决方案,希望能告诉我。

 HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(url);
 HttpWebResponse myResp = (HttpWebResponse)myReq.GetResponse();
 StreamReader respStream = new StreamReader(myResp.GetResponseStream(), Encoding.Default);
 string respStr = respStream.ReadToEnd();
 respStream.Close();
 FileStream fs = new FileStream(startPath+@"\test.htm"FileMode.Create, FileAccess.Write);
 StreamWriter sw = new StreamWriter(fs, Encoding.Default);
 sw.Write(respStr);
 sw.Close();
思路是将网页保存在本地的,startPath为项目所在路径。 大家可以以http://www.baidu.com/index.htm为例(注意要以htm或html为结尾),测试下,看看能不能正常将百度的首页保存到CHM文件中。
效果图是这样的:

二、反编译CHM
反编译CHM的方法同初篇中的利用Process类来进行。

代码

/// <summary>
/// 反编译CHM文件
/// </summary>
/// <param name=”CHMFile”>CHM文件名</param>
/// <returns>返回hhc文件名</returns>
/// <remarks>uses the <see cref=”DecompileChm”></see></remarks>
public string DecompileChm(string CHMFile)
{
string pathDir = Path.GetDirectoryName(CHMFile);//得到chm文件的绝对路径
pathDir = Path.Combine(pathDir, Path.GetFileNameWithoutExtension(CHMFile));
return DecompileChm(CHMFile, ref pathDir);
}
/// <summary>
/// 反编译CHM文件
/// </summary>
/// <param name=”CHMFile”>CHM文件名</param>
/// <param name=”FolderToPut”>反编译后的文件存放路径</param>
/// <returns>返回反编译后的hhc文件名</returns>
/// <remarks>使用hh.exe反编译</remarks>
public string DecompileChm(string CHMFile, ref string FolderToPut)
{
if ((!System.IO.File.Exists(CHMFile)))
{
throw new ArgumentException(CHMFile+文件不存在);
}
if ((!Directory.Exists(FolderToPut)))
{
FolderToPut
= FolderToPut.Replace( , _);
Directory.CreateDirectory(FolderToPut);
}
DirectoryInfo di
= new DirectoryInfo(FolderToPut);
if ((di.Name.Contains( )))
{
throw new ArgumentException(反编译的文件夹名不能包含空格);
}
string strD = null;
strD
= -decompile + di.FullName + + CHMFile;//反编译命令
Console.WriteLine(strD);
Process p
= Process.Start(hh.exe, strD);//调用hh.exe进行反编译

p.WaitForExit();
return Directory.GetFiles(FolderToPut, *.HHC)[0];
}

三、CHM文件转换为Word
接下来,我们来延伸下,利用反编译的文件,将CHM转换成Word文件。思路是这样的:利用反编译,得到hhc文件(hhc文件中包含htm或html文 件的文件名)和一大堆web页面(如果一开始编译进去的是一大堆的话,呵呵),创建一个word文件,将html文件插入到word中,下面以实例的方式 来实现。
为了方便代码管理,我创建了一个类库项目,命名为CHM2Word,里面主要实现将CHM文件反编译并将反编译的文件整合为Word。在CreateCHM项目中调用代码即可,另需要你的机器安装Office2003(对应,添加引用 ->COM->Microsoft Word 11.0 Object Library)或2007(对应,添加引用->COM->Microsoft Word 12.0 Object Library)。

代码

/// <summary>
/// 添加到word中
/// </summary>
/// <param name=”pathFileHHC”></param>
/// <param name=”saveAs”></param>
public void AddToWord(string pathFileHHC, string saveAs)
{
if (File.Exists(saveAs))
{
throw new Exception(word文件已经存在!);
}
Object Nothing
= System.Reflection.Missing.Value;
Microsoft.Office.Interop.Word.Application wApp
= (Microsoft.Office.Interop.Word.Application)this.Word();
Document wDoc
= wApp.Documents.Add(ref Nothing, ref Nothing, ref Nothing, ref Nothing);

if (wApp == null)
{
throw new Exception(转换失败);
}

try
{
string dirfile = “”;//目录位置
dirfile = Path.GetDirectoryName(pathFileHHC);//目录的绝对路径
string[] lines = File.ReadAllLines(pathFileHHC);//读取hhc所有的行,这是为了找出里面的htm或html文件

string quote = “” + (char)34;
long filenumber = 0;

//遍历每一行
foreach (string TextLine in lines)
{
string htmFile = null;

if (TextLine.IndexOf(.html, 0) > 0 || TextLine.IndexOf(.htm, 0) > 0)//如果这一行里面有.htm或者html.的字符串
{

#region 以下代码是获取htm或者html文件名

int endQuote = 0;
if (TextLine.IndexOf(.html, 0) > 0)
{
endQuote
= TextLine.IndexOf(quote, TextLine.IndexOf(.html, 0));
}
else
{
endQuote
= TextLine.IndexOf(quote, TextLine.IndexOf(.htm, 0));
}
int quoteLoop = 0;
quoteLoop
= endQuote 1;
while (TextLine.Substring(quoteLoop, 1) != quote)
{
quoteLoop
= quoteLoop 1;
}
htmFile
= TextLine.Substring(quoteLoop + 1, endQuote quoteLoop 1);//获取html文件的名字

#endregion

htmFile = dirfile + \\ + htmFile;

bool b = false;//是否存在html文件
try
{
b
= File.Exists(htmFile);
}
catch (Exception ex)
{
}
if ((!b))
{
continue;
}
//将文件插入到word中
wApp.Selection.InsertParagraphAfter();
filenumber
+= 1;
if (ProcessFile != null)
{
ProcessFile(
this, new ProcessFileEventArgs(htmFile, filenumber));
}
//InsertFile参数说明
//文件名: 必选的 String. 要被插入的文件名和路径。如果没有指定路径,Word默认为当前文件夹
//Range: 可选的 Object. 如果指定的文件时word, 参数为bookmark(书签). 如果文件为其他类型(如Excel工作表), 参数为指定的一个单元或区域,如 R1C1:R3C4
//确定是否转换 可选 Object.如果值为 True,则 word 应用程序将在插入非“ Word 文档”格式的文档时提示对转换进行确认。.
//链接:  可选 Object. 如果值为 True,则可用 INCLUDETEXT 域插入该文档。
//附件: 可选 Object. 为 True 时将该文件作为附件插入电子邮件消息中。
wApp.Selection.InsertFile(htmFile, ref Nothing, ref Nothing, ref Nothing, ref Nothing);
if ((filenumber % 10 == 0))
wDoc.Save();
}
}
wDoc.Save();
//保存word
wDoc.Close(ref Nothing, ref Nothing, ref Nothing);//关闭
wApp.Quit(ref Nothing, ref Nothing, ref Nothing);//释放

}
catch (Exception ex)
{
}
finally//释放对象
{
if ((wDoc != null))
{
Marshal.ReleaseComObject(wDoc);
wDoc
= null;
}

Marshal.ReleaseComObject(wApp);
wApp = null;
}
}

创建word对象

代码

/// <summary>
/// 创建word对象
/// </summary>
/// <returns></returns>
public object Word()
{
Microsoft.Office.Interop.Word.Application WordApp;
try
{

//WordApp = new Microsoft.Office.Interop.Word.ApplicationClass();//如果是office2003和office2007用这样方法
WordApp = new Microsoft.Office.Interop.Word.Application();//如果是office2010,使用这个方法
}
catch (Exception e)
{
WordApp
= null;
}
return WordApp;
}

反编译导出类主要方法

代码

/// <summary>
/// feedback about processing
/// </summary>
public event EventHandler<ProcessFileEventArgs> ProcessFileIntoWord;//定义一个事件属性
private WordClass withEventsField_w = new WordClass();
/// <summary>
/// 通过这个类,我们可以转换为word,并且把事件传给调用者
/// </summary>
public WordClass w
{
get { return withEventsField_w; }
set
{
if (withEventsField_w != null)//如果不为null,撤销事件
{
withEventsField_w.ProcessFile
-= w_ProcessFile;
}
withEventsField_w
= value;
if (withEventsField_w != null)//如果不为null,注册
{
withEventsField_w.ProcessFile
+= w_ProcessFile;
}
}
}
/// <summary>
/// 主要函数:反编译、导出
/// </summary>
/// <param name=”ChmFile”>待反编译的CHM文件</param>
/// <param name=”DocFile”>word文件名</param>
/// <remarks>word文件一定不存在</remarks>
public void DecompileAndExport(string ChmFile, string DocFile)
{
try
{
Decompile d
= new Decompile();//实例化一个反编译类
string strHHC = d.DecompileChm(ChmFile);//获取hhc文件
w.AddToWord(strHHC, DocFile);//调用word类的添加到word中方法
}
catch (System.Runtime.InteropServices.COMException ex)
{
//throw new clsError(“Com exception:” + ex.Message, ErrorsOcurred.ComError);
}

}

我利用刚刚生成的baidu的CHM导出的word如图:

效果还是不错的,呵呵。如果你的CHM文件大的话,导出的时间可能会比较长一些。

PS:
1.如果你使用的是office2003或者office2007,需要修改类库项目下的WordClass类下Word方法,因为office2010的
Microsoft.Office.Interop.Word.ApplicationClass不再提供构造方法,而是提供Microsoft.Office.Interop.Word.Application()接口
2.如果在转换的工程中,始终没有反应,可以调试下,如果出现这样的错误,“因为没有打开的文档,所以这一命令无效”。

调试中不会弹出异常,但是将鼠标放到wApp对象中,查看的会发现那样的错误,原因是因为权限不够,可以采用如下方法解决:

运行dcomcnfg打开组件服务,依次展开”组件服务”->”计算机”->”我的电脑”->”DCOM配置”

找到”Microsoft Word应用程序”,右键打开属性对话框,
点击”标识”选项卡,点击”标识”标签,选择”交互式用户”(此设置可能对计算机安全存在威胁,如不设置可以解决问题就不设置,点”下列用户”,把管理员的用户administrator密码….正确填写进去也行)
点击”安全”选项卡,依次把”启动和激活权限”,”访问权限”,”配置权限”,都选择为自定义,然后依次点击它们的编辑,把everyone添加进去,并加入所有的权限…
OK,解决此问题!
如果你的office是2010或者你的系统版本较高的话,很有可能遇到这样的问题。我的电脑是windows7+office2010,就遇到了这样的问题。

3.在反编译和在线生成CHM的时候会生成一些临时文件,如果不及时删掉的话,会造成空间的浪费。我们自己可以写一个简单的删除程序,这个应该很简单,如果不会的,可以参考我以前项目中的代码,http://www.cnblogs.com/alexis/archive/2010/07/03/1770409.html

在下篇(应用篇)中,我将说说如何将这些技术运用到实际中。

[转载]PowerDesigner15官方正式版+注册补丁

mikel阅读(1030)

[转载]PowerDesigner15官方正式版+注册补丁,Java技术文章,Java系列教程,Java.

PowerDesigner15官方正式版+注册补丁

www.firnow.com    时间 : 2009-09-08  作者:匿名   编辑:小张 点击:  2302 [ 评论 ]

(1)软件介绍:
PowerDesigner是Sybase公司的CASE工具集,使用它可以方便地对管理信息系统进行分析设计,它几乎包括了数据库模型设计的全过程。利 用PowerDesigner可以制作数据流程图、概念数据模型、物理数据模型,可以生成多种客户端开发工具的应用程序,还可为数据仓库制作结构模型,也 能对团队设计模型进行控制。它可与许多流行的数据库设计软件,例如:PowerBuilder,Delphi,VB等相配合使用来缩短开发时间和使系统设 计更优化。

(2)官方下载:
目前 PowerDesigner 最新官方正式版本为 15.1.0.2850 ,謾軻提供官方下载地址:
主程序:PowerDesigner15_Evaluation.exe
http://download.sybase.com/eval/PowerDesigner/PowerDesigner15_Evaluation.exe
类库: PowerDesigner15_Library.zip
http://download.sybase.com/eval/PowerDesigner/PowerDesigner15_Library.zip
(2)注册(破解)方法:
1.点击以上链接到官方下载 PowerDesigner 15.1.0.2850 最新正式版并安装;
2.下载謾軻提供的注册补丁 pdflm15.dll [点击下载],然后替换原安装目录里的 pdflm15.dll 文件;
3.重启 PowerDesigner 15 即完成破解。

(3)破解说明:
对于 PowerDesigner15 的破解,网上盛传的方法是通过 pdflm15.dll + license.lic 破解补丁进行破解,然而謾軻亲自试验后发现这种方法其实只适用于 PowerDesigner12 的破解,用在 PowerDesigner15 身上则会出现如下错误提示:

diyblPic

错误提示1: PowerDesigner:pdshell15.exe-无法找到入口

无法定位程序输入点?SExceptionDialog_@@YAHPBDOJPB_WZZ于动态链接库PDCore15.dll上。

diyblPic

错误提示2: Sybase PowerDesigner(R)

Cannot load license management library(pdflm15)

针对这种现象,謾軻通过对 PowerDesigner15 的研究发现,官方加强了程序的保护措施,在动态链接库 PDCore15.dll 做了手脚,于是謾軻花了将近2个多小时的睡眠时间终于把 PowerDesigner15 破解出来,而且在只修改官方 pdflm15.dll 一个文件的情况下完成了注册效果,保持了软件原有的稳定性,废话少说,謾軻以图为证,希望对大家有所帮助:

diyblPic

官方原版为15天试用版

diyblPic

破解后为企业正式版

[转载]SQL Server 2008批量删除数据表

mikel阅读(1368)

[转载]SQL Server 2008批量删除数据表_飞宏风_百度空间.

测试数据
create table dbo.temptb_1 (id
int);
create table guest.temptb_2 (id
int);

打开隐式事务
SET IMPLICIT_TRANSACTIONS ON
执行动态删除
–定义一个变量

declare @SQL varchar(max);
set @SQL=;
select @SQL=@sql+drop table +
–获取表名称,形如:dbo.temptb_***,escape ‘\’表示’\’为转义符号
QUOTENAME(SCHEMA_NAME([schema_id]))
+.+QUOTENAME([name])+;
from sys.tables where where is_ms_shipped =0 and [name] like temptb\_% escape \’
— select @sql;
EXEC(@sql);
检查删除是否正确
select * from sys.tables
正确,则提交事务,确认删除
commit tran
不正确,则回滚事务,取消删除
rollback tran
关闭隐式事务
SET IMPLICIT_TRANSACTIONS OFF

[转载]Asp.net MVC 2 + Castle + NHibernate 项目实战(1)

mikel阅读(1002)

[转载]Asp.net MVC 2 + Castle + NHibernate 项目实战(1) – Taven – 博客园.

本文将开始一步一步地使用ASP.NET MVC 2 + Castle + NHibernate 开发一个项目。

在开始之前,我先对这三个组件做一个简单的介绍:

ASP.NET MVC

它是微软提供的一个基于MVC标准的Web开发模式,其典型特点是有控制器和视图;在这之前,.NET下的Web开发模式大多是采用WebForm,其典型特点是服务端控件和后台触发事件;

NHibernate

它是一个ORM框架,使用Java的SSH做过项目开发的人就非常熟悉了,当前最新版本为NHibernate 3.0,听说完全支持Linq查询语句了,以前只支持HQL语句。

Castle

它是一个非常大的框架,包含IoC、MVC、ORM、AOP等,这次我只用到其IoC的功能。

关于IoC

IoC的英文是Inversion of Control,中文意思是控制反转,也有称其为Dependence Injection,中文意思是依赖注入,也就是DI;

除了Castle可以作IoC 外,还有著名的Spring.Net、Unity等,在我另外一个开源博客项目 http://rorowo.codeplex.com/ 中就用到了微软的Unity 2.0作为IoC。

好了,废话不多说,下面开始。

首先,第一步是创建一个解决方案,项目结构如下:

需要引用的DLL库文件,我们全部放在RoRoWo.Common.DependLib下:

根据表的结构,如图:

现在我们开始为表结构创建实体类,以BlogCategory表为例,我们根据该表的字段名称和数据类型创建一个POCO类,放在RoRoWo.Domain.Entities下,代码内容如下:

代码

namespace RoRoWo.Domain {

public class Blogcategory {
public Blogcategory() { }
public virtual int Cateid { get; set; }
public virtual IList<Blogarticle> Blogarticles { get; set; }
public virtual string Catename { get; set; }
public virtual int Parentid { get; set; }
public virtual int State { get; set; }
public virtual int Sortid { get; set; }
public virtual int Articlecount { get; set; }
public virtual System.DateTime Createtime { get; set; }
public virtual string Note { get; set; }
}
}

在这里,我推荐一个可以生成NHibernate映射对象代码的工具(开源的),项目地址:NHibernate Mapping Generator(它同时支持 hbm.xml文件的方式、Fluent Mapping方式、Castle ActiveRecord方式)

接下来,要为这个类创建一个映射关系,我这里使用配置文件的方式,但是正式项目推荐使用Fluent方式。我们创建一个XML文件,文件名为“Blogcategory.hbm.xml”,放在RoRoWo.Domain.Mappings下,内容如下:

代码

<?xml version=1.0 encoding=utf-8?>
<hibernatemapping assembly=RoRoWo.Domain namespace=RoRoWo.Domain xmlns=urn:nhibernate-mapping-2.2 defaultlazy=false>
<class name=Blogcategory table=BlogCategory>
<id name=Cateid column=CateID>
<generator class=native />
</id>
<property name=Catename column=CateName />
<property name=Parentid column=ParentID />
<property name=State column=State />
<property name=Sortid column=SortID />
<property name=Articlecount column=ArticleCount />
<property name=Createtime column=CreateTime />
<property name=Note column=Note />
</class>
</hibernatemapping>

这里就是一个典型的映射关系了,如果有一对多,多对多的表关系,也是在这个配置中进行维护。

创建这个XML后,还有个很重要的操作,就是将其设为“嵌入的资源” ,鼠标右键查看“Blogcategory.hbm.xml”文件属性,将“生成操作”项的“内容”改为“嵌入的资源”,如图:

到此,一个映射关系的实体就建立好了,下面我们就要来实现NHibernate对该表的增删改查操作了,我们把这些操作的实现放在RoRoWo.Data中。

注意,RoRoWo.Data需要添加对 “Castle.Core.dll” Castle.DynamicProxy2.dll NHibernate.dll RoRoWo.Domain 的引用。

在创建数据库操作类之前,我们需要创建一个 “SessionManager”类,它负责维护整个ORM中的上下文,这里我使用李永京的一个类,其代码如下:

代码

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

using NHibernate;
using NHibernate.Cfg;

namespace RoRoWo.Data
{
public class SessionManager
{
private ISessionFactory _sessionFactory;
public SessionManager()
{
_sessionFactory = GetSessionFactory();
}
private ISessionFactory GetSessionFactory()
{
return (new Configuration()).Configure().BuildSessionFactory();
}
public ISession GetSession()
{
return _sessionFactory.OpenSession();
}
}
}

我们创建一个“BlogCategoryRespository.cs”文件,其代码如下:

代码

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

using NHibernate;
using NHibernate.Cfg;
using NHibernate.Criterion;
using RoRoWo.Domain;

namespace RoRoWo.Data
{
public class BlogCategoryRespository
{
private ISession _session;
public ISession Session
{
set
{
_session = value;
}
}

public BlogCategoryRespository(ISession session)
{
_session = session;
}

public Blogcategory GetById(int cateId)
{

return _session.Get<Blogcategory>(cateId);
}

public void Create(Blogcategory dto)
{
_session.Save(dto);
_session.Flush();
}

public int CreateAndReturn(Blogcategory dto)
{
int newid = (int)_session.Save(dto);
_session.Flush();
return newid;
}

/// <summary>
/// 使用事务
/// </summary>
/// <param name=”dto”></param>
/// <returns></returns>
public int CreateTransaction(Blogcategory dto)
{
using (ITransaction tx = _session.BeginTransaction())
{
try
{
int newId = (int)_session.Save(dto);
_session.Flush();
tx.Commit();
return newId;
}
catch (HibernateException)
{
tx.Rollback();
throw;
}
}
}

public void UpdateCustomer(Blogcategory dto)
{
_session.Update(dto);
_session.Flush();
}

public void SaveOrUpdate(IList<Blogcategory> dtos)
{
foreach (var c in dtos)
{
_session.SaveOrUpdate(c);
}
_session.Flush();
}

public void Delete(Blogcategory dto)
{
_session.Delete(dto);
_session.Flush();
}

public IList<Blogcategory> From()
{
//返回所有Blogcategory类的实例
return _session.CreateQuery(from Blogcategory)
.List<Blogcategory>();
}

public IList<int> Select()
{
//返回所有Blogcategory的CateId
return _session.CreateQuery(select c.CateId from Blogcategory c)
.List<int>();
}

public IList<Blogcategory> Where()
{
return _session.CreateQuery(from Blogcategory c where c.CateId=’3′)
.List<Blogcategory>();
}

public IList<Blogcategory> GetGreaterThan(int CateId)
{
//return _session.CreateQuery(“select from Blogcategory c where c.CateId > :cid”)
// .SetInt32(“cid”, CateId)
// .List<Blogcategory>();

return _session.CreateCriteria(typeof(Blogcategory))
.Add(Restrictions.Gt(CateId, CateId))
.List<Blogcategory>();

}

public IList<Blogcategory> CreateCriteria()
{
ICriteria crit = _session.CreateCriteria(typeof(Blogcategory));
crit.SetMaxResults(50);
IList<Blogcategory> blogcategorys = crit.List<Blogcategory>();
return blogcategorys;
}

public IList<Blogcategory> Narrowing()
{
IList<Blogcategory> blogcategorys = _session.CreateCriteria(typeof(Blogcategory))
.Add(Restrictions.Like(Catename, s%))
.Add(Restrictions.Between(Parentid, 1, 3))
.List<Blogcategory>();
return blogcategorys;
}

public IList<Blogcategory> Query()
{
Blogcategory dtoSample = new Blogcategory() { Catename = sss, Parentid = 0 };
return _session.CreateCriteria(typeof(Blogcategory))
.Add(Example.Create(dtoSample))
.List<Blogcategory>();
}

public IList<Blogcategory> UseQueryByExample_Get(Blogcategory dtoSample)
{
Example example = Example.Create(dtoSample)
.IgnoreCase()
.EnableLike()
.SetEscapeCharacter(&);
return _session.CreateCriteria(typeof(Blogcategory))
.Add(example)
.List<Blogcategory>();
}

}
}

该代码具有了对一个表的基本操作,现在我们就来创建一个单元测试,测试一下插入数据。

在创建插入操作时,我们要能使NHibernate正常工作,还需要创建一个配置文件,我们创建一个XML文件,文件名为“hibernate.cfg.xml”,放在RoRoWo.UnitTest下,其内容为:

代码

<?xml version=”1.0″ encoding=”utf-8″?>
<hibernate-configuration xmlns=”urn:nhibernate-configuration-2.2″ >
<session-factory>
<property name=”connection.driver_class”>NHibernate.Driver.SQLClientDriver</property>
<property name=”connection.connection_string”>
Data Source=.;Initial Catalog=RoRoWoDB;User ID=sa;Password=2010;
</property>
<property name=”adonet.batch_size”>10</property>
<property name=”show_SQL>true</property>
<property name=”dialect”>NHibernate.Dialect.MsSQL2005Dialect</property>
<property name=”use_outer_join”>true</property>
<property name=”command_timeout”>10</property>
<property name=”query.substitutions”>true 1, false 0, yes ‘Y’, no ‘N’</property>
<property name=”proxyfactory.factory_class”>
NHibernate.ByteCode.Castle.ProxyFactoryFactory,
NHibernate.ByteCode.Castle
</property>
<mapping assembly=”RoRoWo.Domain”/>
</session-factory>
</hibernate-configuration>

其中“Data Source=.;Initial Catalog=RoRoWoDB;User ID=sa;Password=2010;”是我的数据库连接,您可以改为您的。

现在我们添加一个单元测试(不明白如何添加的请参考相关资料),先测试插入方法,其代码如下:

代码

/// <summary>
///Create 的测试
///</summary>
[TestMethod()]
public void CreateTest()
{
SessionManager sessionManager = new SessionManager();
ISession session = sessionManager.GetSession();
BlogCategoryRespository target = new BlogCategoryRespository(session);
Blogcategory dto = new Blogcategory();

dto.Catename = 新分类 + new Random().Next(100000, 999999).ToString();
dto.Parentid = 0;
dto.State = 0;
dto.Createtime = DateTime.Now;

int newid = target.CreateAndReturn(dto);
Assert.IsTrue(newid > 0);
}

执行单元测试,可以通过测试,并且在数据库中已经成功插入了一条记录,结果完全正确;

我们接着对查询方法进行测试,我们将测试代码如下:

代码

/// <summary>
///GetById 的测试
///</summary>
[TestMethod()]
public void GetByIdTest()
{
SessionManager sessionManager = new SessionManager();
ISession session = sessionManager.GetSession();
BlogCategoryRespository target = new BlogCategoryRespository(session);
int cateId = 3;
Blogcategory actual;
actual = target.GetById(cateId);
Assert.AreEqual(cateId, actual.Cateid);

}

/// <summary>
///From 的测试
///</summary>
[TestMethod()]
public void FromTest()
{
SessionManager sessionManager = new SessionManager();
ISession session = sessionManager.GetSession();
BlogCategoryRespository target = new BlogCategoryRespository(session);
IList<Blogcategory> actual;
actual = target.From();
Assert.IsTrue(actual.Count > 0);

}

/// <summary>
///Select 的测试
///</summary>
[TestMethod()]
public void SelectTest()
{
SessionManager sessionManager = new SessionManager();
ISession session = sessionManager.GetSession();
BlogCategoryRespository target = new BlogCategoryRespository(session);
IList<int> actual;
actual = target.Select();
Assert.IsTrue(actual.Count > 0);
}

/// <summary>
///Where 的测试
///</summary>
[TestMethod()]
public void WhereTest()
{
SessionManager sessionManager = new SessionManager();
ISession session = sessionManager.GetSession();
BlogCategoryRespository target = new BlogCategoryRespository(session);

IList<Blogcategory> actual;
actual = target.Where();
Assert.IsTrue(actual.Count > 0);
}

/// <summary>
///GetGreaterThan 的测试
///</summary>
[TestMethod()]
public void GetGreaterThanTest()
{
SessionManager sessionManager = new SessionManager();
ISession session = sessionManager.GetSession();
BlogCategoryRespository target = new BlogCategoryRespository(session);
int CateId = 0; // TODO: 初始化为适当的值
IList<Blogcategory> actual;
actual = target.GetGreaterThan(CateId);
Assert.IsTrue(actual.Count > 0);

}

测试结果全部绿灯通过:

下一篇,我将谈谈如何配置一对多和多对多的表映射关系。

该例子的完整代码可以到开源平台下载,地址: http://rorowoproject.codeplex.com

文章中如有不足之处,望大家多指正

[转载]前端管窥:图片Sprite管理

mikel阅读(972)

[转载]前端管窥:图片Sprite管理 – BENNY CHIA! – 博客园.


Sprite 是每个前端工程师处理图片的基本技能。有些工程师昵称这项技能为“雪碧”,可见大家对这个东西的关爱程度。所谓图片的sprite技术,就是把网站用到的 小图片整合在一张比较大的“地图”上,然后在页面容器里对这张“地图”采用背景图片定位的方式来调用此处需要用到的那张小图片的位置。
Sprite的优势:
使用图片sprite技术的优势有三:一,减少针对图片的http请求 数,如果使用许多小图片的方式来组织页面,势必会造成加载页面的时候对每个图片文件形成一个http请求,如果使用sprite技术,则页面只需要对这些 小图片组成的大图进行一次请求即可,减小了网络负担。二,减小图片大小。使用sprite生成的大图其文件大小比其组成部分的小图片大小的总和要小,图片 越小,下载越快。且图片下载后所有在大图上的图片同时刷新出来,而不是每个图片分别刷新,网页的视觉整体性要好。三,便于图片管理。网页需要的各种尺寸的 icon图标和按钮图片等以整齐的顺序排列,便于图片修改和管理。
Sprite的劣势:
sprite的好处就是上面那些,不好之处也是有的,比如,如果你需要一 张背景透明的图片,众所周知IE6对png图片的支持不好,处理img图片尚有解决方法,处理背景平铺也有对策,但是处理一个sprite定位的背景图片 现在还没有好的解决方案。有些方案虽然能解决,但是对客户端造成的负担可以让你得不偿失。
这让我想到table和div之间的争论,有人做页面重 构工作,将一切table均使用div代替,事实是显示数据的表格还是table效果最好,非但数据表格,有些页面布局能够使用table简单解决,就不 必把问题复杂化。facebook和人人的弹窗就是用table写的,效果很好。
一些经验和建议:
现在在工作中,sprite图片越来越大,有的项目中sprite图片居然超 过1000px,这时我们就得去看看,这些组成sprite的小图片组织得是否合理。举例来看,google的logo图片下方充满了小图标,整个 google搜索页只用了这么一张28k大小的图片:

这么做对于google这种sprite基本不变,同时十分重视每1k图片大小的优化的网站来说,这么做有他的道理。但是在一般网站来说,我不建议 采用google的sprite排列方式,尤其不建议把logo做到sprite里。出于经常维护的需要,我们需要更好的图片维护,sprite最好能够 有一种规则,让你对其中每一个图标的位置都清清楚楚。

比如,利用PS的网格工具做参考,或者在PSD文件中建立一个框架图层,将网站各种尺寸的图标放在不同的横行,每个图标之间留出同样的尺寸,如果是 16px的icon,可以在每个16px的空间右边空出5px的距离放下一个图标,这样的话两个图标左边缘的距离就是21px,如果sprite左边第一 个icon的background-position为0 0的话,第10个icon的background-position就是-210px 0。这样你可以精确地知道每个图标的位置,今后调用图标只需要心算一下即可。


如果sprite图片的第一行放了16px的icon,第二行就可以用来安放24px的icon。如果sprite图片的宽度过大,也会对图片管理形成不便,这时候就可以把头一行的icon换行,放在24px的icon下方即可。
工作中还会碰到一种情况,做好的sprite图,优化得不是很好,出现了大的空隙,同时还有好多小图标放的地方不合适,想把这些图标移到空 隙里面去,这种工作岂不是要一个一个计算图标位置,麻烦可大了。我在这里给大家介绍个经验,开着css文件的同时开着excel,可以给你很大帮助。

如图,icon图标已经按照上面说的方法每21px安放一个,每个的位置我都很清楚,第一个图标的定位是-735px 0,第二个图标的定位是-756px 0。需要移动的图标在同一横行,图标数是23个。然后我把需要调整的icon整行剪切到图中另外一个位置,记下第一个图标在新位置的定位-63px -242px,第二个图标在新位置的定位是-84px -242px。于是把这两组数按图写进excel表里,并向下拉出共23行的等差数列,23个图标新旧位置的对应关系便出来了。然后在css中查找原来的 值并替换新值即可。如果找不到原来的值,说不定是原来在工作中为了处理特殊效果改变了正常的定位,后面做出“无”标记,单独处理就可以了。
总结
所以说,写好一个sprite对今后维护是多么重要的事情呵。下课~

[转载]11个IT人士必备的Chrome 插件

mikel阅读(1305)

[转载]11个IT人士必备的Chrome 插件 – Memento.. – 博客园.

Chrome 浏览器现在可谓如日中天,与 Firefox 共同蚕食着 IE 的市场,网页开发者们可能也会开始转向这一新兴的浏览器,来调校自己的网站。而随着 Chrome 插件作者们的介入,为网页开发者提供便利的插件也纷纷崭露头角。

1. Firebug Lite

firebuglite

Firebug 绝对是最受网页开发者喜爱的 Fifefox 插件(没有之一)。通过它可以在浏览器中查看并编辑任何网页的 HTML,CSS 以及 JavaScript,并在修改的同时地看到改动后的效果。Firebug Lite 是针对 Chrome 浏览器的一个精简版本,可以用来查找网页中的错误以便快速更正。

尽管 Firebug Lite 尚不能包括 Firebug 所有功能,但也已经秉承其精粹,且已经提供了针对高级用户控制台界面。

2. IE Tab

ietab

微软的 Internet Explorer 浏览器会让很多网页设计者头痛,但目前为止在大众范围内仍是被使用最多的浏览器。IE Tab 扩展实际上是在 Chrome 的一个标签页里用 IE 打开网页,通过它你可以查看网页在 IE 用户的眼里是否显示正常。

3. Eye Dropper

eyedropper

通 过 EyeDropper,可以查看 Chrome 浏览的网页中任意颜色的信息。点击扩展的按钮,会打开一个下拉式的色轮界面,其中有一个取色器按钮(Pick color from webpage),点击它,再点击网页中任何位置,就可以查看所点击位置像素的颜色在色轮中的位置、RGB 水平以及 HTML 颜色代码。

4. Chrome SEO

measureit

安装好该插件后点击插件按钮就会显示当前网站与搜索引擎优化相关的信息,包括反向链接,Alexa排名、Google PageRank排名等流量值数,在社会化书签网站中的热门程度等。

5. Lorem Ipsum Generator

loremipsum

Lorem Ipsum Generator 扩展可以用来在设计网页时生成填充网页内容的文本,用以调适格式,免去手动输入此类文字浪费的时间。该插件十分小巧,在易于使用的同时也不会占用过多的内存,在需要时可以信手拈来。

6. Resolution Test

resolutiontest

顾名思义,Resolution Test 就是通过调整浏览器的大小来查看网站在不同的常见分辨率下的情况。作为网页设计者一般都会配备高分辨率的显示器,但一般的网页访问者来说通常都不会这么奢侈,这个扩展的作用就是用来确保网站的格式在这部分人看来也是正常的。

7. Speed Tracer

speedtracer

Speed Tracer 通过浏览器内建的测量工具来记录网页应用在执行不同任务时所用的时间,以便于开发者找到致使网站运行缓慢的原因。该插件可以显示浏览器在解读执行布局、JavaScript时所有的时间以及其它一些细节。

这个插件唯一的缺点在于,必须使用“–enable-extension-timeline-api”这个参数来启动 Chrome 浏览器才能让其正常运作。但既然是网站开发者,这点麻烦就是小菜一碟了,对吧?

8. MeasureIt!

measureit

MeasureIt! 名字就很直观。它可以显示出所浏览网页中任意元素的尺寸(像素宽度和高度)。和这个列表中很多插件一样,这个插件也有 Firefox 版本。

9. 1-Click Web Proxy

地址: https://chrome.google.com/extensions/detail/kjdehhkgdgjcekacdccoflccmhbkefce

这个插件应该是国人做的。因为她的中文名字是——  一键翻墙!

她已经连续一个月排到Chrome Extension 官方Top Rated的第7名了~ 囧~ 看来还真是迎合国民的需求啊~

真相在这里:https://chrome.google.com/extensions/list/rating

做IT的经常去国外网站查资料,遇到打不开的网页,比如google groups 、blogspot等,只需要点击这个插件的按钮就可以了。速度还挺不错。

10. Pendule

pendule

Pendule 会弹出一个简单易用且设计精美的控制面板,其中包含了很多对于开发者来说很有帮助的任务选项。比如重新载入或是禁用 CSS,查看 JavaScript 代码,隐藏图片,取色器,测量尺,查看页面源代码,以及多种编码验证工具等。是一个很不错的功能基础且全面的开发者用扩展。

11. BuiltWith

builtwith

BuiltWith 可以给出关于当前网页的一个资料信息,列出了网站中所使用的相关技术。它会显示网页中所使用的小挂件、网站管理员所用的网站流量分析追踪服务、网页所使用的框架以及广告平台等等。

[转载]C#生成CHM文件(入门篇)

mikel阅读(1237)

[转载]C#生成CHM文件(入门篇) – Alexis – 博客园.

HTML Help Workshop介绍:微软出品的HTML Help WorkShop制作chm文件的最佳工具。

本文,我们将用编程的方法来实现将html文件编译成CHM文件。在开始编程之前,我们有必要了解下HTML Help Workshop是怎么生成CHM的。

HTML Help Workshop编译成CHM文件需要如下三个文件,分别以hhp,hhc,hhk为文件后缀名。

hhp:CHM工程文件,CHM目标文件属性95%的参数都在这里被确定.
hhc,列表文件,确定目标文件中左侧树形列表中”目录”选项卡下的内容.
hhk,索引文件,确定目标文件中左侧树形列表中”索引”选项卡下的内容.
hhp几乎就是一个标准的ini文件.分为三个小节Option,Windows,Files.

典型的配置文件(hhp)结构如下:

[OPTIONS]
Compatibility=1.1 Or later
Default window=Main
Default font=宋体,9,1
Contents file=test.hhc
Index file=test.hhk
Display compile progress=Yes
Full-text search=Yes
Language=0X804 中文(中国)

[WINDOWS]
Main=,”test.hhc”,”test.hhk”,,,,,,,0x20,0xB4,0x104E,[80,60,720,540],0x0,0x0,,,,,0

[FILES]
NewTopic.html

稍微解释下:

Default window=Main:默认的显示模式,这里是主页面

Default font=宋体,9,1:默认的字体

Contents file=test.hhc:内容文件

Index file=test.hhk:索引文件

Display compile progress=Yes:是否显示编译过程

Full-text search=Yes:是否全文搜索

Language=0X804 中文(中国):默认语言

索引文件(hhk)也是一个HTML文件,它包含若干个关键词,当用户打开chm文件后,单击索引标签并输入一个关键词后,chm文件将显示与这个关键词有关的主题的列表,使大家非常方便地找到相关主题。 典型的文件结构如下:

代码
DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> <HTML> <HEAD> <meta name="GENERATOR" content="Microsoft® HTML Help Workshop 4.1">   HEAD> <BODY> <UL>  <LI> <OBJECT type="text/sitemap">  <param name="Name" value="NewTopic">  <param name="Local" value="NewTopic.html">  OBJECT> UL> BODY> HTML>
 
内容页项目资源hhc)文件结构如下:
代码
DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> <HTML> <HEAD> <meta name="GENERATOR" content="Microsoft® HTML Help Workshop 4.1"> HEAD> <BODY> <OBJECT type="text/site properties">  <param name="Window Styles" value="0x237"> OBJECT> <UL>  <LI> <OBJECT type="text/sitemap">  <param name="Name" value="NewTopic">  OBJECT> <UL>  <LI> <OBJECT type="text/sitemap">  <param name="Name" value="NewTopic">  <param name="Local" value="NewTopic.html">  OBJECT> UL> UL> BODY> HTML>
 

用C#编程实现编译,其实是利用Process类来调用exe实现的。
代码
Process helpCompileProcess = new Process(); //创建新的进程,用Process启动HHC.EXE来Compile一个CHM文件  try  {  //判断文件是否存在并不被占用  try  {  string path = _chmFile; //chm生成路径  if (File.Exists(path))  {  File.Delete(path);  }  }  catch  {  throw new Exception("文件被打开!");  }  ProcessStartInfo processStartInfo = new ProcessStartInfo();  processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;  processStartInfo.FileName = hhcFile; //调入HHC.EXE文件  processStartInfo.Arguments = "\"" + Path.GetFullPath(GetPathToProjectFile()) + "\"";//获取空的HHP文件  processStartInfo.UseShellExecute = false;  helpCompileProcess.StartInfo = processStartInfo;  helpCompileProcess.Start();  helpCompileProcess.WaitForExit(); //组件无限期地等待关联进程退出  if (helpCompileProcess.ExitCode == 0)  {  MessageBox.Show(new Exception().Message);  return false;  }  }  finally  {  helpCompileProcess.Close();  }  return true;
 

附件是项目,.Net4.0的,有兴趣的可以在其他版本上也实现下,只要将文件拷过去即可。

如果是vs2010,直接运行项目即可,在运行项目之前可以先把CreateChm\bin\Debug目录下的hhp、hhc、hhk、chm文件全部删掉,运行程序后后生成这些文件。

PS:我尝试将一些引用js文件和图片的html文件,将他们编译为chm文件时,这些js文件和图片能够自动被包含到chm文件中,呵呵,这样就可以创建丰富多彩的chm文件了,如我给的demo中,指针就是一个漂亮的时钟,关于更复杂的CHM编程,稍后带来。

PS:如果觉得的好的话,请点推荐,如果值得收藏的话,请点收藏,3Q

C#创建简易CHM文件Demo

[原创]ASP.NET MVC 使用模板引擎AderTemplateEngine进行视图解析

mikel阅读(1136)

ASP.NET MVC 使用AderTemplateEngine模板引擎进行视图显示

1. 创建ArtTemplateViewLocator视图文件定位类,代码如下:

namespace ArtLib

{

class ArtTemplateViewLocator : ViewLocator

{

public ArtTemplateViewLocator()

{

base.ViewLocationFormats = new string[] { “~/Views/{1}/{0}.htm”,

“~/Views/{1}/{0}.html”,

“~/Views/Shared/{0}.htm”,

“~/Views/Shared/{0}.html”

};

base.MasterLocationFormats = new string[] { “” };

}

}

}

2. 创建VariableResolver类用于ArtTemplate模板视图解析,并注册自定义组件TagList,代码如下:

namespace ArtLib

{

public static class VariableResolver

{

public static object ArtTemplateResolve(string filePath,IDictionary viewData)

{

//初始化模板引擎

TemplateManager template1 = TemplateManager.FromFile(filePath);

//设置模板数据

template1.SetValue(“ViewData”, viewData);

//注册自定义的标签

template1.RegisterCustomTag(“list”, new TagList());

return template1.Process();

}

}

}

3. 创建ArtTemplateViewEngine类用于处理视图请求,并赋予ViewData给模板引擎,代码如下:

IViewLocator _viewLocator = null;

public IViewLocator ViewLocator

{

get

{

if (this._viewLocator == null)

{

this._viewLocator = new ArtTemplateViewLocator();

}

return this._viewLocator;

}

set

{

this._viewLocator = value;

}

}

public string TemplatePath { get; set; }

#region IViewEngine 成员

public void RenderView(ViewContext viewContext)

{

string viewLocation = ViewLocator.GetViewLocation(viewContext, viewContext.ViewName);

if (string.IsNullOrEmpty(viewLocation))

{

throw new InvalidOperationException(string.Format(“View {0} could not be found.”, viewContext.ViewName));

}

string viewPath = HttpContext.Current.Request.MapPath(viewLocation);

//以下为模板解析

string viewTemplate = VariableResolver.ArtTemplateResolve(viewPath, viewContext.ViewData) as string;

HttpContext.Current.Response.Write(viewTemplate);

}

#endregion

4. 创建ArtTemplateControllerFactory类,用于Golbal.asax进行视图绑定,代码如下:

namespace ArtLib

{

public class ArtTemplateControllerFactory : DefaultControllerFactory

{

protected override IController CreateController(RequestContext requestContext, string controllerName)

{

Controller controller = (Controller)base.CreateController(requestContext, controllerName);

controller.ViewEngine = new ArtTemplateViewEngine();//修改默认的视图引擎为我们刚才创建的视图引擎

return controller;

}

}

}

5. 创建自定义的模板标签类:TagList.cs用于显示数据列表,代码如下:

namespace ArtLib

{

public class TagList : ITagHandler

{

#region ITagHandler 成员

public void TagBeginProcess(TemplateManager manager, Ader.TemplateEngine.Parser.AST.Tag tag, ref bool processInnerElements, ref bool captureInnerContent)

{

processInnerElements = true;

captureInnerContent = true;

}

public void TagEndProcess(TemplateManager manager, Ader.TemplateEngine.Parser.AST.Tag tag, string innerContent)

{

Expression exp;

exp = tag.AttributeValue(“pageSize”);

if (exp == null)

throw new Exception(“Missing attribute: pageSize”);

string pageSize = manager.EvalExpression(exp).ToString();

exp = tag.AttributeValue(“currentPage”);

if (exp == null)

throw new Exception(“Missing attribute: currentPage”);

string currentPage = manager.EvalExpression(exp).ToString();

Business business = new BusinessLogic();

List<InformationSimple> list = new List<InformationSimple>();

if (string.IsNullOrEmpty(pageSize))

{

list = business.Select<InformationSimple>();

}

else

{

Page page = new Page();

page.PageSize = Convert.ToInt32(pageSize);

page.CurrentPage = Convert.ToInt32(currentPage);

list = business.SelectByPage<InformationSimple>(ref page);

}

String html = “”;

foreach (InformationSimple info in list)

{

html = html + “<tr><td>” + info.InfoTitle + “</td></tr>”;

}

html = “<table>” + html + “</table>”;

manager.WriteValue(html);

}

#endregion

}

6. 修改ASP.NET MVC的测试项目的Global.asax文件的Application_Start()方法,加入自定义控制器工厂类:ArtTemplateControllerFactory,代码如下:

protected void Application_Start()

{

ControllerBuilder.Current.SetControllerFactory(typeof(ArtTemplateControllerFactory));

RegisterRoutes(RouteTable.Routes);

}

7. 创建模板文件Views/Home/Index.htm,代码如下:

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<html xmlns=”http://www.w3.org/1999/xhtml” >

<head>

<title></title>

</head>

<body>

<ad:list pageSize=”10″ currentPage=”1″></ad:list>

#ViewData[“Title”]#

</body>

</html>

8.

[转载].NET模板引擎 EFPlatform.CodeGenerator (代码生成器 静态页生成 生成HTML 模板)

mikel阅读(869)

[转载].NET模板引擎 EFPlatform.CodeGenerator (代码生成器 静态页生成 生成HTML 模板) – Eric’s Bloggy – 博客园.

这个东东是去年我看着ASP:标记突发奇想花4天 时间设计编写的类库, 原名叫 HtmlGenerator, 最近发现PHP和JAVA有很多类似的项目, 但是都设计的很渣(不同意的表打我@_@), 于是把 HtmlGenerator 重构了一下, 改叫 CodeGenerator. 配合我的数据库迁移工具和数据库实体类生成品….. 好像跑题了 -____-

CodeGenerator 的特点:
1. 标记简结实用, 所有网页美工都能在一分钟内掌握. 而且不与HTML标准冲突, 模板页可用任何WYSIWYG工具编辑, 和编辑普通HTML网完全相同.
2. 标记只与表示层相关, 不包括任何业务逻辑, 丝毫不影响你应用多层结构.
3. 标记到后台被解析成了生成器对象, 完全面向对象, 不像绝大多数生成器要死嗑字符串.
4. 生成器对象使用DataSource属性取得数据, DataSource可以为  简单值类型(如 int, DateTIme), 也可以为简单数组(如 decimal[], string[]), 还可以为ADO.NET数据集(如DataTable), 甚至单个对象实体或对象集合或列表(如 SomeClassCollection, List<SomeClass>), 所有数据源类型通吃! 哈哈, 比ASP.NET带的数据控件支持的类型还多.
5. 标记的Name直接与数据源的列名ColumnName或属性名PropertyName, 好处不言而喻了吧.
6. 说到这里好了, 留一手先. 呵呵

演示程序下载地址: http://files.cnblogs.com/ericfine/Demo.rar
EFPlatform.CodeGenerator 源代码下载地址: http://files.cnblogs.com/ericfine/EFPlatform.CodeGenerator.rar (过时了)
EFPlatform.TemplateEngine 源代码下载地址: http://files.cnblogs.com/ericfine/EFPlatform.TemplateEngine.rar (其实就是CodeGenerator的优化版:))

应用项目:
http://portray.mz99.com/
http://music.mz99.com/
http://joke.mz99.com/
http://www.mcuol.com/

应用流程:

Default.aspx.cs:

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.Common;
using System.IO;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using EFPlatform.TemplateEngine;

public partial class _Default : Page
{
private string outputPath;
private string categoryFileName;
private string productFileName;
private static DbProviderFactory dbFactory;
private DbConnection connection;

protected void Page_Load(object sender, EventArgs e)
{
outputPath
= Server.MapPath(./);
categoryFileName
= string.Format(@”{0}\Template\Category.html, outputPath);
productFileName
= string.Format(@”{0}\Template\Product.html, outputPath);
string currentConnection = ConfigurationManager.AppSettings[Connection];
ConnectionStringSettings css
= ConfigurationManager.ConnectionStrings[currentConnection];
this.GetConnection(css);
}


private void GenerateCategory()
{
string template = Helper.ReadTextFile(categoryFileName);
Generator gen
= new Generator(template);
gen.ParseTemplate();
Region rgnTitle
= gen.GetRegion(Title);
Region rgnCategory
= gen.GetRegion(Category);
Region rgnProducts
= gen.GetRegion(Products);
Region rgnNavigator
= gen.GetRegion(Navigator);

if(rgnTitle == null || rgnCategory == null || rgnProducts == null || rgnNavigator == null)
{
Response.Write(
Missing region.);
return;
}


int categoryId;
string outputFileName;
DataView dvCategory
= this.GetCategoryTable().DefaultView;
Pager pgrCategory
= new Pager(1, dvCategory.Count);

for(int i = 0; i < pgrCategory.PageCount; i++)
{
rgnTitle.DataSource
= (string)dvCategory[i][CategoryName]; //Use a string as data source
rgnCategory.DataSource = dvCategory[i]; //Use a DataRowView object as data source
pgrCategory.CurrentPage = i + 1;
rgnNavigator.DataSource
= pgrCategory; //Use a Pager object as data source
categoryId = (int)dvCategory[i][CategoryID];
rgnProducts.DataSource
= this.GetProductTable(categoryId); //Use a DataTable object as data souce
outputFileName = string.Format(@”{0}\Html\Category{1}.html, outputPath, categoryId);
Helper.WriteTextFile(outputFileName, gen.Generate());
}

}


private void GenerateProduct()
{
string template = Helper.ReadTextFile(productFileName);
Generator gen
= new Generator(template);
gen.ParseTemplate();
Region rgnTitle
= gen.GetRegion(Title);
Region rgnProduct
= gen.GetRegion(Product);
Region rgnNavigator
= gen.GetRegion(Navigator);

if(rgnTitle == null || rgnProduct == null || rgnNavigator == null)
{
Response.Write(
Missing region.);
return;
}


string outputFileName;
List
<Product> productList = this.GetProductList();
Pager pgrProduct
= new Pager(1, productList.Count);

for(int i = 0; i < pgrProduct.PageCount; i++)
{
rgnTitle.DataSource
= productList[i].CategoryName; //Use a string as data source
rgnProduct.DataSource = productList[i]; //Use a Product object as data source
pgrProduct.CurrentPage = i + 1;
rgnNavigator.DataSource
= pgrProduct; //Use a Pager object as data source
outputFileName = string.Format(@”{0}\Html\Product{1}.html, outputPath, productList[i].ProductID);
Helper.WriteTextFile(outputFileName, gen.Generate());
}

}


DataSourcePreparing

protected void Button1_Click(object sender, EventArgs e)
{
this.GenerateCategory();
}


protected void Button2_Click(object sender, EventArgs e)
{
this.GenerateProduct();
}

}

Web.config:

<?xml version=”1.0″?>
<configuration>
<system.web>
<compilation Debug=”true” />
<authentication mode=”Windows” />
<customErrors mode=”Off” defaultRedirect=”GenericErrorPage.htm”>
<error statusCode=”403″ redirect=”NoAccess.htm” />
<error statusCode=”404″ redirect=”FileNotFound.htm” />
</customErrors>
</system.web>
<connectionStrings>
<add name=”Access” providerName=”System.Data.OleDb” connectionString=”Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|Northwind.mdb”/>
<add name=”SQLExpress” providerName=”System.Data.SQLClient” connectionString=”Data Source=.\SQLExpress;Integrated Security=True;User Instance=True;Database=Northwind;AttachDBFilename=|DataDirectory|Northwind.mdf”/>
</connectionStrings>
<appSettings>
<add key=”Connection” value=”Access”/>
</appSettings>
</configuration>