ASP.NET Core中的Action的返回值類(lèi)型實(shí)現(xiàn)
在Asp.net Core之前所有的Action返回值都是ActionResult,Json(),File()等方法返回的都是ActionResult的子類(lèi)。并且Core把MVC跟WebApi合并之后Action的返回值體系也有了很大的變化。
ActionResult類(lèi)
ActionResult類(lèi)是最常用的返回值類(lèi)型?;狙赜昧酥癆sp.net MVC的那套東西,使用它大部分情況都沒(méi)問(wèn)題。比如用它來(lái)返回視圖,返回json,返回文件等等。如果是異步則使用Task
public class TestController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult MyFile()
{
return File(new byte[] { }, "image/jpg");
}
public ActionResult MyJson()
{
return Json(new { name = "json" });
}
public ActionResult Ok()
{
return Ok();
}
}
IActionResult接口
ActionResult類(lèi)實(shí)現(xiàn)了IActionResult接口所以能用ActionResult的地方都可以使用IActionResult來(lái)替換。同樣異步的話使用Task包起來(lái)做為返回值。
public class ITestController : Controller
{
public IActionResult Index()
{
return View();
}
public IActionResult MyFile()
{
return File(new byte[] { }, "image/jpg");
}
public IActionResult MyJson()
{
return Json(new { name = "json" });
}
public IActionResult HttpOk()
{
return Ok();
}
public async Task<IActionResult> AsyncCall()
{
await Task.Delay(1000);
return Content("ok");
}
}
直接返回POCO類(lèi)
Asp.net Core的Controller的Action可以把POCO類(lèi)型(其實(shí)不一定是POCO類(lèi),可以是任意類(lèi)型,但是使用的時(shí)候一般都返回viwemodel等POCO類(lèi))當(dāng)做返回值,不一定非要是ActionResult或者IActionResult。Asp.net Core框架會(huì)幫我們自動(dòng)序列化返回給前端,默認(rèn)使用json序列化。同樣異步的話使用Task包起來(lái)做為返回值。
public class Person
{
public string Name { get; set; }
public string Sex { get; set; }
}
public class ITestController : Controller
{
public Person GetPerson()
{
return new Person { Name = "abc", Sex = "f" };
}
public async Task<List<Person>> GetPersons()
{
await Task.Delay(1000);
return new List<Person> {
new Person { Name = "abc", Sex = "f" },
new Person { Name = "efg", Sex = "m" }
};
}
}
ActionResult< T >泛型類(lèi)
當(dāng)我們?cè)O(shè)計(jì)restful webapi系統(tǒng)的時(shí)候習(xí)慣使用POCO做為返回值。比如我們?cè)O(shè)計(jì)一個(gè)獲取Person的api。通過(guò) /person/001 url獲取001號(hào)person。
[Route("[controller]")]
public class PersonController : Controller
{
IPersonRepository _repository;
PersonController(IPersonRepository repository)
{
_repository = repository;
}
[HttpGet("{id}")]
public Person Get(string id)
{
return _repository.Get(id);
}
}
這個(gè)方法看起來(lái)好像沒(méi)什么問(wèn)題,但其實(shí)有個(gè)小問(wèn)題。如果repository.Get方法沒(méi)有根據(jù)id查找到數(shù)據(jù),那么將會(huì)返回null。如果null做為Action的返回值,最后框架會(huì)轉(zhuǎn)換為204的http status code。

204表示No Content 。做為restful api,204的語(yǔ)義在這里會(huì)有問(wèn)題,這里比較適合的status code是404 NOT FOUND 。那么我們來(lái)改一下:
[HttpGet("{id}")]
public Person Get(string id)
{
var person = _repository.Get(id);
if (person == null)
{
Response.StatusCode = 404;
}
return person;
}
現(xiàn)在如果查找不到person數(shù)據(jù),則系統(tǒng)會(huì)返回404 Not Found 。

但是這看起來(lái)顯然不夠優(yōu)雅,因?yàn)镃ontrollerBase內(nèi)置了NotFoundResult NotFound() 方法。這使用這個(gè)方法代碼看起來(lái)更加清晰明了。繼續(xù)改:
[HttpGet("{id}")]
public Person Get(string id)
{
var person = _repository.Get(id);
if (person == null)
{
return NotFound();
}
return person;
}
很不幸,這段代碼VS會(huì)提示錯(cuò)誤。因?yàn)榉祷刂殿?lèi)型不一致。方法簽名的返回值是Person,但是方法內(nèi)部一會(huì)返回NotFoundResult,一會(huì)返回Person。

