mercredi 28 mars 2012

学习之模块架构 DotNetNuke 6

前面的博客介绍了:

博客园原文地址 :  学习之模块架构 DotNetNuke 6

这篇博客主要是讲模块的架构和加载,以及模块与DotNetNuke门户网站(Portals)系统的关系。充分了解模块可以帮助DNN开发者根据需要更清晰的构建模块。
在DNN中,模块是一个可插入的用户接口组件,用来处理请求并生成动态的内容。它只能出现在ASP.NET页面上,而页面可以包括任意数量的模块"实例"。
整个模块架构包括四个部分 : 门户网站(Portal),页面(Tab),模块(Module)和模块容器(Container)。

  • 门户网站(Portal)
Portal可以定义为一个基于Web的应用程序,从不同的源聚集内容,并寄宿信息系统的表示层(模块)。下图描述了Portal的基本架构,DNN处理页面请求时需要执行许多步骤。下述步骤在页面初始化的过程中执行,用来在运行时动态地加载模块。动态创建的模块然后就能够处理它们自己的生存周期,包括诸如初始化、加载、呈现等各种事件。

图一 : Portal的基本架构

第一步: 页面配置检索(Page Configuration Retrieval)

第1步就是为被请求的页面检索模块。检索步骤由许多重要的信息块构成,例如页面上出现的各个模块、模块在页面上显示的区域(即内容窗格Pane),以及与每个模块相关联的安全角色。
//Default.aspx.cs//OnInit//load skin control and register UI js
UI.Skins.Skin ctlSkin = UI.Skins.Skin.GetSkin(this);
//add skin to page
SkinPlaceHolder.Controls.Add(ctlSkin);

//DotNetNuke.UI.Skins.Skin.cs : OnInit()
bool success;
//Load the Module Control(s)
success = Globals.IsAdminControl() ? ProcessSlaveModule() : ProcessMasterModules();

