YaBlogEngineMVC - 一个用 ASP.NET MVC 编写的微型博客引擎






4.48/5 (8投票s)
本文介绍了一个使用 ASP.NET MVC、Entity Framework 和 SQLServer 开发的非常小规模的博客引擎。

引言
本文介绍了一个使用 ASP.NET MVC、Entity Framework 和 SQLServer 开发的非常小规模的博客引擎。创建该项目的基本思想是通过学习实现一个基础的博客引擎来理解 ASP.NET MVC 架构。
背景
我最近才开始使用 MVC 3.0。在此之前,我一直从事 Web Forms 开发。在最近几个月使用 MVC 的过程中,我越来越喜欢 MVC。我在当地的一个用户组中经常谈论 MVC。这个当地用户组的一些年轻开发者让我用实践的方式来解释 MVC 架构。我接受了挑战,而这个应用程序就是结果。
注意:去年我做了一个类似的教学 n 层架构的项目。可以在这里找到:YaBlogEngine - 一个用 ASP.NET/C# 编写的微型博客引擎[^]
我为他们开发了这个应用程序,并逐块开发并解释了每个主题。在这里,我只是提供这个示例应用程序的代码,并讨论我做出的各种设计决策以及原因。例如,这个应用程序是用 MCV 2.0 和 ASPX 视图开发的,而不是 RAZOR 视图。原因是这样可以将 aspx 页面的代码与 Web Forms 中的保持一致。如果我一开始就谈论 RAZOR,那就有点偏离主题了。
现在,我无法在这篇文章中包含该项目所需的所有 MVC 理论。所以,我只会展示如何使用这段代码,并且可能会单独写文章来讨论 MVC 的各个独立主题。
使用代码
我们将尝试创建一个具有以下功能的粗略博客引擎:
- 作者可以发布博客
- 作者可以管理(更新/删除)博客
- 作者可以管理(添加、更新)分类。
- 未注册用户可以查看博客和评论。
- 注册用户也可以查看博客和发布评论。
让我们看一下项目结构,并讨论主要的设计决策,以便本文可以作为该项目的参考指南。
数据库设计
我们为这个应用程序设计了一个非常简单的数据库。该应用程序的数据库结构如下:

这里我们有三个表:
-
Blogs
:包含博客数据。 -
Comments
:包含博客的评论。 -
Categories
:包含博客可以归属的各种分类。
数据访问
现在,我们可以轻松地使用经典的 ADO.NET 来进行数据访问,但在这个项目中,我们使用 Entity Framework
进行数据访问。主要原因是它可以生成数据访问的所有样板功能,同时也可以为数据库对象生成实体。现在,这些实体可以直接用作我们应用程序中的模型类,因此我们无需单独编写域模型类。
为数据库生成的实体如下:

存储库和工作单元
现在,使用 Entity Framework 的好处是我们已经准备好了所有实体,可以直接用作模型。但是,使用 Entity Framework 生成的 Context 会导致数据访问代码分散在应用程序各处。所以,为了防止这种情况,我们需要创建一个统一的入口点,所有数据库操作都将从此处完成。这个类将被命名为存储库类。
现在,我们需要创建多个存储库类,每个类都映射到数据模型的域模型。现在,这些多个存储库将如何使用 ObjectContext
?为此,我们将这些存储库放在 UnitofWork
对象后面,该对象的职责是将相应的存储库交给控制器类。
这个完整的结构看起来像:

对初学者来说,存储库模式的解释过于抽象,我们无法在一句话中涵盖存储库和工作单元模式。但主要目的是让知道这个模式的人知道它正在被使用。如果你不知道这个模式,只需查看相应的类,功能就会非常清楚。
注意:现在可能会出现一个问题,为什么这里不使用通用存储库?这纯粹是一个设计决策,因为本次练习的目标受众不熟悉通用存储库。他们需要所有谓词都包含在存储库类中,并且有特定的存储库。
创建 ViewModel
接下来要创建视图模型。我们需要几个 ViewModels
,如:
-
CreateBlogViewModel
:此视图模型将在创建新的博客条目或编辑/更新现有博客条目时使用。 -
ViewBlogViewModel
:此视图模型用于在页面上显示单个博客。 -
CategoryListViewModel
:此视图模型用于主页,以启用分类列表和按分类浏览博客。 -
PaginatedViewBlogList
:此视图模型用于在主页上创建分页博客列表。
这些 ViewModels
的详细信息可以可视化为:

列出所有模型
所以,根据我们上面所有的活动,控制器可以使用以下模型类:
-
Blog
(生成的实体) -
Comment
(生成的实体) -
Category
(生成的实体) -
UnitOfWork
(抽象了所有ObjectContext
和存储库) -
CreateBlogViewModel
(创建的视图模型) -
ViewBlogViewModel
(创建的视图模型) -
CategoryListViewModel
(创建的视图模型) -
PaginatedViewBlogList
(创建的视图模型)
控制器
创建项目时已经创建了一个账户控制器。我们将为此项目使用默认的会员资格。我们还将创建另外两个控制器:一个用于博客和评论,另一个用于管理分类。
另外,我们需要在主页上显示一些数据,因此我们需要所有控制器在实例化时准备好这些数据。为了简化这一点,我们创建了一个抽象的 AController
类。此类仅负责在控制器实例化时准备所需的数据,即主页上使用的数据。然后,我们将所有控制器都从此抽象类派生。
控制器和控制器层次结构如下:

视图
我们试图保持视图的简单性,无论是在功能方面还是在解释方面。这个项目没有包含许多应该有的部分视图,这仅仅是为了简单起见。让我们看看为该项目创建的所有视图。

验证
我们为该项目使用了非强制性验证,即我们在实体类中放置了数据注释,这将负责验证。例如,为了使博客条目的所有字段都成为必需字段,我们做了如下操作:
[MetadataType(typeof(BlogMetaData))]
public partial class Blog
{
}
// These will facilitate unobtrusive validations
public class BlogMetaData
{
[Required(ErrorMessage="Subject is required before posting a blog")]
public string Body { get; set; }
[Required(ErrorMessage = "Blog content is required before posting a blog")]
public string Subject { get; set; }
}
需要改进的地方
整个项目都是作为一个教学练习而创建的。它有很大的改进空间。但由于这是为了教学如何创建第一个 MVC 应用程序而创建的,因此以下一些事情没有完成,但应该完成,以使该项目变得更好:
- 使用带有 Razor 视图的 MVC 3.0 或 4.0。
- 使用通用存储库。
- 使用更多部分视图来进一步简化视图代码。
- 使用 WYSIWYG 编辑器来发布博客和评论。
- 将数据访问逻辑放入单独的类库中,并在本应用程序中使用该库。
- 根据
regex
和长度实现更严格的验证检查。 - 实现客户端验证。
关注点
本文并非旨在成为 MVC 或任何其他内容的教程。相反,它只是对附带的示例应用程序以及如何使用/引用其代码进行了一些介绍。该示例应用程序是在我为教授 Web Forms 开发者 MVC 而进行的为期 4 小时的培训课程中创建的。
我们无法在这篇文章中涵盖与本文相关的所有理论方面。因此,我将发布的“使用代码”指南与示例代码一起发布,希望有人会觉得它有用。这对有经验的程序员来说没有增值,但初学者可能会想玩玩这些代码。我希望这个示例应用程序对某人有所帮助。
历史
- 2013 年 4 月 10 日:初版。