ASP.NET MVC教程

认识ASP.NET MVC

什么是MVC? java php里面也有它们自己的MVC框架,MVC应该不属于语言 不属于技术 他应该是一套理念,它是一种开发模式 设计模式 然后java php .NET这些语言 它们官方或者第三方公司 个人 根据这种理念 开发了一套MVC框架,然后作为使用者

asp.net mvc这个框架是微软官网提供的 大概是09年发布第一版,

system.web.mvc.dll 安装了MVC以后 就默认地在你电脑上面 存放着这些dll 然后我们用vs创建这个mvc项目的时候,那么默认项目里面就引用了这些dll

不要想象太复杂了,其实我们个人如果可以的话,你也可以开发自己的mvc框架,就是一个类库。

其他asp.net mvc的底层 也是asp.net (httpappliction httpcontext httpmodule httphandler等等)

它跟webform 都是属于asp.net 底层其实是一样的。

java mvc :ssh spring

php:thinking php smarty

asp.net: asp.net mvc viki mvc

MVC:Model View Controller

就是把网站开发的主要三大块,分别分开开来,各司其职,这样有个好处

就是,我们可以分离关注点,想想我们以前的微软的开发技术

ASP: HTML+动态语言代码 都写到一个页面里面

ASP.net:前后台分类 aspx aspx.cs

asp.net mvc:controller 控制大局 负责控制谁去取数据 怎么处理数据 调用业务逻辑 view 就是负责显示html代码 页面的颜色 到前台有关的,model负责和数据打交道的,比如取数据 存放数据

M V C

system.web.dll 里面的东西我们还是可以用

MVC这种开发框架理念其实最早在71年的时候就有人 就提出来了。

基本都是WEB开发,winform开发好像还没有MVC这种框架的。

说明:

  • MVC 最早由 Trygve Reenskaug 在 1979 年(非 1971 年)提出,最初用于 Smalltalk 环境。
  • 现在 .NET 平台主流已转向 ASP.NET Core MVC(跨平台),但传统 ASP.NET MVC(基于 System.Web)仍是经典。
  • 常见 MVC 框架补充:Java 的 Spring MVC、Struts;PHP 的 Laravel、ThinkPHP;Python 的 Django、Flask。

第一个ASP.NET MVC项目实现一个Hello Word

我们打开vs 我这里使用vs2015

如果是低版本的vs 比如vs2010 可能要先安装mvc 去官网下载一个mvc的安装包

打开vs 右击文件 新建项目

如果像我这样 没有mvc的模板选中的话 那么久要安装这个asp.net core

https://www.asp.net/core

在VS中打开Nuget控制台,输入(工具-nuget管理器)

Install-Package Microsoft.AspNet.Mvc -Version 5.0.0

VS2015安装ASP.NET MVC4

http://www.microsoft.com/zh-cn/download/details.aspx?id=44533

下载安装 AspNetMVC4.msi

vs 2015 updatge2 只有选中.NET 4.5然后选择web 空项目 才有这个mvc的模板

参考页面http://tieba.baidu.com/p/3978379647

说明:

  • VS2015 若要开发 ASP.NET MVC 5,需选择 “Web 应用程序”​ 模板并勾选 MVC;若模板缺失,可通过安装 ASP.NET MVC 4/5​ 或升级 VS 解决。
  • 传统 ASP.NET MVC 5 最新包为 Microsoft.AspNet.Mvc 5.x(非 5.0.0),建议 NuGet 安装最新稳定版。
  • ASP.NET Core MVC 与 传统 MVC 不兼容,命名空间为 Microsoft.AspNetCore.Mvc

介绍一下MVC项目的文件结构

上节课创建好的vs项目,目录像下面的

APP_DATA 这个可以不要 一般用来存放数据文件

app_start:应用程序启动,这里面的一些类 方法 都是应用程序启动的时候,执行

BundleConfig.cs:让我们的视图view输出 js css 着一些

FilterConfig.cs :过滤相关的?

IdentityConfig.cs :单点登录 对接整合有关?

RouteConfig.cs : 路由相关的 (怎么样让用户输入的地址 找到对应的方法 localhost/hello/index –>hellocontroller.cs index方法)

Content 这个文件夹主要是存放css js着一些静态的文件 当然我们可以存放到其他地方 不一定是这里

Controllers 文件夹就是存放我们说的 MVC里面的C 的文件了,我们可以存放在一个独立的类库项目里面

fonts 文件夹 在存放字体

