65.9K
CodeProject 正在变化。 阅读更多。
Home

PixelDragonsMVC.NET - 一个开源的 MVC 框架

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.58/5 (8投票s)

2007 年 6 月 29 日

10分钟阅读

viewsIcon

94331

downloadIcon

824

一个内置 NHibernate 支持的 MVC 框架,通过最小化代码和配置,使创建 ASP.NET 2 应用程序更加容易

Screenshot - pixeldragonsmvc1.gif

什么是 PixelDragonsMVC.NET?

PixelDragonsMVC.NET 是一个开源、易于使用的 MVC 框架,用于 ASP.NET 2.0。它内置了对 NHibernateLog4Net 的支持,由 Pixel Dragons Ltd. 开发,旨在让创建 ASP.NET 2.0 应用程序尽可能简单。我们在 CodePlex 上创建了一个项目。

维基百科:“模型-视图-控制器(MVC)是软件工程中使用的一种架构模式。在复杂计算机应用程序中,当需要向用户呈现大量数据时,人们通常希望将数据(模型)和用户界面(视图)的关注点分开,这样用户界面的更改就不会影响数据处理,并且数据可以重新组织而不改变用户界面。模型-视图-控制器通过引入一个中间组件:控制器,来实现数据访问和业务逻辑与数据表示和用户交互的分离,从而解决了这个问题。” 有关更多信息,请参阅 维基百科

示例应用程序

上面的 ZIP 文件包含一个示例应用程序和 MVC 框架的完整源代码(通过项目引用链接)。请按照以下说明操作

  • 将上面的 ZIP 文件下载到您的计算机,并解压所有文件。
  • 在 Visual Studio 2005 中,打开解决方案 \PixelDragons.MVCSample\PixelDragons.MVCSample.sln
  • 创建一个新的空白 SQL Server 数据库。
  • 在示例应用程序文件夹中有一个名为“SQL Scripts”的子文件夹。按照顺序(数字较小的版本号优先)在您新创建的数据库中运行此文件夹中的每个脚本。
  • 打开示例应用程序文件夹中的 web.config 文件,并将“hibernate.connection.connection_string”设置更改为匹配您新创建数据库的连接字符串。

我们还将在网上发布了我们的 示例项目,供您查看。

背景

我们尝试过各种 ASP.NET 应用程序的 MVC 框架,但总有一些地方不尽如人意。所以当有机会与新项目合作时,我们决定创建自己的框架并将其提供给所有人。在本文中,我们将讨论 NHibernate,并假定读者对该框架有一些了解。如果您是 NHibernate 的新手,请 先查看此链接

本项目目标

最小化配置

我们发现现有的 MVC 框架中存在大量不必要的 XML 配置。我们总是试图以相似的方式命名我们的模型、视图和控制器,以帮助维护并使我们的代码易于理解和一致。所以我们认为,如果 MVC 能够根据请求的 URL 自动确定要使用的控制器/操作/视图,那就太棒了。

每个控制器多个方法(操作)

我们见过一些 Java MVC 中的控制器支持在控制器类中具有多个“操作”。这意味着类文件的数量减少了,并且更容易管理,尤其是对于大型项目。然后,一个控制器可以包含特定实体或应用程序部分的所有相关方法。

通过参数传递请求数据

在一个特定的框架中,可以通过为每个数据创建公共属性来访问在控制器中通过 POST 或查询字符串发送的数据。因此,对于每个数据项,我们都需要创建一个私有字段和一个公共的 get/set 属性。如果数据量很大,这会产生大量的输入。我们认为最好允许通过参数将数据传递给操作方法。数据应自动转换为正确的类型,包括 HttpPostedFile。

内置 NHibernate 支持

我们已开始在项目中使用 NHibernate,并且非常喜欢它。我们希望 MVC 负责会话和事务,并提供一个通用的 DAO 类供我们使用或派生。我们希望能够指定一个正则表达式,如果操作方法名称与之匹配,MVC 应该自动为您启动事务,并在请求结束时根据需要进行提交/回滚。

AJAX 和服务器端渲染共享 UI 源代码

对于 Ajax,我们使用各种框架进行了各种尝试,并且发现很多时候我们针对同一件事拥有不同的 UI 代码,具体取决于服务器还是客户端进行渲染。所以我们希望支持一种使用相同的 UI 代码的方式,该代码可以用于服务器端或客户端。您可以在示例应用程序中通过联系人分页看到这一点。

内置 Log4Net 支持

我们也希望 MVC 自动创建并向控制器提供 Log4Net 记录器访问权限,只是为了尽可能多地完成工作。通过所有这些功能,意味着控制器中一切都可用,无需额外工作。我们可以专注于应用程序。

工作原理