//DotNetNuke.UI.Skins.Skin.cs : ProcessMasterModules()
bool success = true;
if (TabPermissionController.CanViewPage())
{
  //check portal expiry date
  if (!CheckExpired())
  {
    if ((PortalSettings.ActiveTab.StartDate < DateAndTime.Now && PortalSettings.ActiveTab.EndDate > DateAndTime.Now) || TabPermissionController.CanAdminPage() || Globals.IsLayoutMode())
    {
      //dynamically populate the panes with modules
      if (PortalSettings.ActiveTab.Modules.Count > 0)
      {
        foreach (ModuleInfo objModule in PortalSettings.ActiveTab.Modules)
        {
          success = ProcessModule(objModule);
        }
      }

第二步: 安全审计(Security Audit)

第2步就是判断在上一步中检索出来的安全信息。通过检查当前用户的角色(是注册用户还是匿名用户)以及与每个模块相关联的查看角色,就可以为当前页面形成一列经过“授权”的模块。
private Boolean ProcessModule(ModuleInfo module)
{
  bool success = true;
  if (ModulePermissionController.CanViewModule(module) && module.IsDeleted == false &&
((module.StartDate < DateTime.Now && module.EndDate > DateTime.Now) || Globals.IsLayoutMode() || Globals.IsEditMode()))
  {
  //...
  }
  //...
}

第三步:内容注入(Content Injection)

第3步(也是最后一步)就是将“授权”模块动态地插入到页面上相应的内容窗格中。在所有的模块加载之后,每个模块就能够执行各自的事件并呈现内容。
Pane pane = GetPane(module);
if (pane != null)
{
  success = InjectModule(pane, module);
}

  • 页面(Tab)
图二描述了基本的Portal的Tab组件。页面本身表示一个完整的标记文档,由大量的内容窗格(Pane)组成,并且在每个内容窗格中还包含大量的模块。

图二:页面组件

每个模块都包含一个标题、若干装饰(Container)以及由模块生成的内容。装饰可以包括若干按钮、链接以及一个改变模块状态或者执行与模块相关功能的悬浮菜单。

  • 模块(Module)
正如前面所述,Portal是基于Web的应用程序,处理各种请求并生成动态内容。每个模块都生成自己的标记块(称为段),再和皮肤的标记一起展示完整的文档。
因为每个模块都生成自己的标记,所以可以将模块视为较大应用程序中的微型应用程序。通常,用户通过单击链接或者提交表单(所提交的表单由门户网站系统及传递给相应模块的命令处理)与每个模块生成的内容交互。

  • 模块容器(Container)
模块周围的装饰称为模块容器。通过容器,用户能够与模块交互,执行诸如最小化、最大化以及其他高级特性(如果用户拥有该页面的编辑特权)的动作。
图三示范了一个HTML模块在用户以编辑特权登录时的模块容器。这个模块容器包含许多项,例如拥有一列管理选项的悬浮菜单、模块的标题。

图三:模块容器

DotNetNuke est le plus gros projet open-source en technologie .Net.

lundi 26 mars 2012

分享之数据库实体关系图 DotNetNuke 5.6.1

下图所示是DotNetNuke 5.6.1社区版的ERD(Entity-Relationship Diagram). 找了好久只找到这个版本的,估计不是官方的,是一个叫R2i的公司在维护的。但我觉得这个已经足够了,因为5.6.x是DNN 6之前的最后一个版本,所以我觉得DNN 6和它之间内核库不会有Break changes,当然少许的改动或优化总是有的。
为什么要分享这个图呢? 因为我觉得ERD对我们理解全部DNN的架构非常重要,并且能够帮助我们减少开发第三方模块的时间。
在下图中,表框的不同颜色表示了他们类别的不同 :
  • 蓝色 : 认证系统,比如用户认证,页面模块查看权限...
  • 红色 : 内容管理,比如皮肤,页面...
  • 绿色 : 辅助系统,比如异常记录,任务...
  • 黑色 : 配置系统,比如模块定义,语言包...
  • 灰色 : 第三方核心插件,比如Text/HTML模块,搜索模块...




这个图是有点小了,估计大家看不清楚。所以提供PDF下载外加MetaData下载 : ERD PDF || METADATA XLS
希望想学习或想了解DNN的园友看完之后,对DNN的Architecture有更全面的了解。5 jours avant 01 Avril !

vendredi 23 mars 2012

如何创建新模块 DotNetNuke 6 & Entity Framework Code First

Soleil 索引 :
第一部分:开发新模块 - DNN6

Étoile 如果你还不知道DotNetNuke是什么的话,请访问 www.dotnetnuke.com
Étoile 如果你还不知道如何在本地安装DNN 6, 请猛戳 http://codeciel.blogspot.fr/2012/03/how-to-install-dotnetnuke-6-on-local.html
Arc-en-ciel 如果你想要知道如何开发一个你自己的DNN6模块,那么这篇文章就是你需要的。


  • 步骤1:通过DNN6 Host创建desktop module和module definition
从数据库的角度出发,这一步会把新模块的相关信息存入数据库,让DNN可以识别,这样你就可以把这个模块加入任意页面。如果你仔细看了DNN数据库的结构后,你会发现有很多和模块(Module)相关的表 - dbo.DesktopModules, dbo.Modules, dbo.ModuleDefinitions, dbo.TabModules, dbo.PortalDesktopModules. 这儿不会细讲这些表的用途,如果可以的话,有机会我会专门为此写一篇博客。
所以,现在你只要按照下面的步骤就可以创建一个属于你的DNN模块 :
  - 用host账户登入你的DNN6网站
  - 点击Host页面,再进入Extensions页面
  - 单击Manage按钮, 选择Create New Module,你将会看到(如Figure 1所示):
提示: 如果你找不到Manage按钮,请确认你的页面模式(通常在右上角可以看见)是Edit而不是View或Layout。
1
Figure 1 : 创建模块
  - 填好这些文本框后。(最后把"Add Test Page ?"打上勾,以简化步骤)
  - 单击“Create Module”, 然后你就可以看见新的模块已经出现在了“TestEFCodeFirstPage”页面上(如Figure 2 所示)了
2
Figure 2 : 新页面里包含了新模块

  • 步骤2:把新模块与VS项目联系起来
  - 现在打开VS2010,创建新项目,如Figure 3 所示。
提示:值得注意的事,项目的名字必须与module的名字相同,即“EFCodeFirst”,开始的时候你可以把这个项目保存到任何位置,因为一旦完成创建之后,我们会把这个文件夹移动到<网站根目录>/DesktopModules里,合并这俩个文件夹。
3
Figure 3 : 创建新vs2010项目
  - 再次用VS2010打开“EFCodeFirst.csproj”. 因为我们还需要配置这个项目,来让它可以顺利的在DNN6下编译和运行。
  - 点击项目属性,然后进入到Compiler页面,修改输出路径为<网站根目录>\bin\
  - 如果你Site的运行环境是.net framework version 2.0.50727.5448的话,请在IIS里修改Site的application pool为ASP.NET V4.0。因为EF Code First是需要.net 4.0的。
  - 添加Dotnetnuke.dll引用,它可以在<网站根目录>\bin\下找到。需要注意的是在属性里将copy local设置为false。
提示:上面这种添加Dotnetnuke.dll引用的方法不是企业开发常用的,或者说是应该避免的才比较正确。因为Dotnetnuke不断在更新,为了保证团队开发时,Dotnetnuke.dll引用都是同一个版本,我们通常会固定一个稳定的版本来开发。具体操作是:存放指定版本Dotnetnuke.dll的文件夹是共享的,所有的dnn引用都是指向这个文件夹的。
  - 重命名web.config文件为web.config.old,因为在网站的根目录已经有了一个web.config。
  - 删除EFView.ascx文件
  - 添加一个新文件,文件类型是Web User Control,还是命名为“EFView.ascx ”,以便DNN能识别。
  - 打开文件EFView.ascx, 我们随便写点东西进去,比如 : “This is my first dnn6 module”
  - 打开文件EFView.ascx.cs,将它的基类换成PortalModuleBase,保存并编译这个项目
  - 刷新页面http://dnn614/TestEFCodeFirstPage.aspx,你将会看到如Figure 4所示 :
4
Figure 4 : 测试页面和行模块

好了,看到这里你就应该知道如何创建一个DNN6模块了。在这个模块里,你可以根据需求,随意开发。下面的第二部分就是,在一个DNN模块里使用Entity Framework Code First进行实战开发。




第二部分 : DNN模块里使用EF Code First

Pouce levé 这部分是基于这篇文章: Introduction to Entity Framework Code First


  • 步骤 3* : Entity Framework 简介
在我直接进入正题之前,我想先介绍一下EF。EF是一个.NET平台下的ORM框架,个人觉得做的很不错,之前还接触过另外俩款在.NET平台下的ORM - LLBLGen Pro和NHibernate。LLBLGen Pro自从收费之后,功能也越来越强大,用起来也挺顺手的,之所以没有继续用的原因很简单:我现在这个客户公司,不想花钱买它的licence。NHibernate是从Java版的Hibernate移植过来的,就好比Lucene.NET与Lucene的关系一样,不同的是Lucene.NET早早就进Apache的孵化器了,而NHibernate的生命力还很强大。我没有用NHibernate的原因也很简单,被它的配置文件惊吓住了。比较这三款的优缺点不是这里的重点,每个人的习惯和思考方式不一样,所以喜好自然不同,选一款自己用的顺手又顺心的ORM就可以了。下面开始介绍EF的三种使用方法 :
EF在4.0的时候只提供俩种与实体交互的方法,即数据库优先模型优先。前一种情况下,你在开发你的应用前开始设计数据库。然后你可以用VS自带的实体数据模型设计工具来设计一个虚拟模型,操作很简单:直接从数据库把表拖拽到设计器中(如Figure 5所示)。后一种情况下,我们先用实体数据模型设计工具来手工设计模型(如Figure 6所示),然后指定数据库的连接。但不管是前面哪种情况,你都要使用实体数据模型设计器来生成你的数据模型对象。

2-1
Figure 5 : 数据库优先

2-2
Figure 6 : 模型优先

EF在4.1中引入一种新的模式来生成模型对象 : 代码优先(Code First)。在代码优先这种方式里,你不会遇到任何设计器。先全部用.NET Framework来搭建对象类,然后用一些特定属性和相关技术来生成EF数据模型。(如Figure 7一样)

2-3
Figure 7 : 代码优先

上面大致讲了一下这三种方法,如果你感觉有点混淆,静下心来,仔细看Figure 8,我相信你肯定会清楚不少。在我们这个模块中,我们使用的是最后一种。


2-4
Figure 8 : EF与实体交互的方式

第二部分的目的不仅仅是完成我们的模块,而是一步一步的,让大家弄清楚使用EF Code First的全部过程。接下来,在开发模块,你将处理一个用来表示博客帖子的数据模型,实际上,数据是驻留在SQL Server里一个名叫BlogPosts表中的。通过使用模型对象,你能够从表中读写数据。


  • 步骤 3 :  创建模型
假设我们的数据模型是用来储存博客帖子和博客贴分类的。根据三层架构的思想,我们应该另外创建一个project来专门开发数据模型 :在与“EFCodeFirst”项目同一个solution里创建Library类型的新项目,命名为“EFCodeFirstLib”。这个类库项目里将会包括俩个模型对象,即BlogPost和Category。他们的模型代码如下展示 :
提示: EFCodeFirstLib项目的文件夹应该放在<网站根文件夹>/DesktopModules/, 并且其编译路径应该是<网站根文件夹>/bin/.
public class BlogPost
{
  public Guid Id { get; set; }
  public string Title { get; set; }
  public string Content { get; set; }
  public DateTime PublishDate { get; set; }
  public virtual Category Category { get; set; }
}
  
public class Category
{
  public Guid Id { get; set; }
  public string Name { get; set; }
  public virtual ICollection<BlogPost> BlogPosts { get; set; }
}

在BlogPost类中,定义了五个属性: Id, Title, Content, PublishDate 和 Category。注意里面的Category是外键。Category类有三个属性:Id, Name 和 BlogPosts。其中的BlogPosts 是一个属性集合,因为可以有很多个博客帖子属于同一个category。需要记住的是,默认情况下,表示主键的属性类型应该是int或Guid。当然,你可以用一些attributes定制主键。我们将在后面讨论。


  • 步骤4 : 创建Data Context
现在模型对象都已经创建好了,让我们开始创建一个Data Context,通过它可以让你查询和处理实体数据,另外,它的基类是DbContext类。下面就是我们在模块中要使用的Data Context:
public partial class BlogContext : DbContext
{
  public BlogContext():base("BlogDb")
  {
  }

  public DbSet<BlogPost> BlogPosts { get; set; }
  public DbSet<Category> Categories { get; set; }
}
BlogContext类继承了DbContext类。在它的构造函数中,调用了基类的构造器并且传递了所需的数据库名称。当你首次运行应用时,将会为你用这个名字创建数据库。如果不传递这个名称,默认创建数据库的名字将会是DbContext类的fully qualified name。在我们这个例子中就是“EFCodeFirstLib.BlogContext”。
BlogContext类定义了俩个公共属性,即BlogPosts和Categories。这些属性的类型是DbSet。DbSet类代表了一个实体集(从数据库角度,就是一个数据库的表),可以执行CRUD(创建,读取,更新,删除)操作


  • 步骤5 : 测试数据库的生成(可选)
我们现在可以测试我们已经写的代码了,当然你也可以选择跳过这一步。
首先在EFCodeFirst项目的“EFView.ascx”中添加一个按钮(button),并且生成相应的按钮点击事件方法。加入我们刚刚创建的EFCodeFirstLib项目的引用。



Figure 9 : 测试页面


然后在按钮点击事件方法中写入以下代码:
using (var db = new BlogContext())
{
  Guid id = Guid.NewGuid();
  var cat = new Category { Id = id, Name = "ASP.NET" };
  var post = new BlogPost { Title="Title1", Content="Hello World!", PublishDate=new DateTime(2011,1,1), Category=cat};
  db.Categories.Add(cat);
  db.BlogPosts.Add(post);
  int i = db.SaveChanges();
}
上面的代码创建了一个BlogContext实例,接着创建了Category和BlogPost类的各自实例。把新创建的实体实例加入到DbSets里面,最后调用SaveChanges()方法。 SaveChanges()方法将持久化加入的实体数据,也就是把实体数据写入数据库相应的表中,并且返回此次操作执行的记录数。
现在我们编译这俩个项目,在浏览器中打开http://dnn614/TestEFCodeFirstPage.aspx. 点击页面中的按钮。 因为我们是第一次运行并点击按钮,EF将会在SQL Express里创建新的数据库和表。库名是BlogDb,因为我们在DataContext的构造里已经指出了;俩个表名分别是BlogPosts和Categories。


Sans titre1
Figure 11: SQLExpress里创建的数据库和表

值得注意的是BlogPosts和Categories表里的Id列被设定为主键, 同样BlogPosts表中,有一名叫Category_Id的外键被定义。

  • 步骤6 : 每次运行(点击按钮)时重新创建数据库
在测试时,你也许想要在每次运行应用时都创建或重新创建数据库,以便初始化运行环境。同时也想在创建数据库的时候加入一些测试数据。当你修改了你的实体代码时,因为数据库的表也会相应的改变, 数据库也应该重新创建。默认情况下,EF只会在你首次运行时创建数据库,之后应用会一直操作这同一个数据库。这当然不是我们想要的,因为我们的实体代码会随着需求的变更而修改或增加,为了改变这种默认行为,你需要在代码里创建一个database initializer,并且继承DropCreateDatabaseAlways类。如名字暗示的那样,DropCreateDatabaseAlways类总是会重新创建数据库。下面的代码就是我们自己的BlogContextInitializer :
提示:你也可以继承DropCreateDatabaseIfModelChanges类,它只会在Model改变的时候,重新创建数据库。
public class BlogContextInitializer : DropCreateDatabaseAlways<BlogContext>
{
  protected override void Seed(BlogContext context)
  {
    Category cat1 = new Category { Id=Guid.NewGuid(), Name=".NET Framework" };
    Category cat2 = new Category { Id = Guid.NewGuid(), Name = "SQL Server" };
    Category cat3 = new Category { Id = Guid.NewGuid(), Name = "jQuery" };
    context.Categories.Add(cat1);
    context.Categories.Add(cat2);
    context.Categories.Add(cat3);
    context.SaveChanges();
  }
}
BlogContextInitializer 继承了DropCreateDatabaseAlways 基类,并且重写了Seed()方法,方法里写入了一些往数据库里添加样本数据的代码:添加了三个categories。一旦完成了initializer,你需要添加以下代码到按钮点击事件方法里去:
protected void Button1_Click(object sender, EventArgs e)
{
  Database.SetInitializer<BlogContext>(new BlogContextInitializer());
   ...
   ...
}
现在你就会发现每次点击按钮时,数据库都会重新创建,并且填充样本数据到Categories表里。

  • 步骤7 : 在Code First里使用已有的数据库
上面的代码里,你允许EF自己创建数据。但在许多情况下,你会想要用已经存在的数据库而不是创建一个新的。又因为我们在DNN里使用EF Code First,所以在任何情况下都不可能全部重新创建DNN使用的数据库(DNN614)。我们不得不使用其它的数据库(比如DNN614_BlogDb)。如何让Code First知道我们想要使用那个数据库呢?只需要在web.config的Connection String里指明就可以了:
<connectionStrings>
  <add name="SiteSqlServer" connectionString="Data Source=(local)\LEGAL;Initial Catalog=DNN614;User ID=login614;Password=xxx" providerName="System.Data.SqlClient" />
  <add name="BlogDb" connectionString="Data Source=(local)\LEGAL;Initial Catalog=DNN614_BlogDb;User ID=lgfr;Password=xxx" providerName="System.Data.SqlClient"/>
</connectionStrings>

Sans titre
Figure 12 : 指明已有的数据库

需要注意的地方是,我们在<connectionStrings>里添加的数据库连接字符串的名字,必须和我们在DataContext构造器里指明的一样(“BlogDb”)。
如果你在DataContext没有指明,那么那个数据库连接字符串的名字就必须和DataContext类名一样(“BlogContext”)。
为了让大家更清楚Code First选择数据库连接字符串的流程,我们用这个例子再解释一遍 :
  •   情况一:在DataContext中(BlogContext)指明了名字“BlogDb”
      EF首先会在configuration文件里查找是否有名字为“BlogDb”的数据库连接字符串。
      如果有,EF就会使用这个。如果没有,EF就会在本地的SQL Express中创建一个名为“BlogDb”的新数据库。
  •   情况二:没有在DataContext中(BlogContext)指明
      EF首先也会在configuration文件里查找名为“BlogContext ”的数据库连接字符串。
      如果找到,EF就是使用;否则EF就会在SQL Express里创建一个名为“EFCodeFirstLib.BlogContext”的新数据库。其中EFCodeFirstLib是BlogContext的命名空间。

  • 步骤8 : 使用Data Annotations来标明数据表和键的信息
上面的例子中,当创建实体对象对应的数据库和表时,EF使用的是默认的约定。我们也可以用一些data annotations来定制EF的行为。例如下面代码所示,我们添加了一些data annotations属性来标明表名([Table]),主键([Key]) 和外键([ForeignKey])信息。
[Table("BlogPosts")]
public class BlogPost
{
  [Key]
  public Guid Id { get; set; }
  public string Title { get; set; }
  public string Content { get; set; }
  public DateTime PublishDate { get; set; }
  [ForeignKey("Category")]
  public Guid CategoryId { get; set; }
  public virtual Category Category { get; set; }
}

[Table("Categories")]
public class Category
{
  [Key]
  public Guid Id { get; set; }
  public string Name { get; set; }
  public virtual ICollection<BlogPost> BlogPosts { get; set; }
}

  • 总结 :
Entity Framework Code First允许我们直接在代码使用EF特性,比如未经任何实体数据模型设计。这种方式下,全部使用C#类来创建实体对象,需要定义一个继承了DbContext类的DataContext类,同时可以使用data annotation属性显式地标明相关信息。默认时,当应用第一次运行时,EF会在SQL Express里创建新的数据库;我们可以通过创建自己的数据库初始化策略(Database Initializer)来改变这种默认行为。也可以使用已经存在的数据库,只需在configuration文件里标明了数据库连接字符串。 
Code First相对与其他两种方式来说,有很大的灵活性。但我觉得在DNN中不太适合使用,因为我不是特别能接受一个DNN网站同时有俩个数据库,维护起立不方便。所以,在现实项目中,我经常使用的方式是Database First。
最后友情提供一下本例中的DNN模块安装包和源代码:安装包  源代码Profitez-le et je vous souhaite un très bon weekend !!

jeudi 22 mars 2012

分享几个Web开发必备小抄

摘选自: "20 Cheat Sheets for Web Development you must have".


点击可查看大图!


1) PHP
本人说不上讨厌PHP,却绝对的不喜欢,可能是上学的时候留下的阴影吧。最近正在用Wordpress建站,不得已得用PHP。



2) HTML Character Entities



3) CSS



