dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.2k stars 9.94k forks source link

Better Support HTTP 303 Status Code #36172

Open johnpmcconnell opened 3 years ago

johnpmcconnell commented 3 years ago

Before you close this as a duplicate, read the post over. I'm aware of the previous request at #13359 but don't feel it adequately addresses the issue.

Motivation

303 needs to be more easily accessible because its intended use case is extremely common:

It is primarily used to allow the output of a POST action to redirect the user agent to a selected resource, since doing so provides the information corresponding to the POST response in a form that can be separately identified, bookmarked, and cached, independent of the original request.

From RFC 7231 Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content

This use case describes almost every endpoint that creates a new persistent resource in an HTML website: you create the resource and then send the user to the page displaying the new resource, typically with a URL containing a unique identifier generated during the request. In particular, the fact that 303 must change the method to a GET request is necessary for these use cases to avoid attempting to create or update the new resource. While 302 typically does replace the method in implementation, the standard does not specifically require it the way 303 does. This ambiguity is exactly what I wish to avoid; the client must not send another POST request to the new resource's location.

Actually, I wish to avoid 302 entirely because of this ambiguity. It is much better to use a redirect status code with explicit semantics regarding the method than one that lets the client decide what to do. Frameworks should not make it easier to use an ambiguous, less predictable web standard than to use the unambiguous replacements specifically created in response to the ambiguity.

MDN echoes this sentiment, suggesting 302 should only be used in response to GET requests:

Even if the specification requires the method (and the body) not to be altered when the redirection is performed, not all user-agents conform here - you can still find this type of bugged software out there. It is therefore recommended to set the 302 code only as a response for GET or HEAD methods and to use 307 Temporary Redirect instead, as the method change is explicitly prohibited in that case.

In the cases where you want the method used to be changed to GET, use 303 See Other instead. This is useful when you want to give a response to a PUT method that is not the uploaded resource but a confirmation message such as: 'you successfully uploaded XYZ'.

Status Quo

Currently, the only way to redirect using the 303 status code is to build up the response from scratch. For example, this code might appear in a class extending Controller:

string location = this.Url.Action("MyAction", new { resourceId = newId });
this.Response.Headers.Add(HeaderNames.Location, location);
return this.StatusCode(StatusCodes.Status303SeeOther);

This usage pattern is not even well documented.

Describe the solution you'd like

I'd much rather my code look more like this, similar to what's available for 301, 302, 307, and 308:

return this.RedirectRetrieveToAction("MyAction", new { resourceId = newId });

I'm not picky about the name. That's just a first stab at it, taken from the wording of RFC specification and the naming pattern already present on ControllerBase.

rafikiassumani-msft commented 3 years ago

Triage: We will re-evaluate during .NET7 planning.

ghost commented 1 year ago

Thanks for contacting us.

We're moving this issue to the .NET 8 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s). If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.