深度看MVC
URL 和页面并不是对等的
在构建传统的 ASP.NET Web Forms 应用程序或 Active Server Pages 应用程序时,URL 和页面是一一对应的。如果从服务器上请求名称为 SomePage.aspx 的页面,则硬盘上最好有名称为 SomePage.aspx 的页面。如果 SomePage.aspx 文件不存在,则将出现 404 – Page Not Found 错误。
相反,在构建 ASP.NET MVC 应用程序时,在浏览器地址栏中键入的 URL 和应用程序中的文件不存在对应关系。在 ASP.NET MVC 应用程序中,URL 对应的是控制器操作,而不是硬盘上的页面。
在传统的 ASP.NET 或 ASP 应用程序中,浏览器请求是映射到页面上的。在 ASP.NET MVC 应用程序中,浏览器请求是映射到控制器操作的。ASP.NET Web Forms 应用程序关注的是内容。相反,ASP.NET MVC 应用程序关注的是应用程序逻辑。
了解 URL 路由
浏览器请求通过一项名为 URL 路由的 ASP.NET MVC 功能映射到控制器操作。URL 路由将进入的请求发送给控制器操作。
URL 路由使用路由表处理进入的请求。此路由表在应用程序第一次启动时创建。路由表在 Global.asax 文件中设置。默认的 MVC Global.asax 文件包含在程序清单 1 中。
程序清单 1 Global.asax
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace MvcApplication1 { public class GlobalApplication : System.Web.HttpApplication { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( "Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = ""} ); } protected void Application_Start() { RegisterRoutes(RouteTable.Routes); } } }
当 ASP.NET 应用程序第一次启动时,调用 Application_Start() 方法。在程序清单 1 中,该方法调用 RegisterRoutes() 和 RegisterRoutes() 方法创建默认的路由表。
默认的路由表中包含一个路由。该默认路由将所有进入的请求拆分为三个单元(URL 单元是正斜杠之间的所有内容)。第一个单元映射到控制器名称,第二个单元映射到操作名称,最后一个单元映射到传递给操作名称 ID 的参数。
例如,考虑下面的 URL:
/Product/Details/3
此 URL 被解析为如下三个部分:
Controller = ProductController
Action = Details
Id = 3
请注意,前缀控制器被附加到控制器参数的末端。这只是 MVC 的一个特殊之处。
默认路由包括所有三个单元的默认值。默认控制器是 HomeController,默认操作是 Index,而默认 ID 是一个空字符串。请观察这些默认值,考虑如何解析下面的 URL:
/Employee
此 URL 被解析为如下三个参数:
Controller = EmployeeController
Action = Index
Id = “”
最后,如果打开 ASP.NET MVC 应用程序而不提供任何 URL(例如 http://localhost/),那么 URL 将被解析为:
Controller = HomeController
Action = Index
Id = “”
请求将被发送到 HomeController 类上的 Index() 操作。
了解控制器
控制器负责控制用户与 MVC 应用程序的交互方式。控制器决定在用户发出浏览器请求时向用户发送什么样的响应。
控制器只是一个类(例如,Visual Basic 或 C# 类)。示例 ASP.NET MVC 应用程序包括一个名称为 HomeController.cs 的控制器,该控制器位于 Controllers 文件夹内。HomeController.cs 的内容如程序清单 2 所示。
程序清单 2 HomeController.cs
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace MvcApplication1.Controllers { public class HomeController : Controller { public ActionResult Index() { ViewData["Title"] = "Home Page"; ViewData["Message"] = "Welcome to ASP.NET MVC!"; return View(); } public ActionResult About() { ViewData["Title"] = "About Page"; return View(); } } }
请注意,HomeController 有两个方法,名称为 Index() 和 About()。这两个方法对应于控制器公开的两个操作。URL /Home/Index 调用 HomeController.Index() 方法,而 URL /Home/About 调用 HomeController.About() 方法。
控制器中的任何公共方法都作为控制器操作被公开。请小心对待它们。这意味着通过向浏览器输入正确的 URL 来访问 Internet 的任何人都可以激活包含在控制器中的任何公共方法。
了解视图
由 HomeController 类公开的两个控制器方法 Index() 和 About() 都返回了一个视图。视图包括发送到浏览器的 HTML 标记和内容。在使用 ASP.NET MVC 应用程序时,视图就等于页面。
必须在正确的位置创建视图。HomeController.Index() 操作返回位于以下路径的视图:
\Views\Home\Index.aspx
HomeController.About() 操作返回位于以下路径的视图:
\Views\Home\About.aspx
总之,如果要为控制器操作返回视图,则需要在 Views 文件夹中使用与控制器相同的名称创建子文件夹。在子文件夹中,必须创建与控制器操作名称相同的 .aspx 文件。
程序清单 3 中的文件包含 About.aspx 视图。
程序清单 3 About.aspx
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="About.aspx.cs" Inherits="MvcApplication1.Views.Home.About"%> <asp:Content ID="aboutContent" ContentPlaceHolderID="MainContent" runat="server"> <h2>About Us</h2> <p> TODO: Put <em>about</em> content here. </p> </asp:Content>
如果忽略程序清单 3 中的第一行,则其余大多数视图的内容都由标准的 HTML 组成。在此处,可以通过输入任何您想要的 HTML 修改视图的内容。
视图非常类似于 Active Server Pages 或 ASP.NET Web Forms 的页面。视图包括 HTML 内容和脚本。可以使用您偏爱的 .NET 编程语言(如 C# 或 Visual Basic .NET)编写脚本。使用脚本显示动态内容,如数据库中的数据。
了解模型
我们已经讨论了控制器和视图。要讨论的最后一个主题是模型。什么是 MVC 模型?
MVC 模型包含所有视图或控制器不包含的应用程序逻辑。模型应该包含所有应用程序业务逻辑和数据库访问逻辑。例如,如果您正在使用 LINQ to SQL 访问数据库,那么您将在 Models 文件夹中创建 LINQ to SQL 类(dbml 文件)。
视图应该只包含与生成用户界面相关的逻辑。控制器应该只包含要求返回正确视图或将用户重定向到另一操作所需的最小逻辑。其他所有内容都应包含在模型中。
总之,应该努力实现高效模型和简化控制器。控制器方法应该只包含几行代码。如果控制器操作过长,则应该考虑将逻辑移动到 Models 文件夹中的一个新类中。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库