4) Javascript



5) JQuery 1.3



6) Regular Expressions
不多说了,必须的必备。



7) Apache Mod Rewrite
Url重写,最近在WordPress里会用到它,既可以让url更易读,又可以提高SEO。



8) WordPress Mind Map
一个讲解了WordPress流程的思维导图,非常清晰。
      


9) SEO
做一个优秀的SEO必然要花一番功夫的,有的放矢能事半功倍。
     


小小总结:
以上九个小抄就是我摘录下来的,基本是现在都用的着的。不过有些东东可能正在过时,正在更新好像更准确一些。要是有人或自己能不断更新这些图就好了。Quelle Bonne Idée!



mercredi 21 mars 2012

Juice UI: 整合了jQuery UI的开源ASP.NET Web控件

前言 

这篇文章的原文来自Jon Galloway,想看原文的请猛戳链接。第一次接触这个Juice UI是看到同事分享的邮件,当时只是粗略看看,不过感觉把jQuery UI整合到ASP.NET Web控件里去确实是个不错的主意。今天偶然在网上看到了这篇文章,就动手把它翻译过来,和大家分享。以下是译文:

今天早上的MVP峰会上,Scott Hunter刚刚从appendTo网站新发布了一个开源项目,名字叫Juice UI。Juice UI是一个Web窗体控件的集合,并整合了jQuery UI。你可以通过添加JuiceUI NuGet package到你自己的应用中,立即就可以使用它。同时源码是提供下载的(go nuts with the source), 他的版权协议是基于MIT和GPL的。


