views:

1987

answers:

5

For a POST method, the W3 specs say:

If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity which describes the status of the request and refers to the new resource, and a Location header (see Section 10.4).

http://www.ietf.org/internet-drafts/draft-ietf-httpbis-p2-semantics-05.txt (section 8.5)

The standard response actually seems to be to send a Redirect to the newly created resource.

I'm building my site with ASP.NET MVC, and tried to follow the spec, so created a ResourceCreatedResult class:

public class ResourceCreatedResult : ActionResult
{
    public string Location { get; set; }
    public override void ExecuteResult(ControllerContext context)
    {
        context.HttpContext.Response.Clear();
        context.HttpContext.Response.StatusCode = 201;
        context.HttpContext.Response.ClearHeaders();
        context.HttpContext.Response.AddHeader("Location", Location);
    }
}

And my action looks something like this:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CreateNew(string entityStuff)
{
    Entity newEntity = new Entity(entityStuff);
    IEntityRepository entityRepository = ObjectFactory.GetInstance<IEntityRepository>();
    entityRepository.Add(newEntity);

    ActionResult result = new ResourceCreatedResult()
        { Location = Url.Action("Show", new { id = newEntity.Id }) };
    return result;
}

However, IE, Firefox and Chrome all fail to redirect to the new resource. Have I messed up generating the correct response, or do web browsers not expect this type of response, instead relying on servers to send a Redirect response?

+2  A: 

Redirect after post or post/redirect/get is something your application must do to be user friendly.

Edit. This is above and beyond the HTTP specifications. If we simply return a 201 after a POST, the browser back button behaves badly.

Note that Web Services requests (which do NOT respond to a browser) follow the standard completely and do NOT redirect after post.

It works like this.

  1. The browser POSTS the data.

  2. Your application validates the data. If it's invalid, you respond with the form so they can fix it and POST.

  3. Your application responds with a redirect.

  4. The browser gets the redirect and does a GET.

  5. Your application sees the GET and responds.

Now -- hey presto! -- the back button works.

S.Lott
This doesn't answer the question. I understand this mechanism, I'm wondering why it is fundamentally different to the HTTP specs?
Giraffe
Since your code doesn't show redirect-after-post, it appeared as though you didn't realize that your application had to do this. "IE, Firefox and Chrome all fail to redirect to the new resource" indicates that you're not doing the redirect in your application.
S.Lott
If you're saying that the correct browser reaction to a 201 response is not to try and GET the url given back in the Location header, and that the server should send a redirect instead of a 201, then it does answer the question in part, but the specs don't suggest that 3xx are valid responses.
Giraffe
Okay, makes more sense with edit.
Giraffe
@Giraffe: the specs don't suggest that 3xx are valid responses. Correct. It's a usability thing that's above and beyond the standard.
S.Lott
+1  A: 

As stated in the spec the response SHOULD be a HTTP 201 with redirect. So it isn't mandatory for a browser vendor to implement the correct answer...

You should try to change to a 30x code to see if it is correctly redirected. If so, it's a browser problem, else it may come from your code (I don't know anything in ASP.NET so I can't "validate" your code)

Pierre-Yves Gillier
+2  A: 

To be explicit, browsers (including modern browsers like Firefox 3 and IE8) do not "take the hint" and follow up an HTTP 201: Created response with a GET request to the URI supplied in the Location header.

If you want browsers to go to the URI supplied in the Location header, you should send an HTTP 303: See Other status instead.

dthrasher
A: 

My solution is to respond with a '201 Created' containing a simple page with a link to the new resource, and a javascript redirect using location.replace().

This lets the same code work for API and browser requests, plays nicely with Back and Refresh buttons, and degrades gracefully in old browsers.

g.inozemtsev
A: 

Shouldn't that only count for when something is "Created" and therefore a simple redirect to action should be genuinely sufficient?

Hurricanepkt