asp.net-core – 从显式类型的ASP.NET Core API控制器(不是IActi
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-mvc – 当前上下文错误中不存在名称“Url”
- asp.net mvc partialview @ Ajax.ActionLink不起作用
- asp.net-mvc-3 – 在MVC 3视图模型上使用Editable属性
- .NET Core技术研究-最实用最常用的配置读取方式
- asp.net – 证明telerik报告的HtmlTextBox中的文本
- asp.net-core – Asp.net Core中的Web应用程序与Web Api项目
- asp.net mvc和sql查询
- 实现对Asp.NetMvc及Asp.NetCore的权限控制
- asp.net – IIS Express全能子域名网址
- asp.net-mvc – Asp.net Mvc:Ninject – IPrincipal
- ASP.NET存储SQL中的图像并检索Asp:Image
- asp.net – 在IIS7上为WordPress重写URL
- asp.net-mvc – 自动发布使用TFS和MSBuild构建,无
- asp.net – IIS 7.5 Web应用程序首先请求应用程序
- asp.net – 为什么当StateProvider不是InProc时,
- asp.net-core-mvc – 如何创建从HttpContext.Tra
- 如何阻止ASP.Net发送默认字符集?
- asp.net-mvc – 我可以在_Layout.cshtml中有条件
- asp.net-mvc – ASP.NET MVC – 在哪里抛出异常?
- asp.net – 是否可以通过Windows服务中的自托管W