asp.net-core – 从显式类型的ASP.NET Core API控制器(不是IActionResult)返回4
|
ASP.NET Core API控制器通常返回显式类型(默认情况下,如果您创建一个新项目),例如: [Route("api/[controller]")]
public class ThingsController : Controller
{
// GET api/things
[HttpGet]
public async Task<IEnumerable<Thing>> GetAsync()
{
//...
}
// GET api/things/5
[HttpGet("{id}")]
public async Task<Thing> GetAsync(int id)
{
Thing thingFromDB = await GetThingFromDBAsync();
if(thingFromDB == null)
return null; // This returns HTTP 204
// Process thingFromDB,blah blah blah
return thing;
}
// POST api/things
[HttpPost]
public void Post([FromBody]Thing thing)
{
//..
}
//... and so on...
}
问题是返回null; – 它返回HTTP 204:成功,没有内容。 然后,许多客户端Javascript组件认为这是成功的,因此有如下代码: const response = await fetch('.../api/things/5',{method: 'GET' ...});
if(response.ok)
return await response.json(); // Error,no content!
在线搜索(例如this question和this answer)指向有用的返回NotFound();控制器的扩展方法,但所有这些都返回IActionResult,它与我的任务< Thing>不兼容。返回类型。该设计模式如下所示: // GET api/things/5
[HttpGet("{id}")]
public async Task<IActionResult> GetAsync(int id)
{
var thingFromDB = await GetThingFromDBAsync();
if (thingFromDB == null)
return NotFound();
// Process thingFromDB,blah blah blah
return Ok(thing);
}
这是有效的,但要使用它,GetAsync的返回类型必须更改为Task< IActionResult> – 显式输入丢失,并且控制器上的所有返回类型都必须改变(即根本不使用显式输入),或者存在混合,其中一些动作处理显式类型而其他动作处理。此外,单元测试现在需要对序列化做出假设,并在它们具有具体类型之前明确地反序列化IActionResult的内容。 有很多方法可以解决这个问题,但它似乎是一个容易设计出来的令人困惑的混搭,所以真正的问题是:ASP.NET核心设计师的正确方法是什么? 似乎可能的选择是: >根据预期的类型,有一个奇怪的(混乱的测试)显式类型和IActionResult混合。 这些都涉及妥协和重构,这些都会丢失一些东西,或者增加与MVC Core设计相悖的不必要的复杂性。哪个妥协是正确的,为什么? 解决方法这是 addressed in ASP.NET Core 2.1与ActionResult< T>:public ActionResult<Thing> Get(int id) {
Thing thing = GetThingFromDB();
if (thing == null)
return NotFound();
return thing;
}
甚至: public ActionResult<Thing> Get(int id) =>
GetThingFromDB() ?? NotFound();
一旦我实现了它,我会更详细地更新这个答案。 原始答案 在ASP.NET Web API 5中有一个HttpResponseException(正如Hackerman所指出的那样),但它已从Core中删除,并且没有中间件来处理它。 我认为这种变化是由于.NET Core – ASP.NET试图完成所有开箱即用的工作,ASP.NET Core只会执行你明确告诉它的事情(这是它为什么它如此快速和便携的重要部分) )。 我找不到一个现有的库,所以我自己写了。首先,我们需要一个自定义异常来检查: public class StatusCodeException : Exception
{
public StatusCodeException(HttpStatusCode statusCode)
{
StatusCode = statusCode;
}
public HttpStatusCode StatusCode { get; set; }
}
然后我们需要一个RequestDelegate处理程序来检查新的异常并将其转换为HTTP响应状态代码: public class StatusCodeExceptionHandler
{
private readonly RequestDelegate request;
public StatusCodeExceptionHandler(RequestDelegate pipeline)
{
this.request = pipeline;
}
public Task Invoke(HttpContext context) => this.InvokeAsync(context); // Stops VS from nagging about async method without ...Async suffix.
async Task InvokeAsync(HttpContext context)
{
try
{
await this.request(context);
}
catch (StatusCodeException exception)
{
context.Response.StatusCode = (int)exception.StatusCode;
context.Response.Headers.Clear();
}
}
}
然后我们在Startup.Infigure中注册这个中间件: public class Startup
{
...
public void Configure(IApplicationBuilder app)
{
...
app.UseMiddleware<StatusCodeExceptionHandler>();
最后,操作可以抛出HTTP状态代码异常,同时仍然返回一个显式类型,可以轻松地进行单元测试而无需从IActionResult转换: public Thing Get(int id) {
Thing thing = GetThingFromDB();
if (thing == null)
throw new StatusCodeException(HttpStatusCode.NotFound);
return thing;
}
这保留了返回值的显式类型,并允许轻松区分成功的空结果(返回null;)和错误,因为无法找到某些内容(我认为它就像抛出ArgumentOutOfRangeException)。 虽然这是问题的解决方案,但它仍然没有真正回答我的问题 – Web API的设计者构建了对显式类型的支持,期望它们将被使用,添加了返回null的特定处理;这样它会产生204而不是200,然后没有添加任何方式来处理404?添加如此基本的东西似乎需要付出很多努力。 (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net – 对象“aspnet_CheckSchemaVersion”,数据库“XX
- ASP.NET MVC 1是否与ASP.NET MVC 2兼容?
- asp.net-mvc-3 – 是否可以在Javascript文件中使用razor语法
- asp.net-mvc-4 – Can Castle Windsor可用于在ASP.NET MVC
- MVC ASP.NET – 手动授权某人并通过表单身份验证保留授权
- asp.net – 服务器端/客户端或两者用户输入验证
- ASP.NET MVC在javascript中使用ViewData
- asp.net – 使PDF显示内联而不是单独的Acrobat Reader窗口
- asp.net-mvc – 用于局部视图的ASP.NET MVC 3控制器操作
- 在ASP.NET/IIS的URL中使用冒号(:)
- StructureMap和ASP .Net Web API和.Net Framewor
- iis-7 – 本地语言的布尔值
- asp.net-mvc – Ajax.BeginForm,调用操作,返回JS
- asp.net-mvc – 保持viewdata在RedirectToAction
- asp.net-mvc – 如何使用actionresult返回视图和
- asp.net-mvc – 仅在MVC4 BundleConfig中缩小脚本
- ASP.NET和C#重定向
- asp.net – Internet Explorer 9中的URL查询字符
- asp.net – 此操作需要连接到“主”数据库
- asp.net-mvc – 在哪里可以找到一个简单的简单解