Juice UI,能做什么?

jQuery UI 是一个构建在jQuery之上的UI库。它为平常的场景提供了非常多且强大的部件,例如日期选择期,对话框和选项卡等等;并且一些顶尖的js开发者(some of the sharpest Javascript developers in the field)参与开发提供了坚实的基础。虽然你总是可以利用一些使用了jQuery和jQuery UI的库,但是全新的Juice UI控件可以让这些工作更简单。
例如:
   1:  <asp:TextBox runat="server" ID="_Restrict" />
   2:  <Juice:Datepicker
   3:       runat="server"
   4:       TargetControlID="_Restrict"
   5:       MinDate="-20"
   6:       MaxDate="+1M +10D" /> 

执行这段代码,就可以得到:
2012-02-28 09h16_03


组件和行为

Juice UI 发布的时候就已经包括了14个部件或行为。如果你想查看全部控件列表的话,请点击http://juiceui.com/controls, 并且提供互动例子让我们更深入了解控件。
2012-02-28 09h17_29
下面也列出了所有控件,点击可直接转到相应文档:

实战

  • 添加JuiceUI NuGet package
打开VS2010,创建项目前请确保VS2010已安装了NuGet插件。创建一个ASP.NET 4 Web Forms项目。右击项目中的References文件夹,选择Manage NuGet Packages..., 然后找到 "juiceui",点击安装。

