前言

我们知道,在 MVC 应用程序中,有一部分约定的内容。其中关于 Controller 的约定是这样的。

  • 每个 Controller 类的名字以 Controller 结尾,并且放置在 Controllers 目录中。
  • Controller 使用的视图是在 Views 主目录的一个子目录中,这个子目录是根据控制器名称(后面减去Controller后缀)来命名的。

明白了以上约定之后,就来一起看看下面吧。

Controller VS NonController 中内置的约定

在 ASP.NET Core MVC 中已经统一了 MVC 和 Web Api 及 Web Pages, 他们具有相同的 Controller ,并且在 RC2 之后的版本中,ASP.NET Core MVC 支持了 POCO Controller,所以你在做一个 Web Api 的 Controller 的时候不需要再继承自 Controller 基类。

POCO Controller 即 public 的,非抽象的,没有任何继承,不实现任何接口的 Controller 类,类似于 POCO Class,仅仅是以 Controller 结尾而已。

到这里,有些同学可能会问了,在 POCO Controller 中如果我想获取 HTTP 上下文的一些东西应该怎么获取呢? 嗯?。。。 这确实是个问题。。。。怎么办呢? 老实的继承基类 Controller 吧,因为 Vnext 中的 POCO Controller 属性注入已经被取消了。

如果你创建了一个 POCO Controller ,那么他们的名字必须以 Controller 结尾,只有这样他们才是一个有效的 Controller,不然的话,MVC 不会认为你这是一个 Controller 对象。即使你具有 Route 之类的标记也不可以。

所以,在创建一个 MVC Controller 的时候,就有两个先决条件:

  • -- 继承自 Controller 基类
  • -- 或者使用一个以 Controller 结尾的名字

下面是创建两种 Controller 的一个 Web Api Controller示例:

[Route("api/[controller]")]
public class FooController : Controller
{
    [HttpGet]
    public string Get()
    {
        return "foo";
    }
}

[Route("api/[controller]")]
public class BarController
{
    [HttpGet]
    public string Get()
    {
        return "bar";
    }
}

现在有同学可能会问了,第一个既然已经继承了 Controller 基类,再在定义 Controller 的时候还要加 Controller 后缀不是多此一举么?这样写可不可以呢?

[Route("api/[controller]")]
public class Foo : Controller
{
    [HttpGet]
    public string Get()
    {
        return "foo";
    }
}

好吧,这样子也是正确的。为什么呢?这是因为继承的基类 Controller 已经被打上了 ControllerAttribute 的标记,打上了这个标记之后,在构建扫描的时候就会被认为是一个 Controller,也就是说整个继承树已经被认为是一个有效的 MVC Controller 了。

那么,有同学又问了,这样可不可以呢?

[Route("api/[controller]")]
public class Bar
{
    [HttpGet]
    public string Get()
    {
        return "bar";
    }
}

这样子是不行的,因为这是一个 POCO Controller,没有任何标记使 MVC 框架会认为这是一个有效的Controller,这个时候,如果 如果想让框架认为这是一个有效的 Controller,可以通过添加 ControllerAttribute 的方式:

[Controller]
[Route("api/[controller]")]
public class Bar
{
    [HttpGet]
    public string Get()
    {
        return "bar";
    }
}

这个时候,MVC 框架就会认为这是个有效的 Controller 了。

同样的,这样的代码也是有效的,因为基类已经有了 ControllerAttribute 标记 :

[Controller]
public class ApiBase {}

[Route("api/[controller]")]
public class Bar : ApiBase
{
    [HttpGet]
    public string Get()
    {
        return "bar";
    }
}

还有一种可能性,就是当你有一个类,它恰好是以 Controller 结尾,但是实际上并不是一个 Controller 类怎么办呢? 这个时候,你就需要添加一个 NonControllerAttribute 标记,来声明当前的类并不是一个 MVC 的 Controller 类,从而避免在构建的时候,框架会认错。

[NonController]
public class DemoController
{
    // 非 action 代码
}

有一点需要注意的是,NonControllerAttribute 标记比 ControllerAttribute 具有更高的优先级,所以当一个 Controller 同时具有这两个标记的时候,会以 NonControllerAttribute 为准。

实际上,只要是整个 Controller 继承树中有一个 Controller 被标记为 NonControllerAttribute 的时候,整个继承树的 Controller 均会被认为是无效的 Controller 了。


本文地址:http://www.cnblogs.com/savorboard/p/dontnet-controller.html
作者博客:Savorboard
欢迎转载,请在明显位置给出出处及链接

