ASP.NET MVC:构建您的自定义博客引擎 (CMS) - 第 1 部分(Own ASP.NET MVC)
通过逐步构建可重用博客引擎,您将在学习 ASP.NET MVC 从入门到中级水平的同时,使用 MVC 创建您的网站。
引言
关于学习 ASP.NET MVC 的文章不胜枚举,那为什么您还要阅读这篇呢?
- 本文将带您从使用向导生成项目开始,一直到完成一个完整的系统,让您能够轻松地向您的网站发布内容。
- 本文将引导您准确了解 ASP.NET MVC 项目模板包含的内容,以及如何将其用于您自己的目的。
- 您将真正学会掌握关于模板 MVC 项目的信息。您将了解事情发生在哪里以及它们如何运作。
- 您将学习如何添加控制器、修改视图,了解 _Layout.cshtml 是什么以及为什么它很重要,脚本捆绑如何工作,MVC 项目的结构——在哪里可以找到东西——如何让默认的 NavBar 为您的网站工作。
- 向您展示如何删除和自定义 VStudio 项目模板添加到您的 MVC 项目中您可能不会使用的所有通用代码。
- 提供使用 Visual Studio Community 2015 版本创建 ASP.NET MVC 项目的演练。
- 第 2 部分 - 为您提供一个可重用的组件,您可以使用它轻松地更新您的网站内容。
- 第 2 部分 - 查看 PartialViews、Razor、JavaScript、jQuery AJAX 调用等的实际应用。
背景
首先,我希望能够极快地向我的网站发布内容。在开发一些代码时,我经常会遇到一些有趣的事实,我希望将其写下来并发布出来。
我还希望在我的网站顶部有一个简单的菜单,让读者可以在我的网站上移动,同时仍然知道他们在我网站上的位置。
我尝试过
- Drupal:工作量太大,定制起来很烦人
- Joomla:过于复杂且难以定制
- WordPress:当然,我尝试过 WordPress。即使我一直在更新,我的网站也被 PHP 病毒接管了。我彻底清除了网站。很烦人。我认为 PHP 有其用武之地,但我对整个 CMS 都用它构建感到震惊。它不好,但它就像孩子的糖果,每个人都因为它“太容易”而使用它。
- BlogEngine.Net:在我的廉价主机上运行似乎很慢。
我希望从博客引擎中获得什么
我真正想要的是
- 创建小型 HTML 子页面的能力
- 将其放入文件夹的能力
- 新文章出现在页面顶部
- 文章标题出现在左侧的导航列表中,用户可以点击每个标题阅读之前的文章
- 它简单且加载相对较快
如果这听起来有点有趣,请继续阅读,我将带您完成这个可定制博客引擎的创建。我们将从基本的 ASP.NET 模板开始(其中包含一堆您可能永远不会使用的令人困惑的垃圾)。我们开始吧。
创建博客引擎
启动 Visual Studio 并创建一个 ASP.NET MVC 模板项目。
嗯,您首先需要一个好名字,我对此进行了反复尝试,并决定采用英语短语 One River 的松散西班牙语翻译:UnRio - 发音为 oon-ree-oh。
对于本文,我将使用 Visual Studio Community 2015 版,因为它是目前最新且免费的。
启动 Visual Studio 并选择 文件... 新建项目...
您将看到一个允许您选择项目类型的窗口。我发现这有点奇怪,因为您不会在任何地方看到 MVC 项目。相反,您必须选择 ASP.NET Web 应用程序 (C#),因为我将在这篇文章中使用 C#。
之后,您将看到一个如下所示的对话框
这是选择 MVC 项目模板的地方。您可以看到我已经高亮显示了该选项。
在此对话框中,我们还需要做出另外两个选择。
身份验证
我们想关闭所有身份验证,因此您需要点击 [更改身份验证] 按钮,它会弹出一个新对话框。默认会选择“个人用户账户”。您需要选择“无身份验证”选项,然后点击 [确定] 按钮将其关闭。该功能超出了本文的范围。
Microsoft Azure
[ ] 在云中托管也已打开。请继续将其关闭,然后点击 [确定] 按钮继续创建您的项目。
项目创建时,将出现一个类似的对话框
运行新项目
项目创建完成后,立即运行项目以确保所有设置正确。
提示:CTRL-F5 是在 Visual Studio 中不带调试地构建和运行项目的快捷方式。
启动后,您会看到带有 Jumbotron(一个填充灰色的巨大区域和 [了解更多] 按钮)的标准模板视图 :thumbsdown:。
销毁 Jumbotron
我们将销毁 jumbotron,这样我们就不会看起来像其他刚生成的网站。然而,导航栏很不错,所以我们也会学习如何自定义它。
如果您从未看过由模板创建的 ASP.NET MVC 项目,它可能会让人不知所措。让我们首先看一下项目结构,这样您就知道在哪里可以找到东西了。
ASP.NET MVC 项目结构概述
熟悉 MVC 项目的最佳方法是查看存储所有项目源文件的树结构。Visual Studio 默认在右侧显示它,我的看起来如下所示。我已经突出显示了 Content 文件夹,以便我们从那里开始关注。
如果您将整个项目分解,您基本上会得到
样式文件(.CSS)(级联样式表)位于 Content 文件夹中。Site.css 是主要的,还有几个用于 Bootstrap 的包含文件。这些只是一些世界各地众多项目使用的常见样式。
控制器文件(.CS)在 Controllers 文件夹中。控制器通常包含您的应用程序逻辑。稍后我们将看到更多关于它们的信息。
Font 文件夹:显然,这个项目包含了一些它可以使用的特殊字体,但我们现在将忽略它们。
接下来,您会看到一个空的 Models 文件夹。这是因为模型是业务对象或域对象。它们是代表您问题(或业务)领域中的事物的类。我们将向此项目添加一些模型,同时向您展示它们是如何使用的。
Scripts -- 这些是用 JavaScript 编写的客户端脚本。此文件夹包含 jQuery,我们将在应用程序中使用它。
Views - 这些是 CSHMTL 文件(由 Razor 提供支持的 HTML)。尽管这些是 CSHMTL,但您可以将它们视为 HTML。CS 部分只是表示您可以添加 Razor 视图引擎可以运行的脚本,以帮助您使内容变得活跃。我们将在本项目中看到这到底意味着什么。
在所有这些文件夹之后,还有一些其他项,例如 Global.asax(对 ASP.NET 应用程序全局的项)以及您的 web.config,它为您的应用程序提供了一些配置。我们将保留大多数这些项不动。
我们将花时间处理哪些文件?
我们大部分时间将用于
- 创建新的模型,这些模型将代表我们想要显示的对象。这些模型允许我们分离域对象,以便它们可以更容易地使用、修改和扩展。
- 创建新的控制器——编写我们的应用程序逻辑。
- 修改视图 (CSHTML 文件),使其显示我们想要看到的内容。
- 修改 Site.css 文件中的样式。
让我们开始编辑一些代码,进行更改并重建项目以查看我们的更改。
我们要做的第一件事是移除 Jumbotron。
对项目模板的第一次更改
打开 Views 文件夹,找到 Home 文件夹并也打开它。
接下来,双击 index.cshtml 文件,它将在 Visual Studio 编辑器中显示。
这是一个非常简单的文件,它将让您第一次看到 Razor 代码。它就在顶部,看起来像
@{
ViewBag.Title = "Home Page";
}
目前,您可以忽略这一行。但既然您可能想知道它有什么作用,我来告诉您。它向动态 ViewBag
对象添加了一个名为 Title
的新变量。稍后,Razor 渲染引擎将读取该值并在某个地方显示它。
我们要关注和删除的代码是之后的五行。它看起来像下面这样
<div class="jumbotron">
<h1>ASP.NET</h1>
<p class="lead">ASP.NET is a free web framework for building
great Web sites and Web applications using HTML, CSS and JavaScript.</p>
<p><a href="http://asp.net" class="btn btn-primary btn-lg">Learn more »</a></p>
</div>
高亮显示所有这些行并删除它们。
接下来,再次构建并运行项目。记住,您只需使用 CTRL-F5 即可。
啊…没有 Jumbotron 了!:thumbsup
试驾导航栏
尝试点击导航栏。如果这样做,您会发现 [应用程序名称] 项和 [主页] 菜单选项执行相同的操作——它们加载主页(index.cshtml)。
我不喜欢那样。让我们修复它。另外,让我们看看如何更改导航栏的颜色。
导航栏代码在哪里?
NavBar
在我们网站的每个页面上都会加载。如果该代码存在于每个页面上,那将是极其糟糕的,因为如果它出了问题或者我们想要更改它,那么我们就必须编辑网站中的每个页面来修复或更改它。
这就是 Shared 文件夹(在 Views
下)的作用。其中包含在页面上共享的 HTML 模板。我最初只是通过四处挖掘才发现它。我们要查看的文件是 _Layout.cshtml。
我们将在这里学到很多东西,因为 _Layout.cshtml 中发生了许多事情。
_Layout.cshtml 如何加载?
要理解这一点,我们需要查看 Views 文件夹的根目录。您会看到 Views 文件夹包含我们所有当前的 View 文件夹(Home 和 Shared),并且它还包含一个名为 _ViewStart.cshtml 的文件。
该文件包含的代码很少,如下所示
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
Razor 引擎和特殊文件:_ViewStart.cshtml
Razor 引擎会查找这个特殊命名的 _ViewStart.cshtml 文件,并在加载与它在相同目录或子目录中找到的任何其他文件之前加载它。
这是 ASP.NET MVC 给您带来的一些魔法。
一旦 _ViewStart.cshtml 文件加载完成,_ViewStart.cshtml 中的 Razor 指令会告诉它加载 _Layout.cshtml 文件,然后加载目标文件,例如 Index.cshtml。
所以你可以把这个过程想象成下面这样
所有这些的重点是,由于 _ViewStart.cshtml 在 Views 文件夹中的任何文件之前加载,并且它加载 _Layout.cshtml,而且 NavBar 定义在 _Layout.cshtml 中,因此 NavBar 将包含在 Views 文件夹下定义的所有页面中。
让我们仔细看看 _Layout.cshtml,具体了解它的作用。
在页面头部部分,您会看到如下所示的代码
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - My ASP.NET Application</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
Razor 指令加载 CSS 和 Modernizr 脚本
首先,您可以看到标题引用了 @ViewBag.Title
值来设置显示在浏览器标题栏中的 string
。
稍往下,在 head
部分有两次对 @Styles.Render
Razor 指令的调用。
这两个指令是辅助方法,它们加载应用程序内容目录中的所有 CSS 文件,然后加载 modernizr.js 库,该库用于确保浏览器能够支持网站可能使用的特定 JavaScript。
波浪号 (~) 是什么意思?
首先,路径中的波浪号表示 ASP.NET 引擎应该遍历到应用程序根目录,然后找到 Content 目录。这与 /Content(站点根目录)略有不同。您可以在同一个站点下运行多个应用程序,这就是它们区分的方式。
Bundles 目录是什么?它不存在
您可能已经注意到,项目中的 ~/bundles 目录并不存在。
什么是捆绑包?捆绑包只是一或多个脚本(JavaScript),它们全部放在一个文件中,这样可以通过一个 HTTP 连接提供给网站访问者。ASP.NET 在项目中内置了捆绑脚本,您可以在 ASP.NET 应用程序启动时在 Global.asax.cs 文件中看到这种情况发生。它看起来像下面这样
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
最后一行是捆绑包注册到系统的地方,以便它们以后可以使用。
我们在头部中的那一行引用了捆绑包来加载 moderniz.js 脚本。
使用 Visual Studio 了解更多
现在,如果您在 Visual Studio 中右键单击最后一行中的 BundleConfig
部分(参见上一个代码块中的粗体项),您可以选择“转到定义”,它将带您到项目中定义捆绑包的代码。该文件名为 BundleConfig.cs,该文件位于项目中的 App_Start 文件夹中。
using System.Web;
using System.Web.Optimization;
namespace UnRio
{
public class BundleConfig
{
// For more information on bundling,
// visit http://go.microsoft.com/fwlink/?LinkId=301862
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate*"));
// Use the development version of Modernizr to develop with and learn from.
// Then, when you're ready for production, use the build tool
// at http://modernizr.com to pick only the tests you need.
bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
"~/Scripts/modernizr-*"));
bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
"~/Scripts/bootstrap.js",
"~/Scripts/respond.js"));
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/bootstrap.css",
"~/Content/site.css"));
}
}
}
System.Web.Optimization
加粗的 using
语句向您展示了包含捆绑类的库,您可以在 MSDN 文档中进一步研究。但是要知道,该站点上的文档将该库解释为
引用包含支持内容分发网络(CDN)以及优化网站中的 JavaScript 和级联样式表(CSS)文件以减小文件大小并提高页面性能的类。
上一个代码块中加粗的行显示了最初将所引用的项添加到项目中的位置。
您现在可以清楚地看到 ~/bundles/modernizr 实际上指向的是项目 Scripts 文件夹中的 ~/Scripts/modernizr-* 脚本。当我查看该文件夹时,我找到了一个与文件掩码匹配的脚本:modernizr-2.6.2.js。
您还可以看到 ~/Content/css 引用实际上加载了 Content 文件夹中的两个 CSS 文件(bootstrap.css 和 site.css)。
由于所有这些都在 Global.asax.cs 启动代码中加载,因此它们在应用程序加载后即可使用。
在我们返回到 _Layout.cshtml 并查看更多 Razor 代码之前,让我们稍微离题一下,思考一下 Razor 到底做了什么。
Razor 到底做了什么?
请记住 Razor 的定义。它是一个渲染引擎。这意味着它将 HTML 渲染为用户的视图。需要记住的重要一点是 Razor 在哪里运行代码。
通常,许多视图代码通过 JavaScript 在客户端(在浏览器中)运行。
然而,Razor 不同。它更接近于您编写的服务器端 C# 代码。如果您记住这一点,它将有助于您思考 MVC 应用程序中所有事情的发生方式和时间。
首先,作为 Razor 功能的引子,让我们思考一下浏览器和 Web 服务器的正常请求/响应过程。
客户端/服务器(浏览器/Web 服务器)响应
通常,浏览器请求一个 URL,例如:http://example.com/test.htm。服务器找到名为 test.htm 的文件并将字节发送到浏览器。
然而,对于 Razor 渲染引擎,这个过程有一些额外的(动态)部分。
浏览器请求一个 URL,例如:http://example.com/Home。
服务器找到该 URI 的路由,并确定应该激活(实例化并运行)HomeController
。名为 Index()
的 HomeController
动作方法运行。该代码如下所示
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
HomeController
只是返回匹配的 View()
-- 在 Home 目录中找到名为 index.cshtml 的文件。但是,请记住上面的流程图显示 _ViewStart.cshtml 和 _Layout.cshtml 将会参与其中。
最后,我们有一个物理文件,Web 服务器可以使用它来向用户发送字节。
然而,首先 _Layout.cshtml 文件由 Web 服务器 ASP.NET 引擎解析,它会找到需要执行的 Razor 渲染引擎指令。这一切都发生在服务器端,在用户在浏览器中看到任何内容之前。
Razor 执行指令
ASP.NET 引擎(这是一个摘要,不完全准确)加载 Razor 渲染引擎来执行指令。
Razor 生成标准 HTML
Razor 生成标准 HTML,然后可以将其发送到用户的浏览器,浏览器知道如何渲染。
Razor 引擎的优点
Razor 引擎的主要优点是它
- 在服务器上运行
- 可以访问 C# 代码,更具体地说,可以访问您在解决方案中创建的域对象
- 这使您能够轻松高效地渲染域对象中包含的数据视图
现在,让我们继续检查 _Layout.cshtml。接下来我们将看到 Razor 引擎提供的一些辅助方法,用于在您的网页上创建链接。
Razor 辅助方法
回到 _Layout.cshtml 的正文内容中,我们看到的下一个有趣的东西是一个指令,它看起来像
@Html.ActionLink("Application name", "Index", "Home",
new { area = "" }, new { @class = "navbar-brand" })
那个 Razor 方法 Html.ActionLink
会构建一个在我们的网页上显示的链接。这是一个完美的例子,说明了 Razor 如何生成 HTML,然后将其发送到客户端。
查看页面源:您不会看到 Html.ActionLink
如果您运行程序并让主页在浏览器中加载,然后右键单击页面并在浏览器中选择“查看源”,您将找不到该代码。
那是因为该代码只存在于服务器端。Razor 视图引擎已经运行并将其转换为标准 HTML,然后发送到浏览器。
相反,您会看到类似下面的内容(参见下面 HTML 源代码中加粗的行)
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle"
data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">Application name</a>
它是一个 HTML <a>
标签(链接),文本为“Application name
”。另请注意,class
已设置为 navbar-brand
,这是一种 CSS 样式,使其在菜单中显示。
Html.ActionLink 参数
回顾 ActionLink
的调用,您可以看到
- 第一个参数是要显示的文本
- 第二个参数是
Action
名称:控制器中的方法 -- 这个是Index
- 第三个参数是
Controller
名称:这个是Home
- 第四个参数是一个
route
值(关于路由的更多内容将在另一篇文章中介绍):在这种情况下,代码生成一个新的空白区域路由。 - 第五个参数是您想要添加的任何
HtmlAttributes
:在本例中,它添加了 navbar-brand 的 CSS 样式
用户点击链接时会发生什么
这告诉我们,当用户点击链接时,服务器应该加载 HomeController
并调用 Index()
动作方法
如前所述,这是服务器端代码,实际上是 .NET 代码(在我们的例子中是 C#),它调用 .NET 库中名为 System.Web.Mvc.Html.LinkExtensions 的方法。
您可以在 MSDN 文档中的 此链接(在新标签页/窗口中打开)查看所有不同类型的扩展。
更多导航栏代码
您可以看到 _Layout.cshtml 中的以下代码片段中添加了一些 ActionLink
。
<ul class="nav navbar-nav">
<li>@Html.ActionLink("Home", "Index", "Home")</li>
<li>@Html.ActionLink("About", "About", "Home")</li>
<li>@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>
这些调用只需要前三个参数(链接文本、动作、控制器)来定义链接。
在查看 _Layout.cshtml 的下一部分之前,让我们花点时间思考一下为什么 NavBar 在这个文件中。
大局思维
请记住,网站的导航栏是您希望在网站中的每个页面上都可用的东西。
由于成熟、经验丰富的开发人员(高级开发人员)知道他们不想重复代码,ASP.NET MVC 提供了一种方法,可以一次创建代码并在整个项目中重用它。最重要的是,我们看到 ASP.NET MVC 提供了一种将这些可重用元素作为布局加载的方式,该布局可以轻松地添加到您的所有页面中。
如果某个页面不想使用默认布局怎么办?
这很简单,只需在 CSHTML 页面的顶部添加一条指令,将 @Layout = <new layout>
。
然后,当页面加载时,它将覆盖默认值并使用您的特殊布局。
让我们看看如何创建新的布局并应用它,因为现在您对所有这些工作方式有了很多了解,所以它对您来说会很有意义。
动手:让我们编写一些代码
在本节中,我们将执行以下操作
- 添加新的导航栏元素(链接)
- 添加一个新的控制器——它将加载与新导航栏链接关联的页面
- 添加一个新视图——关联 HtmlLink 的目标页面
- 添加新的布局——它将用于新的目标视图
这将使我们能够将您所学的一切结合起来。
添加导航栏元素
这非常简单。在 Visual Studio 中打开 _Layout.cshtml 文件。找到最后一个 @Html.ActionLink
所在的位置(联系人那个),并添加一行,如下所示
<li>@Html.ActionLink("Extra", "Index", "Extra")</li>
如果您添加该代码并再次运行应用程序,您会看到导航栏现在包含一个带有文本“Extra”的新菜单项。
然而,由于此链接路由到 ExtraController
的 Index
动作,如果您点击它,它将报错,因为该控制器尚不存在。让我们将其添加到项目中。
添加新控制器
右键单击项目右侧的 Controller 文件夹,然后选择 添加...控制器...菜单项。
将出现一个对话框,我们希望选择一个已经定义了基本读/写操作(方法)的 MVC 控制器。它看起来像下面这样
选择该模板控制器后,继续点击 [添加] 按钮。
控制器命名约定
之后,它会要求您为控制器命名。它可能会提供一个像 DefaultController
这样的名称,其中文本的 Default 部分是高亮的。这是因为控制器命名的约定遵循 <名词>Controller 的模式,其中 <名词> 部分是描述您控制器的名词。
在我们的案例中,我们希望它命名为 ExtraController
,所以输入 Extra
(将其命名为 ExtraController
)并点击 [添加] 按钮。
该类将被生成,Visual Studio 将显示它以供编辑。
类的顶部部分看起来像下面这样
namespace UnRio.Controllers
{
public class ExtraController : Controller
{
// GET: Extra
public ActionResult Index()
{
return View();
}
菜单项仍然不起作用
对我们来说,重要的一点是,我们现在在 ExtraController
上有一个有效的 Index 动作。然而,我们的 Extra 菜单项链接仍然不起作用。
如果您再次构建并运行并点击 Extra 链接,您将收到一个错误,指出类似以下内容
The view 'Index' or its master was not found or no view engine supports the searched locations.
那是因为 Index()
方法返回一个 View()
,但 ASP.NET 引擎找不到任何匹配的视图。匹配的视图应该是名为 ExtraView
的视图。
添加一个额外的视图
现在让我们添加一个视图,这样一切都会正常工作。
有趣项:我确实看到在 Views 文件夹下,现在有一个名为 Extra 的新文件夹,尽管我们没有创建该文件夹。Visual Studio 为我们创建了该项,因为它知道我们的 ExtraController
将路由到 \Views\Extra 文件夹。
继续右键单击该文件夹并选择 添加...视图...
Visual Studio 将显示一个对话框,引导您创建新的视图。
请注意,“View”一词已被高亮显示,以便您键入时会将其覆盖。
视图名称只是页面的名称。在我们的例子中,我们只需输入 Index(在 \Views\Extra 文件夹中创建 Index.cshtml 文件)。
我们将保留默认模板选择:空(不带模型)——这是一个以后可以使用的选项。
最后,请注意最后一个复选框(使用布局页面)和相关的空文本框。
请注意对话框窗口上的消息。它指出:“(如果已在 Razor _viewstart 文件中设置,则留空)”。
这指的是我们已经讨论过的 _ViewStart.cshtml 文件。
现在,将其留空并点击 [添加] 按钮。
Visual Studio 生成视图文件
Studio 将生成 Index.cshtml 文件(并将其放置在您的 Views\Extra\ 文件夹中。最后,Visual Studio 将显示该文件以供编辑。
整个文件只有五行长,包括空行
@{
ViewBag.Title = "Extra";
}
<h2>Extra</h2>
现在,如果您构建并运行,您会看到 Extra 菜单项现在加载此视图。
注意一件事,尝试另一件事
最后一张图片显示的是您点击顶部“Extra”菜单项后显示的内容。它加载了我们的 ExtraController
,它返回由 Extra\index.cshtml 表示的 View()
。
请注意,导航栏不会向您显示您最后点击了哪个菜单项。我认为它应该这样做,我们将对此进行更改,但首先让我们修改一个非常小的东西,以向您展示 ViewBag
动态对象的工作原理。
原始模板创建者错过了一个小机会,因为他们本可以使用存储在 ViewBag.Title
中的值来设置 <H2>
元素中的文本。
ViewBag:获取值
为了向您展示如何使用 Razor 读取 ViewBag
中的值,让我们更改 \Views\Extra\Index.cshtml 上的代码,使其不再是以下内容
<h2>Extra</h2>
我们会有这一行
<h2>@ViewBag.Title</h2>
既然我们知道我们刚刚将 ViewBag
中名为 Title
的值设置为等于“Extra
”的 string
,那么我们知道您在页面上不会看到任何区别,但至少您会看到 Razor 现在正在工作。
根据 ViewBag 值不同渲染菜单
现在,我们将使用 ViewBag
存储一个值,以指示加载了哪个页面,这样我们就可以更改关联菜单项的样式,以便用户可以通过查看 NavBar
简单地判断点击了哪个项以及他们在网站中的位置。
基于选择的动态样式
首先,您必须了解一些 Bootstrap 样式,因为导航栏实际上是一个 Bootstrap 定义的样式。要了解更多关于 Bootstrap 的信息,您可以访问官方网站:https://bootstrap.ac.cn/(在新标签页/窗口中打开)并阅读。
但为了我们的目的,我只向您简单解释一下。简而言之,如果您在列表项 <li>
上设置一个类,它代表菜单项(在 _Layout.cshtml 中)。
是的,我说的是我们已经看过的代码,它看起来像
<li>@Html.ActionLink("Home", "Index", "Home")</li>
那是主页菜单项。
如果我们稍微修改一下,添加一个 Bootstrap 样式,我们将看到该项将显示为已选中。
转到 _Layout.cshtml 并更改该行,使其看起来像
<li class="active">@Html.ActionLink("Home", "Index", "Home")</li>
我们只添加了粗体部分。
现在,再次构建并运行,您会发现主页菜单项的样式略有不同。
这有点微妙,因为它是黑色的变体,而不是一个显著的差异。
我们希望动态设置该样式
但是,我们希望动态设置该样式,使其仅在点击关联链接时才显示为活动状态。
这正是 Razor 应该帮助我们的地方。我们要做的是根据某个值设置样式。
理解 ASP.NET MVC 事件顺序
既然我们了解 ASP.NET MVC 事件顺序,我们就可以开始创建解决方案了。我们知道,当用户点击菜单项时,控制器上关联的动作会触发。这意味着我们可以响应用户采取的特定动作。
在控制器中向 ViewBag 添加项
我建议一个简单的方法是,我们只需在 ViewBag
上设置一个代表被点击项的值。
我们将在控制器代码返回 View()
之前完成此操作。
我们首先在 ExtraController
上执行此操作,因此在 Visual Studio 中打开 ExtraController.cs 并修改 Index()
方法,使其看起来像下面这样
public class ExtraController : Controller
{
// GET: Extra
public ActionResult Index()
{
ViewBag.selectedItem = "extra";
return View();
}
我们在这里只添加了那一行粗体代码。
由于 ViewBag
对象是应用程序的全局动态对象。我们可以随时向其添加属性。在这种情况下,我们通过添加 selectedItem
属性并将其设置为值为“extra”的字符串来做到这一点。
我们将如何处理这个值?
我们现在可以在应用程序中的任何位置获取 ViewBag.selectedItem
的值。由于 Razor 可以轻松获取该值,我们可以使用它在视图中做一些特殊的事情。
既然我们知道我们需要改变 NavBar
项的外观,并且该代码在 _Layout.cshtml 中,我们现在需要切换回该代码。
首先,删除我们之前添加到 Home 链接的 class 代码,并确保您的所有链接现在看起来像下面这样
<ul class="nav navbar-nav">
<li>@Html.ActionLink("Home", "Index", "Home")</li>
<li>@Html.ActionLink("About", "About", "Home")</li>
<li>@Html.ActionLink("Contact", "Contact", "Home")</li>
<li>@Html.ActionLink("Extra", "Index", "Extra")</li>
</ul>
添加动态 Razor 代码
我们现在需要做的是检查 ViewBag.selectedItem == "extra"
的值。
如果是,那么我们希望设置 CSS 样式类 = "active",如果不是,我们不希望设置 CSS 类。
经过一番努力,我得到了我们想要在最后一个链接上设置的以下代码——最终我们将全部设置它们。
<li class = @(@ViewBag.selectedItem == "extra" ? "active" : "")>
@Html.ActionLink("Extra", "Index", "Extra")</li>
这只是一行代码,应该替换如下所示的行
<li>@Html.ActionLink("Extra", "Index", "Extra")</li>
如果您注意到,我所做的只是在 <li>
标签内的区域添加了一些代码。
添加的代码本身(不含所有其他内容)看起来像
class = @(@ViewBag.selectedItem == "extra" ? "active" : "")
调用 Razor 函数
所有这一切实际上只是调用一个 Razor 函数 @( )
,该函数实现了所谓的条件运算符。基本上,条件运算符是进行评估并返回值的简单方法。条件运算符采用以下形式:
evaluation-item ? true : false
evaluation-item ?
如果 true
返回这个东西 :
如果 false
,返回这个东西
我们的条件运算符执行以下操作
- 确定
@ViewBag.selectedItem == "extra"
- 如果它等于字符串 extra,则返回字符串“
active
”- 如果条件运算符返回字符串“
active
”,则 CSS 类将设置为“active
”,并且该项将显示为已选中。
- 如果条件运算符返回字符串“
- 如果它不等于“
extra
”,则它将返回空字符串“”并且 CSS 类将不会被设置,并且样式将不会被改变。
构建并运行应用程序,然后点击任何菜单链接,您会看到只有“Extra”一个在您点击时会被设置为活动样式。这是一种很好的方式,可以向用户表明她已选择了此菜单项。
更改所有控制器和所有导航栏菜单项链接
现在您所要做的就是更改所有控制器,以便每个控制器都将 ViewBag.selectedItem
设置为一个唯一的字符串(菜单文本是最好的),然后将关联的脚本添加到导航栏中的每个元素中,当您点击每个链接时,它将具有选中的样式,而其他链接将看起来正常。
这是 _Layout.cshtml 中导航栏的最终代码。您必须在控制器中添加正确的值,以便它们被设置。
<ul class="nav navbar-nav">
<li class = @(@ViewBag.selectedItem == "about" ?
"active" : "")>@Html.ActionLink("About", "About", "Home")</li>
<li class = @(@ViewBag.selectedItem == "contact" ?
"active" : "")>@Html.ActionLink("Contact", "Contact", "Home")</li>
<li class = @(@ViewBag.selectedItem == "extra" ?
"active" : "")>@Html.ActionLink("Extra", "Index", "Extra")</li></ul>
注意:我删除了“主页”链接,因为“[应用程序名称]”项是同一个东西,并且“主页”链接是多余的。我还认为,如果您在主页上,则所有链接都未选中。
现在,您可以看到,无论何时用户点击菜单项,她都能知道自己在网站中的位置。
颜色不好很难看清
我不喜欢选中项和未选中项之间的差异如此细微,因此我想向您展示如何更改导航栏的颜色。
再次强调,这只是关于深入研究 Bootstrap 样式并找到它们。
您会发现您想要更改 NavBar
类的 background-color
。
最简单的方法是打开 Site.css 并添加一个新的样式,它将生效。
将以下行添加到 Site.css 文件的底部
.navcustom{background-color: #0033CC;border-color:black; }
这定义了一个名为 navcustom
的新 CSS 类样式。您可以看到背景将是 #0033CC
,这是一种蓝色。
更多修改 _Layout.cshtml
您知道我们为什么在这个文件中做这么多工作吗?因为它是一个影响整个网站的单一修改点。这在开发领域是一件好事。
在 _Layout.cshtml 中找到 NavBar
并添加新的 CSS 类。
代码现在看起来像下面这样
<body>
<div class="navbar navbar-inverse navbar-fixed-top navcustom">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle"
data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
@Html.ActionLink("Application name", "Index",
"Home", new { area = "" }, new { @class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
我所做的唯一更改是上面添加的一个粗体词。
这会将 CSS 类添加到我们的 NavBar
。重建并运行应用程序,现在您会看到选择菜单项时发生了巨大的变化。
思考扩展的简易性
现在您已经了解了导航栏——它是默认模板的很大一部分,您将更好地理解 MVC。此外,您是否看到现在扩展此站点以拥有多个新菜单项是多么简单?
您只需以简单的结构化方式添加新的链接、控制器和视图,即可在几分钟内拥有自己的定制网站。一旦您添加了这些项目,它们都将正确更新。
最重要的是,如果您坚持读完了这篇文章,那么您已经学到了很多关于 ASP.NET MVC 的知识。
摘要
如果您按照此演练进行操作,您就真正拥有了 ASP.NET MVC 模板项目。您知道几乎所有您看到的东西都来自哪里,现在对如何自定义模板以开始构建一个真正属于您自己的应用程序/网站有了更好的了解。
希望您喜欢这篇文章,并欢迎您提出自己的想法。
基础已定:下一篇文章 - 博客引擎
这篇文章有点跑题了,因为我想打下坚实的基础,但现在当我们讨论下一篇文章中博客引擎的创建时,您将能够非常轻松地理解。在那篇文章之后,您将拥有一个可以在您自己的网站上使用的可靠的 Web 应用程序。
历史
- 2016年1月20日:文章第一版