2012-02-28 08h10_11

  • JuiceUI 的名字空间
通过NuGet package添加JuiceUI时,NuGet会自动的把Juice UI的名字空间写入到你的web.config文件里, 比如:
   1:  <configuration> 
   2:      <system.web> 
   3:          <compilation debug="true" targetFramework="4.0" /> 
   4:          <pages> 
   5:              <controls> 
   6:                  <add assembly="JuiceUI" namespace="Juice" tagPrefix="juice" /> 
   7:              </controls> 
   8:          </pages> 
   9:      </system.web> 
  10:  </configuration> 

如果确实需要Juice UI名字空间的话,通常我会移除上面这段config,在页面中使用<@Import Namespace="JuiceUI" />指令来添加名字空间。


使用Juice UI控件
首先,你需要一个<asp:ScriptManager> - 把它添加到一个页面上或者你site的Master页面上。
   1:  <asp:ScriptManager id="_Script" runat="server" /> 

添加完成后,你就可以使用控件了。这些都是扩展控件,所以你需要使用TargetControlID属性来指出哪个Web窗体控件将扩展Juice UI的行为。这儿有一个精简了的例子,将DatePicker行为与一个TextBox挂钩:
   1:  <asp:TextBox runat="server" ID="DateSample" /> 
   2:  <Juice:Datepicker runat="server" TargetControlID="DateSample" /> 