Models 文件夹是存放MVC里面的M 的文件 就是一些实体类 EF也用到

Scripts文件夹是存放JS代码,当然我们也可以将它放到其他地方

Views 这个文件夹是存放 视图文件的,它里面还分文件夹 每个文件夹呢都和控制前的前缀名称一样 然后呢里面的视图就是和控制器里面的方法名一样

说明:

  • App_Start 内常见类:BundleConfig(打包压缩)、FilterConfig(全局过滤器)、RouteConfig(路由)、IdentityConfig(ASP.NET Identity 配置)。
  • Views 下每个子文件夹对应控制器名(如 Hello 对应 HelloController),视图名对应 Action 名(如 Demo.cshtml 对应 Demo 方法)。
  • Global.asaxApplication_Start 调用各配置类的注册方法。

我们来重点说说和改造一下我们的这个HelloWord项目

万丈高楼平地起 我们学任何东西都要 一步步来 循序渐进

我们主要是包含这几步

1 在Controllers文件夹里面 添加HelloController.cs的控制器 主要前缀的名称

2 是在HelloController.cs里面添加了一个Index方法 我们现在继续创建一个Demo的方法(action)

public ActionResult Demo()
        {
            return View();
        }Code language: PHP (php)

3 在Views文件里面的Hello文件夹下面添加一个视图 cshtml后缀

我们在action里面使用viewbag来存放一个东西,然后在视图这边显示出来

public ActionResult Demo()
        {
            ViewBag.Title = "这是例子页 第04课";
            ViewBag.ADSFDSFDSF = "";
            return View();
        }Code language: PHP (php)

然后在Demo .cshtml

<body>
    <div>
        @ViewBag.Title 
    </div>
</body>Code language: HTML, XML (xml)

http://localhost:16303/Hello/demo

http://localhost:16303/类名前缀/方法名

这个过程 他是怎么进来的

我们这里需要先理解一下 RouteConfig这个路由类

它里面有帮我们注册一个叫Default的路由

public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
        }
    }Code language: PHP (php)

这里面其实就算说我们的url规则是 先对应控制器-HelloController

如果没写 那默认是Home 和Index方法

http://localhost:16303/ —》HomeController 里面的Index方法

http://localhost:16303/home/ —>HomeController 方法没写 则就是Index

http://localhost:16303/hello/ —>HelloController 方法没写 则就是Index

http://localhost:16303/hello/index —>HelloController 方法则就是Index

http://localhost:16303/hello/demo —>HelloController 方法就是demo

http://localhost:16303/index/ —>indexController

说明:

  • ViewBag 是动态类型,可任意添加属性,但编译时无智能提示。
  • 路由匹配顺序:先到先得,默认路由 {controller}/{action}/{id} 是兜底规则。

我们来改造一下我们的项目,去掉一些不必要和搭建EF环境

微软这个MVC模板,他默认是帮我们添加了一些他自己的代码的

EF呢是微软的这个实体框架,它可以方便我们操作数据库,具体更详细的学习,同学们可以看我们的这个

http://www.bamn.cn/course/lesson/23

在web.config里面 我们添加链接字符串

<add name="dblink"
    connectionString="Data Source=.\MSSQLSERVER2008;Initial Catalog=EFDemo;User ID=sa;Password=123321;"
    providerName="System.Data.SqlClient"/>Code language: HTML, XML (xml)

说明:

  • EF(Entity Framework)是 ORM 框架,支持 Code First、Database First、Model First。
  • 连接字符串 providerName 需为 System.Data.SqlClient(EF6)或 Microsoft.EntityFrameworkCore.SqlServer(EF Core)。

搭建EF开发环境 第一节

EF和ASP.NET MVC是最佳的搭配伙伴

通过他们,我们可以快速方便地开发网站

1 先配置我们的这个web.config里面的连接字符串

<connectionStrings>
    <add name="dblink"
    connectionString="Data Source=.;Initial Catalog=bbs;User ID=sa;Password=123321;"
    providerName="System.Data.SqlClient"/>
  </connectionStrings>Code language: HTML, XML (xml)

2 创建上下文BBSContext

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;
using WebApplication1.Models;
namespace WebApplication1.App_Code
{
    public class BbsContext : DbContext
    {
        public BbsContext():base("name=dblink")
        {
        }
        public DbSet<Account> account { set; get; }
    }
}Code language: HTML, XML (xml)

说明:

  • DbContext 构造函数中 "name=dblink" 表示使用 web.config 中名为 dblink 的连接字符串。
  • DbSet<Account> 映射到数据库表(默认表名为 Accountsaccount,取决于 EF 版本和配置)。

