大多数人,都低估了编程学习的难度,而高估了自己的学习能力和毅力。
当前系列: ASP.NET 修改讲义
复习:Web框架MVC

新建MVC项目

新建(或者在solution中添加)项目,选择:.NET Framework -> MVC(注意不需要勾选:https/docker/authentication等我们没讲的选项)


运行静态页面

供学习前端内容时使用
  • 在项目上右键:Add - New Folder,键入Static,创建一个Static文件夹(非必须,但便于管理)
  • 在Static文件夹上右键:Add - New Item,选择 Html Page(以及以后的.js/.css文件类型),键入Home

在新建html文件上右键 - View in Browers,就可以在浏览器中查看页面效果了。

还可以修改默认浏览器:


项目和文件结构



简略说明:

  • MVC核心文件夹
    1. Models
    2. Views
    3. Controllers 
  • 静态资源:
    1. Content:.css文件
    2. Scripts:.js文件
    3. fonts:生成图标用
    4. favicon.ico
  • 项目启动
    1. Global.asax:应用启动配置
    2. App_Start:入口
  • Web.config:项目配置文件
  • 外部引用配置:References和packages.config

IIS Express

演示(并同时设置Global.asax、Controller、Action和View中的断点):F5运行,IIS express启动:

全称:Internet Information Service,是服务器上安装的一个“软件”,这个软件可以响应http请求。复习

IIS Express:是Visual Studio内置的IIS演示版,是精简的/用于开发的/迷你的 IIS。