另外我把一个可拖拽(Draggable )的行为指向一个Panel:
   1:  <asp:Panel runat="server" ID="DragBox" Style="border:1px solid; width:100px;"> 
   2:      Hi. You can drag me around. 
   3:  </asp:Panel> 
   4:  <Juice:Draggable runat="server" TargetControlID="DragBox" /> 

需要注意的是,这只是非常简单的例子并且没有CSS。在Juice UI源码里有很多更复杂的Juice UI样例。

运行这个页面,我们将会看见我们所期待的:一个拥有日期选择器的textbox和一个可以拖拽的panel。
2012-02-28 10h34_32
下面是这个页面的源代码:
   1:  <%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" 
   2:      CodeBehind="Default.aspx.cs" Inherits="Juice_Sample._Default" %> 
   3:  <asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent"> 
   4:  </asp:Content> 
   5:  <asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent"> 
   6:   
   7:      <asp:ScriptManager id="_Script" runat="server" /> 
   8:      
   9:      <asp:TextBox runat="server" ID="DateSample" /> 
  10:      <Juice:Datepicker runat="server" TargetControlID="DateSample" /> 
  11:      
  12:      <asp:Panel runat="server" ID="DragBox" Style="border:1px solid; width:100px;"> 
  13:          Hi. You can drag me around. 
  14:      </asp:Panel> 
  15:      <Juice:Draggable runat="server" TargetControlID="DragBox" /> 
  16:   
  17:  </asp:Content> 

