1. 程式人生 > >ASP.NET Core中的Controller

ASP.NET Core中的Controller

ASP.NET CORE出現之前我們實現的Controller,MVC都繼承自Controller基類,WebApi的話繼承自ApiController。現在ASP.NET CORE把MVC跟WebApi合併了,已經不再區分MVC或者WebApi。ASP.NET CORE的Controller繼承結構也發生了變化。我們看其他示例的時候會發現有些繼承自Controller有些繼承自ControllerBase。事實上ControllerBase是Controller的基類。也就是說如果你繼承自Controller,其實就是繼承了ControllerBase。那什麼時候該選擇直接繼承ControllerBase呢?

ControllerBase

我們先看看ControllerBase的元資料:

很長並沒有截全。可以看到ControllerBase是個抽象類,並且實現了大量的虛方法。這些虛方法大都是對應了Http的狀態碼。
比如:

public virtual OkResult Ok(); //http status 200
public virtual NotFoundResult NotFound(); //http status 404
public virtual ForbidResult Forbid(); //http status 403
public virtual CreatedResult Created(Uri uri, [ActionResultObjectValue] object value); // http status 201
...還有很多很多...

顯然這是為Restful Api設計的基類,所以當你要設計一個Restful(web api)介面的時候可以選擇繼承自ControllerBase,它已經可以滿足你的需求。

Controller

檢視下Controller的元資料:

Controller也是一個抽象類,繼承自ControllerBase,並且繼承了幾個介面。很明顯Controller比ControllerBase多的內容主要是一些跟MVC打交道的東西。
比如:Viewbag、Viewdata屬性,Json、View方法等:

public dynamic ViewBag { get; }
public ViewDataDictionary ViewData { get; set; }
public virtual JsonResult Json(object data);
public virtual ViewResult View();
...

所以如果你是需要實現一個MVC系統,想要使用cshtml模板跟razor試圖引擎渲染頁面則需要繼承Controller。

POCO Controller

除了繼承Controller、ControllerBase之外,ASP.NET CORE框架可以讓你的POCO類直接變成Controller。

使用“Controller”字尾

下面的程式碼,TestController可以正常工作嗎?

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

執行一下:

雖然TestController類並沒有繼承自任何類,但是他確實可以在ASP.NET CORE框架內正常工作。ASP.NET CORE框架預設會查詢字尾為“Controller”的類,並把它當做真正的Controller使用,在路由系統最終匹配Controller的時候它也會被嘗試匹配。

使用ControllerAttribute

如果你的控制器類有什麼特別需求,連類名都不想加入“Controller”的字尾,那麼還有一種方法就是使用ControllerAttribute。

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

執行一下:

POCO類並沒有繼承自任何類,並且也沒有“Controller”字尾命名,但是因為它被標記了ControllerAttribute同樣會被ASP.NET CORE框架認為是一個Controller。在路由系統最終匹配Controller的時候它也會被嘗試匹配。

使用NonControllerAttribute

如果你的一個類名恰巧包含“Controller”的字尾,但你並不想ASP.NET CORE框架發現它,你可以在類上加上NonControllerAttribute。這樣ASP.NET CORE框架就會忽略它。
改一下剛才的TestController,加上[NonController]:

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

執行一下:

/api/test已經匹配不到controller了。

總結

  1. 設計restful(web api)介面的時候可以繼承ControllerBase
  2. 設計MVC系統的時候可以繼承Controller
  3. 當一個POCO類名稱包含"Controller"字尾或新增ControllerAttribute的時候框架會認為這是一個控制器
  4. 當一個類不想被框架當做控制器的時候可以新增NonControllerAttribute