因为VS中所有的ASP.NET项目都运行在localhost(本地主机)上,所以VS用随机生成的端口号(port)来区别各个项目。(复习:域名/端口/路径

VS在运行时启动了一个IIS express,在本地模拟了真实的服务器环境(environment),浏览器是连接着这个IIS在运行的!

——Visual Studio被称之为IDE,就是因为它自带了这些组件,能够完成这些工作(如果使用VS code需要自己搭建这些环境)

运行顺序

URL:http://localhost:62670/Home/About

  1. Global.asax.cs:一次启动只运行一次
  2. HomeController中About()方法
  3. \Views\Home\About.cshtml

其他

更快捷的调试(不用每次都重新启动):

  • View(.cshtml)里面的内容,修改之后可以直接生效(刷新浏览器);
  • Controller等.cs重新编译后生效
  • Global.asax.cs中涉及的内容必须重启后才生效。@想一想@:为什么?


Alter+Enter修改项目属性,在Web项下,重新指定端口号和启动页面

选择浏览器


Route

复习:当一个Http请求带着路径发送到服务器,ASP.NET会首先解析它的Path:

  • 如果有是.htm/.css/.js等静态内容标志的后缀,直接将Url Path对应的静态文件返回给客户端
  • 否则,比如:/Register,注意没有.htm后缀,ASP.NET会根据route规则,将这个请求分配给相应的Handler(endpoint)进行处理。

默认配置

route配置在RouteConfig.RegisterRoutes()方法中,一般不予修改(即:实际上还是可以更改)。

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
name:开发者自定(比如改成HomeIndex),不能重复。一个MapRoute()方法定义一条route规则

url按斜杠分隔成“段”(segment)

  • {controller}和{action},不能修改,对应着应使用的controller和action,比如输入的url是 /Article/Category,对应的是ArticleController下的Category()
  • {id}:route data的名字,可由开发者自定义(比如改成name),比如输入的url是 /Article/Category/12,MVC会将12解析成Category(int id)的参数id的值

defaults

id = UrlParameter.Optional,说明id是可选的。比如/Article/Category没有id仍然是可以匹配这条规则的。

当url中没有{controller}或{action}时,使用的controller和action,比如输入的url是:

  • /Article,匹配不了Action,就只有使用默认的Index()
  • /,匹配不了Controller和Action,就只有使用默认的HomeController和Index()

演示:改动defaults并进行匹配

404错误

如果根据route规则,找不到匹配的Controller和Action,ASP.NET报404错误 



---------- 以下内容在 Model绑定 之后再讲 --------------

RouteData

URL Path中包含的“变量”,比如/Article/Single/2 中 2 就是变量,它还可以是3是4是5……

这其实和URL parameter传值的作用一样:/Article/Single/2就类似于/Article/Single?id=2。

声明

观察MVC默认的route规则,要定义route data:

  • 首先要给它一个名字,比如id
  • 然后使用花括号({})标记

获取

RouteData的和Url Parameter都是从URL中获取,但他们的获取方式是不一样的:

  • 在View中
    @ViewContext.RouteData.Values["id"]
  • 在Action中
    //通过Request对象:
    object id = Request.RequestContext.RouteData.Values["id"];
    //通过BaseController的属性
    object id = RouteData.Values["id"];
    注意这样获取的RouteData是object类型的,通常我们获取过后还需要进行类型转换。
    所以最便捷的方法是利用Model绑定,在Action方法中声明参数:
    public ActionResult Single(int id)

constraints

约束,对RouteData一些限制

MVC的constraint需要使用正则表达式。比如:

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
    constraints: new { id = @"\d+" }   //只能是数字

演示:

  • /Article/Single/2022:OK
  • /Article/Single/fg:404错误

@想一想@:为什么需要路由约束?

自定义配置

可以在RegisterRoutes()中添加更多的MapRoute()方法,制定更多的Route规则。比如:

routes.MapRoute(
    name: "ArticleSingle",
    //希望:url:Article/2 映射到 ArticleController.Single(id)
    url: "Article/{id}",  
    defaults: new { controller = "Article", action = "Single"},
    constraints: new { id = @"\d+" }   //只能是数字
);

这就:

  • 为MVC添加了一个名为“ArticleSingle”的route规则,
  • 该规则能匹配以Article开头的,后面接着一个{id}值的url,比如:/Article/23,
  • 并将该HttpRequest请求交给ArticleController下的Single() Action处理

自定义的route规则是可以“千变万化”的。演示:/Article-2022

url: "Article-{id}",

优先级

当route规则多了以后,就有可能出现“一个URL可以由多个route规则匹配的情形

比如,/Article/Category,现有两个route规则,他们都可以匹配URL Path:

  • 既可以由默认的route匹配
  • 也可以由我们自定义的"/Article/{id}"匹配(如果没有id的constraints的话,#体会#constraints的作用)

这时候,就需要确定哪一个route规则的优先级更高。

MVC中的route规则优先级,按其在RegisterRoutes中注册(书写)的先后顺序从高到低排列。

演示:把这个自定义规则放在Default规则之后……

伪静态

有时候客户会要求url是这种带着html后缀名格式:/Home/Index/3.html

你可能会想到,简单,RegisterRoutes()中调整一下就OK,比如:

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}.html",

演示:

  • 无法实现期望的route
  • 在项目下新建一个

因为ASP.NET会首先根据请求文件类型(文件名后缀)判断是否进行route。默认的,html文件被视为静态文件请求,不会进入route.

所以需要在web.config中添加:

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
  </system.webServer>

告诉ASP.NET对所有请求(All Reuests)使用route(All Managed Modules)。


建议:随着项目规模扩大,route冲突会变得越来越多。所以,

  • 合理规划route
  • 尽可能使用默认route,而不是自定义route
  • 尽可能的使用约束,减少route冲突

非常重要。

总结复习:三种错误


  1. 404
  2. mulitple actions
  3. no view found



area

随着项目规模的扩大,我们可能需要对controller进行分类管理,并且相应的扩展默认的path层级,比如:

  • 所有和Student相关的:/Student/{controller}/{action}/{id}
  • 所有和Code相关的:/Code/{controller}/{action}/{id}
  • ……

可以在ASP.NET项目上添加area。

演示:先建文件夹Areas,然后在Areas上添加Area

每个area下面就像一个迷你MVC项目,一样有Controllers和Views文件夹,一样的按MVC规则运行:

注意还有一个StudentAreaRegistration,可以在里面添加route规则。

正是因为它,所有以/Student/开头的path,都会被首先路由到这个area进行处理。

演示:/Student/Enroll(/Index)进入erea,而不是StudentController.Enroll()


作业


  1. 使用route修改以前的Url格式:
    1. 文章修改:/Article/Edit?id=7 => /Article/Edit/7
    2. 文章单页:/Article/Single?id=1 => /Article/1
    3. 所有文章列表:/Article/Index?pageIndex=3 => /Article/Page-3
    4. 文章分类列表:/Article/IndexOfCategory?pageIndex=3&category=1 => /Article/Category-1/Page-3
    5. 博主文章列表:/Article/IndexOfAuthor?author=5&pageIndex=2 => /Article/User-5/Page-2
    6. 任务历史月记录:/Task/HistoryOfMonth?year=2019&month=8&id=5 => /Task/History/5/2019/8
    根据你的选择,可以用Suggest/Problem代替Article。


学习笔记
源栈学历
今天学习不努力,明天努力找工作

作业

觉得很 ,不要忘记分享哟!

任何问题,都可以直接加 QQ群:273534701

在当前系列 ASP.NET 中继续学习:

多快好省!前端后端,线上线下,名师精讲

  • 先学习,后付费;
  • 不满意,不要钱。
  • 编程培训班,我就选源栈

更多了解 加:

QQ群:273534701

答疑解惑,远程debug……

B站 源栈-小九 的直播间

写代码要保持微笑 (๑•̀ㅂ•́)و✧

公众号:源栈一起帮

二维码