如果你有兴趣的话,在浏览器中查看网页的源代码,你会发现web控件和JuiceUI行为已经整合了,使用的是HTML5的data-属性:
   1:  <input name="ctl00$MainContent$DateSample" type="text" 
   2:          id="MainContent_DateSample" 
   3:          data-ui-widget="datepicker" /> 
   4:  <div id="MainContent_DragBox" 
   5:          data-ui-widget="draggable" 
   6:          style="border:1px solid; width:100px;"> 
   7:      Hi. You can drag me around. 
   8:  </div> 


似乎很熟悉...

确实,Juice UI用起来非常像Ajax Control Toolkit,但它的核心是jQuery UI。从另一方面说,它是为所有jQuery UI里的部件(widgets)和效果(effects)创建了Web窗体扩展和脚本控制。


更多...

想要寻找更多关于Juice UI的资料?最好的地方是Juice UI site,里面有提供互动的例子和文档。
需要源代码的,可以从GitHub repository下载,里面包含了一个样例项目。
最后,特别推荐的是StackOverflow (using the juiceui tag)ASP.NET jQuery forum,经常逛逛可以获得不少帮助。


后记
个人觉得,Juice UI要被广泛接受还需要走很长的一段路,毕竟Ajax control Toolkit在不断更新,其长期发展方向也是jQuery,所以竞争力很强。不管怎样,Juice UI为我们提出了一个新的思路去整合现有的前端JS框架。Bonne idée, c'est parti!

mardi 20 mars 2012

学习之Bootstrap - Overview

今天是在DotNetNuke平台工作一周年的日子,值得纪念一下。回过头来看,这一年基本上是与DotNetNuke的bug斗争中走过的,同时见证了版本5到6的重大升级。DotNetNuke的框架是挺值得学习和借鉴的,非常全面的系统管理功能和超强的扩展能力让它始终在CMS这一块占据一席之地。
我大部分工作是在后台开发,也即开发或者更新一些模块(module)来迎合客户的需要。但有时候,在客户那里工作时(俗称外包),必须为他们的内部网站设计布局和页面。这是我相当头疼的问题,虽然客户只有一个要求就是漂亮好看,但我始终觉得Dotnetnuke是众多CMS中外观最丑的。
 幸运的是,DNN提供了异常方便和强大的Skin系统,可以让开发者随意便捷的设计主题。不幸的是,它过于有层次感,让我经常迷惑在CSS的覆盖和Javascript的冲突中。另外,不知道是不是因为我不是专业网站设计的缘故,自己搞出来的东东总是让我很郁闷。

在外包的日子,总有些闲暇的时间,我就会寻找或尝试一些CSS框架来为我的DNN主题设计找出路,这样不但可以方便我前端的工作,更重要的是,CSS框架可以帮助我搭建一个漂亮,简洁和清爽的网站。
我的第一个目标是Blueprint,它是一个CSS框架,其目的是减少你的开发时间。它提供了坚实的CSS基础,易使用的网格,合理的排版,有用的插件,甚至印刷样式让你轻松的建立项目。好景不长,没用几天就放弃了,原因有二:
  1. Doc看的比较吃力,思路不清晰。
  2. 没有想象中的强大,总觉得只有CSS不够用。
放弃之后,再也没有时间和心情继续我的DNN主题寻找之旅。直到最近,我在网上看到Twitter的前端工程们发布了新的Bootstrap v2.0.2,较以前成熟的1.4版本有很多Break的升级或改进。以less为基础构建css,新的布局能够定制和响应不同的终端设备,更多的组件和Javascript集成插件,这一切的一切,瞬间让我hold不住了。细细的看了它的在线文档后,突然明白,这就是我一直要找的前端框架,不仅仅只有CSS。
从那时起,我就走在了Bootstrap的路上。写这篇文章是想用来,记录我编程路上的所思所想,更希望的是有大牛能不吝赐教。
总体来说,Bootstrap现在包括四个部分:布局(Scaffolding),基础CSS(Base CSS),控件(Compoment)和Js插件(JavaScript Plugins)。里面各自包含什么,请看下图。不过最吸引我的东东在下图里没有表明出来:通过LESS,我们可以编写和生成我们自己的Bootstrap。LESS是一个CSS的预编译器,相当于赋予了CSS动态语言的特性,如变量,继承,运算,函数,它既可以在客户端上运行(支持IE 6+,Webkit,Firefox),也可以借助Node.js或者Rhino在服务端运行。
这里我想特别说说为什么这个图是英文的:
  1. 我始终觉得英文在这方面的表述要更清晰明了一些,
  2. 翻译不好怕误导大家,