ASP.NET Core MVC 中的 [Controller] 和 [NonController]的更多相关文章

  1. 在ASP.NET Core MVC中子类Controller拦截器要先于父类Controller拦截器执行

    我们知道在ASP.NET Core MVC中Controller上的Filter拦截器是有执行顺序的,那么如果我们在有继承关系的两个Controller类上,声明同一种类型的Filter拦截器,那么是 ...

  2. 006.Adding a controller to a ASP.NET Core MVC app with Visual Studio -- 【在asp.net core mvc 中添加一个控制器】

    Adding a controller to a ASP.NET Core MVC app with Visual Studio 在asp.net core mvc 中添加一个控制器 2017-2-2 ...

  3. ASP.NET MVC和ASP.NET Core MVC中获取当前URL/Controller/Action (转载)

    ASP.NET MVC 一.获取URL(ASP.NET通用): [1]获取完整url(协议名+域名+虚拟目录名+文件名+参数) string url=Request.Url.ToString(); [ ...

  4. ASP.NET Core MVC中Controller的Action,默认既支持HttpGet,又支持HttpPost

    我们知道ASP.NET Core MVC中Controller的Action上可以声明HttpGet和HttpPost特性标签,来限制可以访问Action的Http请求类型(GET.POST等). 那 ...

  5. ASP.NET Core MVC中的IActionFilter.OnActionExecuting方法,可以获取Controller的Action方法参数值

    用过ASP.NET Core MVC中IActionFilter拦截器的开发人员,都知道这是一个非常强大的MVC拦截器.最近才发现IActionFilter的OnActionExecuting方法,甚 ...

  6. ASP.NET Core MVC中的IActionFilter.OnActionExecuted方法执行时,Controller中Action返回的对象是否已经输出到Http Response中

    我们在ASP.NET Core MVC项目中有如下HomeController: using Microsoft.AspNetCore.Mvc; namespace AspNetCoreActionF ...

  7. ASP.NET Core MVC中Controller的Action如何直接使用Response.Body的Stream流输出数据

    在ASP.NET Core MVC中,我们有时候需要在Controller的Action中直接输出数据到Response.Body这个Stream流中,例如如果我们要输出一个很大的文件到客户端浏览器让 ...

  8. 008.Adding a model to an ASP.NET Core MVC app --【在 asp.net core mvc 中添加一个model (模型)】

    Adding a model to an ASP.NET Core MVC app在 asp.net core mvc 中添加一个model (模型)2017-3-30 8 分钟阅读时长 本文内容1. ...

  9. ASP.NET Core MVC中构建Web API

    在ASP.NET CORE MVC中,Web API是其中一个功能子集,可以直接使用MVC的特性及路由等功能. 在成功构建 ASP.NET CORE MVC项目之后,选中解决方案,先填加一个API的文 ...

随机推荐

  1. YY一下微信线下支付的场景

    在上一篇文章里面提到了 <跨行清算的实现原理>,这次来分析一下线下支付的场景和流程. 今天看到一篇文章:http://www.huxiu.com/article/23248/1.html? ...

  2. 设计算法,求AB两个整数集合的交集

    [本文链接] http://www.cnblogs.com/hellogiser/p/ab-set-intersection.html [分析] 思路1:排序法 对集合A和集合B进行排序(升序,用快排 ...

  3. 把Actor绑定到角色的插槽上

    void AMonster::PostInitializeComponents(){ Super::PostInitializeComponents(); // instantiate the mel ...

  4. codeforces 375D:Tree and Queries

    Description You have a rooted tree consisting of n vertices. Each vertex of the tree has some color. ...

  5. Android IOS WebRTC 音视频开发总结(四九)-- ffmpeg介绍

    本文主要介绍ffmpeg,文章来自博客园RTC.Blacker,支持原创,转载必须说明出处,个人微信公众号blacker,更多详见www.rtc.help 说明: ps1:如果直接从webrtc开始学 ...

  6. IOS中延时执行的几种方式的比较

    本文列举了四种延时执行某函数的方法及其一些区别.假如延时1秒时间执行下面的方法. - (void)delayMethod { NSLog(@"execute"); } 1.perf ...

  7. kthread_stop引起的OOP

    1 使用kthread_create创建线程:     struct task_struct *kthread_create(int (*threadfn)(void *data), void *da ...

  8. iOS 8安装教程图解

    苹果最新移动设备操作系统iOS 8终于在今天开放下载.相较于iOS 7,iOS 8此次最大的变化包括苹果全新的健康应用.允许用户跨设备操作的连续性(Continuity)功能等. iOS 8的整体软件 ...

  9. XShell 屏幕锁定的恢复方法(Ctrl+Q)

    操作XShell过程中很多时间大家会习惯性的按Ctrl+S进行保存. Ctrl+S在XShell的作用是屏幕锁定,很多朋友会无法操作,会直接把窗口关闭. 解决方法: 快捷键 Ctrl+Q 即能完成解锁 ...

  10. IOS - IOS之同步请求、异步请求、GET请求、POST请求

    1.同步请求可以从因特网请求数据,一旦发送同步请求,程序将停止用户交互,直至服务器返回数据完成,才可以进行下一步操作, 2.异步请求不会阻塞主线程,而会建立一个新的线程来操作,用户发出异步请求后,依然 ...