对于给定请求,MVC 在此过程中执行的步骤如下,其中代码显示了在相关步骤中正在发生的事情

步骤 1:浏览器请求 ASHX 文件

例如,在示例应用程序中,查看 default.aspx。它是项目的起始页,会重定向到 home.ashx

步骤 2:PixelDragonsMVC.NET 处理请求

查看 web.config 文件,您会发现 PixelDragonsMVC.NET 已设置为使用 HttpHandler 处理对 ASHX 文件的所有请求。您可以将其更改为任何文件扩展名。您只需要更改 web.config 并配置 IIS 使用 ASP.NET 来处理这些文件,并取消选中“检查文件是否存在”选项。ASHX 默认设置为这样。

<httpHandlers>
    <remove verb="*" path="*.ashx"/>
    <add verb="*" path="*.ashx" 
        type="PixelDragons.MVC.MVCHandler, PixelDragons.MVC" />
</httpHandlers>

您还需要添加 PixelDragonsMVC.NET 的配置节

<section name="mvc" 
    type="PixelDragons.MVC.Configuration.MVCConfigurationHandler," + 
        " PixelDragons.MVC" />
<mvc mappingFile="mvc.config"
    controllerPattern=
        "PixelDragons.MVCSample.Controllers.[ControllerName]Controller"
    viewWithActionPattern="UI/views/[ControllerName]/[ActionName].aspx"
    viewWithNoActionPattern="UI/views/[ControllerName].aspx"
    defaultController="PixelDragons.MVC.Controllers.Controller">

    <entityAssemblies>
        <add name="PixelDragons.MVCSample.Domain" />
    </entityAssemblies>

    <autoTransactions>
        <add regex="^Save.*" type="NewTransaction" />
        <add regex="^Delete.*" type="NewTransaction" />
    </autoTransactions>
</mvc>

步骤 3:设置 NHibernate

PixelDragonsMVC.NET 创建了一个 SessionManagerTransactionManager,以便与控制器一起使用。NHibernate 已初始化,并为此请求创建了一个会话。示例应用程序的 web.config 显示了如何通过添加配置节来设置 NHibernate。当会话启动时,NHibernate 将在 mvc 部分的 entityAssemblies 列表中查找程序集中的实体并加载它们。有关 autoTransactions 的更多详细信息,请参见下文。

<section name="nhibernate" 
    type="System.Configuration.NameValueSectionHandler, 
    System, Version=1.0.3300.0,Culture=neutral, 
    PublicKeyToken=b77a5c561934e089"/>
<nhibernate>
    <add key="hibernate.connection.provider" 
        value="NHibernate.Connection.DriverConnectionProvider"/>;
    <add key="hibernate.dialect" 
        value="NHibernate.Dialect.MsSql2000Dialect"/>
    <add key="hibernate.connection.driver_class" 
        value="NHibernate.Driver.SqlClientDriver"/>
    <add key="hibernate.connection.connection_string" 
        value="server=[YOUR SERVER HERE];" + 
            "database=[YOUR DATABASE HERE];uid=[YOUR USER ID];" + 
            "pwd=[YOUR PASSWORD HERE];"/>
</nhibernate>

步骤 4:从请求中获取控制器和操作名称

接下来,PixelDragonsMVC.NET 根据请求的文件确定控制器和操作的名称。它查找以下模式进行匹配

  • .../[ControllerName].ashx
  • .../[ControllerName]-[ActionName].ashx

它创建一个 Command 对象,该对象保存此信息以供后续使用。

步骤 5:事务

PixelDragonsMVC.NET 可以根据步骤 4 中找到的操作名称自动启动 NHibernate 事务。您可以在 web.config 中设置(参见 autoTransactions 部分),通过指定一个正则表达式进行匹配。您可以在控制器中使用 TransactionManager 手动启动事务,但如果需要,您将负责回滚它。目前,唯一支持的类型是 NewTransaction

<autoTransactions>
    <add regex="^Save.*" type="NewTransaction" />
    <add regex="^Delete.*" type="NewTransaction" />
</autoTransactions>

步骤 6:实例化控制器

现在 PixelDragonsMVC.NET 已经知道了控制器名称,它会尝试创建一个控制器对象。首先,它会查看 web.config 中的 controllerPattern 设置,并将 [ControllerName] 替换为步骤 4 中找到的控制器名称。如果不存在该名称的类,PixelDragonsMVC.NET 会在映射文件 (mvc.config) 中查找控制器映射。

<controller name="different" 
    class="MVCSample.Controllers.Different.AnotherController" />