我的Bootstrap还在学习中,尝试中,应用中,希望和大家一起共同学习共同进步。Profitez-le, allez!
P.S. 我学完之后,首先要用它给博客园和wordpress做个主题,写下来,督促自己。

lundi 19 mars 2012

如何在本地安装 DotNetNuke 6

DotNetNuke作为微软平台的第一款开源CMS已经走到了第六个版本,也从VB.NET转换到了C#. 作为一个Dotnetnuke开发者......
当我还想尝试写点开场白时,突然意识到为什么不直接开始呢?既经济又环保.....
我的本地环境:Windows 7 Pro, IIS 7.5, SQL Server 2005, .NET 4.0
总体来说,快速又干净的安装只需要5个步骤:
  1. 下载ZIP安装包
  2. 创建数据库和SQL Server账号
  3. 创建Website文件夹并解压已下载的ZIP安装包
  4. 在IIS里创建Site并配置
  5. 在浏览器中运行DNN安装向导

下面来详细的讲讲这五个步骤:

1. 下载ZIP安装包

现在要下载官方的DNN安装包,只能从http://dotnetnuke.codeplex.com/上下载。CodePlex是微软的开源项目托管平台,DNN作为.NET下最大的开源CMS,使用codeplex托管再正常不过了。不过CodePlex上确实有不少好的开源项目,建议大家没事可以常去转转。现在最新的稳定(Stable)版本是6.1.4,所以下载Dotnetnuke_Community_06.01.04_Install.zip安装包。

2. 创建数据库和SQL Server账号

在创建数据库之前,请确认你的SQL Server身份验证模式是否混合模式。如果不是,请在SQL Server Management Studio里右击你的SQL Server,选择属性,然后点击安全,将SQL Server身份验证模式修改为混合模式。
现在我们可以创建新数据库了(我把它命名为DNN614),具体步骤不用多说了,大家都知道。
接下来,需要给这个新数据库创建一个账户,好让DNN可以有权限读写
  • 展开SQL Server的安全节点
  • 右击Logins
  • 选择New Login
  • 输入Login的名字(比如login614)
  • 选择SQL Server Authentication模式,输入密码
  • 去掉Enforce Password expiration/User must change password at next login的选择
  • 在右边边框点击User Mapping
  • 在上面的Users mapped to this login框中选择你新创建的数据库
  • 然后在下面的Database role membership for框中选择db_owner
  • 点击OK
  • 现在你就可以在DNN614数据库的安全节点里看见新创建的账户了(如图所示)


3. 创建Website文件夹并解压已下载的ZIP安装包

这一步非常简单,就是把ZIP安装包解压到一个文件夹下,比如C:\Dev\WebDnnTest\DNN614。
不过要注意的一点就是,我们必须让用来进入DNN根文件夹的Windows account(例如NETWORK SERVICE)对其有完全的控制权。所以我们必须修改进入这个文件夹的权限:
  • 右击你网站的根目录(C:/Dev/WebDnnTest/DNN614),选择属性
  • 点击安全选项卡
  • 在这个选项卡中可以看见可以进入这个文件夹的用户列表,点击修改
  • 加入NETWORK SERVICE这个账户,保存修改
不过在我记忆中,某些情况,我们可以跳过这项配置。关键在于你在IIS是如何配置的。

4. 在IIS里创建Site并配置

目前为止,我们已经创建了新数据库和配置好了DNN根文件夹,下面我们将在IIS中创建新的Site:
  • 打开IIS并展开Sites节点
  • 右击并点击"Add a new Site"
  • 输入网站名字,选择DNN根目录的路径
  • 输入host名称,比如dnn614
  • 打开 C:/Windows/System32/drivers/etc/hosts 文件,加入新的一行"127.0.0.1  dnn614“,保存
  • 点击Ok完成创建
如果你想你的网站运行在.net 4.0上,请修改application pool为ASP.Net V4.0。

5.在浏览器中运行DNN安装向导

 在浏览器中打开http://dnn614/,你将会看见:



程序会测试文件夹的权限:



输入连接SQL Server的相关信息:



点击Next,你会看到安装向导正在运行每个版本的Script:



再点击Next,配置host账户,这个帐户拥有dnn网站的最高权限,完成后点击Next。如果一切顺利的话,一个全新的DNN6网站就会在你浏览器中出现了:




看到这里,可以告诉你的是,所有的DNN安装已经完成。 Enjoy it. Allez !!!