搭建EF开发环境 第二节 处理dbcontext问题

上节课发现我们无法调用bbscontext这个类,后来发现是我们这个bbscontext.cs文件可能是格式不对还是怎么样,vs将它当成了一个普通文件来处理,以后同学们遇到这类问题,应该也要猜测可能是这样,处理方式就是备份原来cs文件到其他地方,然后从vs中删除,再重新创建,然后再拷贝进去。

protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            using (var bbsContext = new WebApplication1.Models.BbsContext())
            {
                //如果不存在数据库则创建
                bool res = bbsContext.Database.CreateIfNotExists();
            }
        }Code language: JavaScript (javascript)

运行后 就可以了

调用数据上下文添加一条记录

public ActionResult Index()
        {
            var bbsContext = new BbsContext();
            bbsContext.Accounts.Add(new Account() { AddTime=DateTime.Now, Name = "叶子", Pwd = "123321", Status=false });
            bbsContext.SaveChanges();//只有执行这一步才会添加到数据库里面
            return View();
        }Code language: PHP (php)

说明:

  • CreateIfNotExists() 已过时,推荐使用 Database.SetInitializer 或 Code First 迁移(Migrations)。
  • 生产环境不应在 Application_Start 中执行数据库创建,应使用 Update-Database 命令。

MVC中表单提交-以前的这种使用Form来获取

以前我们在aspx ashx 这个开发的时候,前台表单提交到后台后,我们是通过

Request.Questing Form 着一些能搞拿到数据

那么我们现在在这个MVC中当然也可以使用这种方式获取数据了

添加标注[httpget]和[httppost]可以区分那个用来第一次get呈现 那个用来处理post

[HttpGet]
        public ActionResult Register()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Register(int? d)
        {
            string name = Request.Form["name"];
            string pwd = Request.Form["pwd"];
            bbsContext.Accounts.Add(new Account() { AddTime = DateTime.Now, Name = name, Pwd = pwd, Status = false });
            int res = bbsContext.SaveChanges();//只有执行这一步才会添加到数据库里面 res>0表示成功 sql受影响记录数
            return Content("注册成功");
        }Code language: PHP (php)

说明:

  • Request.Form 是传统方式,在 MVC 中可用但不推荐,因为破坏了 MVC 的模型绑定优势。
  • [HttpGet]/[HttpPost] 用于区分同一 Action 的不同 HTTP 请求方法。

MVC中表单提交-直接在action方法的参数中绑定

就是直接在action方法 里面写上我们的表单的参数的name的名称,然后mvc会自动把数据存放到这个参数里面的

前台的input的name自动对应上去

[HttpPost]
        public ActionResult Register(string name,string pwd)
        {
            bbsContext.Accounts.Add(new Account() { AddTime = DateTime.Now, Name = name, Pwd = pwd, Status = false });
            int res = bbsContext.SaveChanges();//只有执行这一步才会添加到数据库里面 res>0表示成功 sql受影响记录数
            return Content("注册成功");
        }Code language: PHP (php)

说明:

  • MVC 自动模型绑定:根据表单字段 name 匹配 Action 参数名(不区分大小写)。
  • 参数类型自动转换(如 int? d),转换失败则为 null

MVC中表单提交-直接表单实体绑定

我们试了一下,上一节课里面的action的参数的大小写好像是没问题

我们把action的参数改成这样

public ActionResult Register(string nAme,string pwd)

都是可以的

日期提交过来的时候 因为表单里面没有这个日期,所以我们的日期就为null 这样保存进数据库就会报错

所以我们要把这个日期 添加到这个hidden里面

<form action="/account/register" method="post">
            <div>账号:<input type="text" name="name"/></div>
            <div>密码:<input type="password" name="pwd"/></div>
            <input type="hidden" name="addtime" value="@DateTime.Now"/>
            <div><input type="submit" value="提交"/></div>
        </form>Code language: HTML, XML (xml)

然后action里面就直接绑定到了实体里面

[HttpPost]
        public ActionResult Register(Account model)
        {
            bbsContext.Accounts.Add(model);
            int res = bbsContext.SaveChanges();
            return Content("注册成功");
        }Code language: PHP (php)

说明:

  • 实体绑定:MVC 自动将表单字段映射到实体属性(根据名称匹配)。
  • 隐藏域 addtime 用于传递默认值,避免数据库报错。

使用HtmlHelper来呈现表单

