Returning a 404 from an explicitly typed ASP.NET Core API controller (not IActionResult)

前端 未结 4 1842
春和景丽
春和景丽 2020-12-24 00:01

ASP.NET Core API controllers typically return explicit types (and do so by default if you create a new project), something like:

[Route(\"api/[controller]\")         


        
4条回答
  •  醉酒成梦
    2020-12-24 00:38

    You can actually use IActionResult or Task instead of Thing or Task or even Task>. If you have an API that returns JSON then you can simply do the following:

    [Route("api/[controller]")]
    public class ThingsController : Controller
    {
        // GET api/things
        [HttpGet]
        public async Task GetAsync()
        {
        }
    
        // GET api/things/5
        [HttpGet("{id}")]
        public async Task GetAsync(int id)
        {
            var thingFromDB = await GetThingFromDBAsync();
            if (thingFromDB == null)
                return NotFound();
    
            // Process thingFromDB, blah blah blah
            return Ok(thing); // This will be JSON by default
        }
    
        // POST api/things
        [HttpPost]
        public void Post([FromBody] Thing thing)
        {
        }
    }
    

    Update

    It seems as though the concern is that being explicit in the return of an API is somehow helpful, while it is possible to be explicit it is in fact not very useful. If you're writing unit tests that exercise the request / response pipeline you are typically going to verify the raw return (which would most likely be JSON, i.e.; a string in C#). You could simply take the returned string and convert it back to the strongly typed equivalent for comparisons using Assert.

    This seems to be the only shortcoming with using IActionResult or Task. If you really, really want to be explicit and still want to set the status code there are several ways to do this - but it is frowned upon as the framework already has a built-in mechanism for this, i.e.; using the IActionResult returning method wrappers in the Controller class. You could write some custom middleware to handle this however you'd like, however.

    Finally, I would like to point out that if an API call returns null according to W3 a status code of 204 is actually accurate. Why on earth would you want a 404?

    204

    The server has fulfilled the request but does not need to return an entity-body, and might want to return updated metainformation. The response MAY include new or updated metainformation in the form of entity-headers, which if present SHOULD be associated with the requested variant.

    If the client is a user agent, it SHOULD NOT change its document view from that which caused the request to be sent. This response is primarily intended to allow input for actions to take place without causing a change to the user agent's active document view, although any new or updated metainformation SHOULD be applied to the document currently in the user agent's active view.

    The 204 response MUST NOT include a message-body, and thus is always terminated by the first empty line after the header fields.

    I think the first sentence of the second paragraph says it best, "If the client is a user agent, it SHOULD NOT change its document view from that which caused the request to be sent". This is the case with an API. As compared to a 404:

    The server has not found anything matching the Request-URI. No indication is given of whether the condition is temporary or permanent. The 410 (Gone) status code SHOULD be used if the server knows, through some internally configurable mechanism, that an old resource is permanently unavailable and has no forwarding address. This status code is commonly used when the server does not wish to reveal exactly why the request has been refused, or when no other response is applicable.

    The primary difference being one is more applicable for an API and the other for the document view, i.e.; the page displayed.

提交回复
热议问题