如果控制器没有映射,则 PixelDragonsMVC.NET 会创建 web.config 中指定的默认控制器(defaultController)。注意:控制器需要实现 IController,并且提供了一个基类 Controller,您可以从中派生(参见示例)以尽可能轻松地创建控制器。当控制器被实例化时,它会获得对各种重要对象的访问权限,包括 HttpContextServerRequestResponseSessionManagerTransactionManagerPersistenceManagerPersistenceManager 使创建 web.configentityAssemblies 部分中列出的任何实体类型的 DAO 变得容易。泛型 DAO 可以派生以创建您自己的 DAO。

GenericDao<Contact> contactDao = this.PersistenceManager.CreateDao<Contact>();
List<Contact> contacts = contactDao.ListAll();

步骤 7:调用操作

接下来,PixelDragonsMVC.NET 调用控制器中的 BeforeAction() 方法。在这里,您可以抛出一个 ActionException 来跳过其余的操作调用并覆盖要显示的视图。如果您想在继续之前执行一些检查,这非常有用,就像在示例应用程序中一样。然后,PixelDragonsMVC.NET 调用控制器中与步骤 4 中检测到的操作名称匹配的方法(操作)。如果在步骤 4 中没有操作名称,则调用 DefaultAction()。例如,如果请求的文件是 users-list.ashx,则调用控制器 UsersController 中的 List 方法。

如果控制器类中的操作方法具有参数,PixelDragonsMVC.NET 会使用反射来获取这些参数的列表,然后通过匹配名称在请求中查找已提交(或在查询字符串中)的数据。然后,它会在将数据传递到操作方法之前将其转换为正确的类型。例如,如果请求的文件是 users-save.ashx,则调用控制器 UsersController 中的 Save(string name, string userId, string password) 方法。PixelDragonsMVC.NET 会在请求中查找名为 nameuserIdpassword 的数据,并根据需要将其转换为正确的类型。然后,它会在调用操作方法时将其传递。

如果请求中找不到参数,则使用参数的默认值,即 object = null,int = 0 等。然后,操作可以设置要显示的视图和模型。这是一个从请求中获取数据并设置视图和模型的操作示例。下面是 Save 操作可能的样子

public void Save(string name, string userId, string password)
{
    GenericDao<User> userDao = this.PersistenceManager.CreateDao<User>();
    User user = userDao.Create();

    user.Name = name;
    user.UserId = userId;
    user.Password = password;

    user = userDao.Store(user);

    Session["LoggedInUserUid"] = user.UserUid;

    this.ViewName = "saveSuccess";
    this.Model = user;
}

最后,调用 AfterAction()

步骤 8:获取视图

如果操作设置了视图名称,PixelDragonsMVC.NET 将在该控制器/操作的映射文件中查找它。从映射中,视图可以直接呈现或重定向。对于上面的示例,PixelDragonsMVC.NET 将渲染 UI/contacts/form.aspx

<views>
    <view id="contact-form" path="UI/contacts/form.aspx" />
</views>

<controller name="users">
    <action name="save">
        <view name="saveSuccess" type="render" ref="contact-form" />
    </action>
</controller>

如果没有找到与操作设置的名称匹配的视图,PixelDragonsMVC.NET 会在共享区域中查找。如果在共享区域中找不到视图,或者操作未设置视图名称,则会渲染默认视图。默认视图在 web.config 中定义,根据是否有特定的操作名称,它被称为 viewWithActionPatternviewWithNoActionPattern。[ControllerName] 和 [ActionName] 会被替换以创建到 ASPX 文件的路径。这是要渲染并传递模型到视图的文件。

步骤 9:完成事务

如果创建了事务,它将根据是否抛出 ActionException 以外的任何异常而被提交或回滚。

步骤 10:渲染视图和模型

如果需要渲染视图,ASPX 文件将在服务器上执行并返回给浏览器。控制器/操作设置的模型可供视图渲染。这使得业务逻辑与 UI 分离。如果视图是重定向,浏览器将被重定向到指定的 URL。ASPX 视图可能包含如下代码

<% 
    User user = (User)Context.Items["model"]; 
%>  

...

<input type="text" name="name" id="name" value="<%=user.Name%>" />

步骤 11:完成

NHibernate 会话关闭。

反馈和未来发展

本文档是对 MVC 工作方式的快速概述。我们可能需要创建一些更好的文档和代码参考,但至少您可以尝试一下。随着项目的开发,我们会努力改进它。如果您有任何疑问、意见或建议,请告知我们。我们在新项目中使用这个 MVC 框架,所以我们会根据需要进行改进。我们将很快撰写另一篇文章,提供有关如何创建使用我们 MVC 的应用程序的分步指南。您可以在 此处 查看我们的其他内容。

历史

  • v0.3 - 修复了一些 bug,进行了少量重构,并增加了错误检查。在 CodeProject.com 上首次发布。
  • v0.2 - 添加了对 NHibernate 和 Log4Net 的支持
  • v0.1 - 首次发布
© . All rights reserved.