我们上面的视图里面,都是直接写以前的html表单,这样的话可以是可以,但是速度肯定是没有这么快

我们把前台的cshtml里面的表单改造成这样子

@using (Html.BeginForm("register", "account", FormMethod.Post))
        {
             <div>账号:@Html.TextBox("name")</div>
             <div>密码:@Html.Password("pwd")</div>
             @Html.Hidden("addtime",DateTime.Now)
             <div><input type="submit" value="提交" /></div>
        }Code language: HTML, XML (xml)

速度比之前的html要快很多,因为他支持智能提示

说明:

  • HtmlHelper 提供强类型辅助方法,生成表单元素,支持智能提示和验证。
  • Html.BeginForm 生成 <form> 标签,默认 method 为 POST。

视图页面使用Model来呈现

我们上面呈现表单的时候使用HtmlHelper 同时我们还需要输入名称name

这节我们来使用Model,那么就更强大了

@model WebApplication1.Models.Account
<body>
    <div>
        @using (Html.BeginForm("register", "account", FormMethod.Post))
        {
             <div>账号:@Html.TextBoxFor(m=>m.Name)</div>
             <div>密码:@Html.PasswordFor(m=>m.Pwd)</div>
             @Html.HiddenFor(m=>m.AddTime,@Value = DateTime.Now.ToString())
             <div><input type="submit" value="提交" /></div>
        }
    </div>
</body>
</html>Code language: HTML, XML (xml)

说明:

  • @model 指定强类型视图,使用 TextBoxFor 等强类型辅助方法,编译时检查属性名。
  • HiddenFor 生成隐藏域,用于传递属性值。

另外一个更强大的Helper 就是EditorForModel

类似于我们上面的着一些TextBoxFor

但是他是把整个实体呈现出来

@using (Html.BeginForm("register", "account", FormMethod.Post))
        {
             @Html.EditorForModel()
             <div><input type="submit" value="提交" /></div>
        }Code language: CSS (css)

虽然这样子很快一个表单就出来了

比如这个id 和addtime 其实是不需要我们添加的

说明:

  • EditorForModel() 根据实体所有属性自动生成编辑表单,可通过数据注解(如 [ScaffoldColumn(false)])控制显示。
  • 适用于快速生成 CRUD 表单,但灵活性较低。

完善我们的这个EditorForModel 给实体添加标注 进行验证

比如有一些字段是必填,比如我们这个Name字段是别填

我们这个ID字段是隐藏

我们这个addtime是隐藏的

[Required]
        public string Name { set; get; }Code language: JavaScript (javascript)

上面给Name加了标注 表示Name是必填

@using (Html.BeginForm("register", "account", FormMethod.Post))
        {
             @Html.EditorForModel()
             <div><input type="submit" value="提交" /></div>
        }Code language: CSS (css)

配置文件里面的appsetting要开启

<appSettings>
    <add key="ClientValidationEnabled" value="true" />Code language: HTML, XML (xml)

后台cs这边要进行验证

if (ModelState.IsValid)
            {
                bbsContext.Accounts.Add(model);
                int res = bbsContext.SaveChanges();
                return Content("注册成功");
            }
            else
            {
                return Content("注册失败");
            }Code language: JavaScript (javascript)

我们需要引入jquery

<script src="~/Scripts/jquery-1.10.2.min.js"></script>
    <script src="~/Scripts/jquery.validate.js"></script>
    <script src="~/Scripts/jquery.validate.unobtrusive.js"></script>Code language: HTML, XML (xml)

说明:

  • 数据注解 [Required] 实现服务端验证,ModelState.IsValid 检查验证结果。
  • 客户端验证需引入 jQuery Validate 和 unobtrusive 脚本,并在 web.config 中启用 ClientValidationEnabledUnobtrusiveJavaScriptEnabled

我们来开始讲一下这个mvc的路由 默认路由器

MVC默认就就帮我们配了一个路由

为什么我们访问这个地址http://localhost:16303/Account/Register

它可以找到我们的AccountController这个控制器下面的这个Register方法呢?

这其实是靠我们的路由

默认路由是在我们的appstart的文件夹里面 有配置

RouteConfig .cs 就是这一个了

public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
        }Code language: JavaScript (javascript)

http://localhost:16303/Account/Register/2

http://localhost:16303/Account/Register

http://localhost:16303/Account/ 这一个找的的index方法 因为没有写就是找默认的

http://localhost:16303 这一个就是找Home控制器 和Index方法了