解決這個(gè)問(wèn)題就該ActionResult< T >出場(chǎng)了。我們繼續(xù)改一下:
[HttpGet("{id}")]
public ActionResult<Person> Get(string id)
{
var person = _repository.Get(id);
if (person == null)
{
return NotFound();
}
return person;
}
現(xiàn)在VS已經(jīng)不會(huì)報(bào)錯(cuò)了,運(yùn)行一下也可以正常工作。但仔細(xì)想想也很奇怪,為什么返回值類(lèi)型改成了ActionResult< Person >就不報(bào)錯(cuò)了呢?明明返回值類(lèi)型跟方法簽名還是不一致???
深入ActionResult< T >
接上面的問(wèn)題,讓我們看一下ActionResult的內(nèi)部:

看到這里就明白了原來(lái)ActionResult< T >里面內(nèi)置了2個(gè)implicit operator方法。implicit operator用于聲明隱式類(lèi)型轉(zhuǎn)換。
public static implicit operator ActionResult<TValue>(ActionResult result);
表示ActionResult類(lèi)型可以轉(zhuǎn)換為ActionResult< TValue >類(lèi)型。
public static implicit operator ActionResult<TValue>(TValue value)
表示TValue類(lèi)型可以轉(zhuǎn)換為ActionResult< TValue >類(lèi)型。
因?yàn)橛辛诉@2個(gè)方法,當(dāng)ActionResult或者TValue類(lèi)型往ActionResult< T >賦值的時(shí)候會(huì)進(jìn)行一次自動(dòng)的類(lèi)型轉(zhuǎn)換。所以VS這里不會(huì)報(bào)錯(cuò)。
總結(jié)
- 大部分時(shí)候Action的返回值可以使用ActionResult/IActionResult
- 設(shè)計(jì)restful api的時(shí)候可以直接使用POCO類(lèi)作為返回值
- 如果要設(shè)計(jì)既支持POCO類(lèi)返回值或者ActionResult類(lèi)為返回值的action可以使用ActionResult< T >作為返回值
- ActionResult< T >之所以能夠支持兩種類(lèi)型的返回值類(lèi)型,是因?yàn)槭褂昧薸mplicit operator內(nèi)置了2個(gè)隱式轉(zhuǎn)換的方法
到此這篇關(guān)于ASP.NET Core中的Action的返回值類(lèi)型實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)ASP.NET Core Action的返回值類(lèi)型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
ASP.NET 鏈接 Access 數(shù)據(jù)庫(kù)路徑問(wèn)題最終解決方案
ASP.NET 鏈接 Access 數(shù)據(jù)庫(kù)路徑問(wèn)題最終解決方案...2007-04-04
.Net Core簡(jiǎn)單使用Mvc內(nèi)置的Ioc(續(xù))
怎樣直接獲取Ioc中的實(shí)例對(duì)象,而不是以構(gòu)造函數(shù)的方式進(jìn)行獲取呢?這篇文章繼續(xù)為大家介紹.Net Core簡(jiǎn)單使用Mvc內(nèi)置的Ioc2018-03-03
URLRewriter最簡(jiǎn)單入門(mén)介紹 URLRewriter相關(guān)資源
配置好后,查看日志看到的狀態(tài)都是200,IIS直接認(rèn)為這個(gè)文件是存在的了, 而不是301,或302,這在某些情況下可能會(huì)不適用,比如:搜索引擎優(yōu)化時(shí)目錄或文件調(diào)整。2008-07-07
ASP.NET MVC重寫(xiě)RazorViewEngine實(shí)現(xiàn)多主題切換
這篇文章主要為大家詳細(xì)介紹了ASP.NET MVC重寫(xiě)RazorViewEngine實(shí)現(xiàn)多主題切換,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06
asp.net實(shí)現(xiàn)根據(jù)城市獲取天氣預(yù)報(bào)的方法
這篇文章主要介紹了asp.net實(shí)現(xiàn)根據(jù)城市獲取天氣預(yù)報(bào)的方法,涉及asp.net調(diào)用新浪接口獲取天氣預(yù)報(bào)信息的實(shí)現(xiàn)技巧,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下2015-12-12
C#默認(rèn)以管理員身份運(yùn)行程序?qū)崿F(xiàn)代碼
權(quán)限不夠,導(dǎo)致無(wú)法修改系統(tǒng)時(shí)間,于是我以管理員身份運(yùn)行了一次,結(jié)果測(cè)試成功,下面為大家介紹下C#如何默認(rèn)以管理員身份運(yùn)行程序2014-03-03