http://localhost:16303/Register 这里肯定不会找Home控制器 而是把Register当成控制器了

http://localhost:16303/1

说明:

  • 路由匹配顺序:从上到下,匹配到即停止。
  • UrlParameter.Optional 表示参数为可选。

自定义自己的路由和顺序的问题

默认的路由是default,我们也可以自定义自己的路由

RouteCollection routes 往这个路由表里面添加

http://localhost:16303/account/register/index

http://localhost:16303/account/register/

这两个地址走的应该还是上面这一个?

我们先删了自定义的路由,然后再访问下面这个地址

http://localhost:16303/home/index/1sd

这样还是可以访问

这两个都可以访问

http://localhost:16303/account/register/index/1132这样子访问还是会报错的

因为路由的匹配是从上往下,上面的优先 如果上面的匹配到,那么下面的就不会匹配,所以我们如果有特殊的路由 那么应该放到下面

像我上面自定义的这个路由,就是一个特殊的路由,它是针对account这个固定地址的

现在我们交换了一个位置以后

http://localhost:16303/account/register/index

这个地址现在就不可以访问了,因为它可以匹配到上面的路由,所以它走了是上面的路由

那么register就是控制器类 index就是方法 但是我们系统没有定义这样的控制器和方法 所以报错了

http://localhost:16303/register/index

这个也一样不能访问 因为它走的是下面的路由 但是也没有定义这样的类和方法

localhost:16303/account/register

这一个也不可以,因为它匹配的是上面的,只要是account的就是上面的路由了

其实他就等价于 localhost:16303/account/register/index index其实是使用默认的

localhost:16303/account/ 这样 其实就等价于 localhost:16303/account/home/index

localhost:16303/account/ 这个还是可以访问 因为存在home类index方法

说明:

  • 自定义路由应放在默认路由之前(特殊规则优先)。
  • 路由顺序错误会导致 404 或匹配到错误控制器。

使用命名空间来区分不同路由规则下面的控制器

我们给路由规则配置第四个参数,就是规定不同的路由用不同的命名空间下面的控制器类

方法很简单,只需要配置MapRoute

http://localhost:16303/User/home/index 走的是上面的路由

http://localhost:16303/ 走到是下面的路由

但是如果写成http://localhost:16303/User/ 结果发现出错了

http://localhost:16303/User/home/ 这个反而可以

发现应该是因为我们刚好有一个User的目录,我们稍微改造一下自定义的路由

routes.MapRoute(
                name: "User",
                url: "User1/{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                namespaces: new string[] { "WebApplication1.User"}
            );Code language: JavaScript (javascript)

然后发现都可以访问了

http://localhost:16303/User1/home/index

http://localhost:16303/User1/home/

http://localhost:16303/User1/

说明:

  • namespaces 参数用于解决控制器重名冲突,指定路由优先查找的命名空间。
  • 注意路由 URL 中的 User1 避免与物理目录冲突。

路由规则实践

我们先看一下这个博客园的文章和博客首页的规则是怎么样的

具体某个博客的首页

http://www.blogger.com/john

具体一篇文章是

http://www.blogger.com/john/p/6305770.html

http://www.blogger.com/sanshi/archive/2009/08/30/1556677.html

怎么让上面的请求能对应一个控制器和方法

首先这样的规则 肯定是特殊的,所以我们就要写到上面

//http://www.blogger.com/john/
            routes.MapRoute(
                name: "Blog",
                url: "/{name}",
                defaults: new { controller = "Blog", action = "Index", id = UrlParameter.Optional },
                namespaces: new string[] { "WebApplication1.Controllers" }
            );Code language: JavaScript (javascript)

然后我们在WebApplication1.Controllers的目录下面添加BlogController类再添加一个index方法

public class BlogController : Controller
    {
        // GET: Blog
        public ActionResult Index(string name)
        {
            return View();
        }
    }

// constraints:

// 一组表达式,用于指定 url 参数的值。

routes.MapRoute(
                name: "Blog",
                url: "{name}",
                defaults: new { controller = "Blog", action = "Index", id = UrlParameter.Optional },
                constraints: new { name = "\\w+"},
                namespaces: new string[] { "WebApplication1.Controllers" }
            );Code language: JavaScript (javascript)

说明:

  • constraints 使用正则约束参数格式,如 name = @"\w+" 只允许字母数字下划线。
  • 博客园风格路由需放在默认路由之前,避免被 {controller}/{action} 捕获。

完成Blogger文章路由规则

类似这种文章http://www.blogger.com/wintersun/archive/2009/01/12/1374473.html

我们创建一个新的路由规则,需要放到顶部,因为他们是特殊

//http://www.blogger.com/wintersun/archive/2009/01/12/1374473.html
            routes.MapRoute(
                name: "Article",
                url: "{name}/archive/{year}/{month}/{day}/{id}.html",
                defaults: new { controller = "Blog", action = "Article", id = UrlParameter.Optional },
                constraints: new { name = @"[a-z]+",year = @"\d4", month = @"\d2", day = @"\d2", id = @"\d+" },
                namespaces: new string[] { "WebApplication1.Controllers" }
            );Code language: JavaScript (javascript)

然后我们才blog的控制器哪里添加一个Article的方法

public ActionResult Article(string name,int year,int month,int day,int id)
        {
            return View();
        }Code language: PHP (php)

当我们访问http://localhost:16303/wintersun/archive/2009/01/12/1374473.html

结果发现是404错误,那是因为我们的IIS就已经处理了这个

那么怎么办?我们要么就是去掉IIS的处理,也让html后缀交给aspnet isapi来处理

📌 补充/纠错说明:

  • .html 扩展名默认被 IIS 处理,需配置 IIS.html 交给 ASP.NET 处理(如 runAllManagedModulesForAllRequests="true"),或使用 URL 重写模块。
  • 约束中 year = @"\d4" 应为 year = @"\d{4}"(原笔记第20课有纠正)。

完成博客园文章路由规则-问题的解决

我们上节课,发现路由规则哪里配置好像无法使得我们这个地址的访问能进入到路由中

year = @”[0-9]4″ 这样子配 好像反而不起作用

我们改成year = @”[0-9]+”,反而就可以

我们继续猜测 改成year = @”[0-9]{4}” ,这样是起作用的

localhost:16303/sdsdf/archive/20309/11/12/13744 如果年份改为五位 就又不启用

然后我们改成year = @”[0-9]{4,5}” 发现是可以 意思就是年份4到5位 如果是三位反而又不行

http://localhost:16303/sdsdf/archive/039/11/12/13744

继续猜测 改为year = @”\d{4,5}” 又可以

我们恢复.html

http://localhost:16303/sdsdf/archive/0039/11/12/13744.html

还是不行 所以还是无法达到aspnetisapi这里面

说明:

  • 正则中 \d4 无效,正确为 \d{4}[0-9]4 无效,正确为 [0-9]{4}
  • .html 后缀问题需通过 IIS 配置解决(见第19课补充)。

区域的学习Area

所谓区域,英文是area,其实就是提供功能区域的区分

我们现在创建一个mvc项目,里面有三个文件夹 controllers models views 这三大快分别表示MVC的三个部分,那么这三部分我们就可以开发一个网页,但是有些时候,某一些功能是比较独立的,比如会员中心 论坛 这一些其实可以有自己的一套MVC

创建区域area,其实很简单

右击项目-创建-区域-输入BBS

一个项目可以有多个区域,这些区域放在Areas文件夹下面,它里面就又一套MVC

比如我们这里创建了两个区域 里面就有三个文件夹controllers models views 这三个就可以构成我们的一套MVC

还有一个xxxAreaRegistration.cs 这个是区域的一个注册类

这一个RegisterArea方法是在哪里调用呢?

其实他是通过反射来调用的

在我们的这个global.asax 里面 的

Application_Start事件 第一句就是注册我们的区域的路由

AreaRegistration.RegisterAllAreas();

它会注册所有的区域的路由,并且是比默认路由要优先 所以放在第一

http://localhost:16303/bbs/home/index

说明:

  • 区域用于大型项目模块隔离,每个区域有独立路由(通过 AreaRegistration 注册)。
  • 区域路由优先于主路由,访问格式:/区域名/控制器/动作

区域独立放到一个类库里面

如果这样子可以的话,那么我们的项目就更好的分模块了

我们现在就尝试吧BBS的区域放到一个类库里面,放到类库其实还是不大好

因为vs的智能提示就没用

所以我们还是创建MVC项目更好

其实关键一步就是引用,主项目里面引用我们的这个新的mvc项目

删除处理Web.config之外的东西,并且移动一下文件

http://localhost:16303/BBS/Home/Index

📌 补充/纠错说明:

  • 将区域放到独立类库需手动处理视图编译和路由注册,推荐使用 MVC 项目​ 作为模块,主项目引用。
  • 也可使用 ASP.NET Core 的 Razor Class Library​ 实现模块化。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注