开发者

ASP.NET MVC: Using GET and POST in the same method

Here's the scenario: when a new user registers to our web site, we want to send an email to verify that the user owns the email address. In the email there's a link to a page that will do the verification, something like this:

http://www.mysite.com/account/verify/token

The verify method looks like this:

[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Verify(Nullable<Guid> id)
{
    // tries to get the user based on the verification code
    if (ValidId(id))
    {
        // if the id is correct, update user data in the model and redirect
        return RedirectToAction("Index", "Dashboard");
    }
    else
    {
        // redirects the user to the verify view
        return View("Verify");
    }
}  

The "Verify" view is simply a textbox with a button, so the user can enter the verification code manually (the user can get to this page from the site, and might prefer just to copy-paste the code). When the user clicks on the button, I want to do the same thing that my GET method does; so I ended up with something like this:

[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
public ActionResult Verify(Nullable<Guid> id) { ... }

I have a couple of issues with this code (开发者_如何学编程which works, but...):

  • Is it OK to have a GET and POST method? Or is there a better way to handle this scenario?
  • I'm modifying data in a GET method (if the id is correct, I update the user data to reflect that it's verified) and that's a big NO NO ... still, I want the user to just be able to click on the link and verify the token. Is there a better way to achieve this?

Thanks


I personally wouldn't bother with the AcceptVerbs attribute. (** See note below) You could then combine this into one action, which could respond as needed. (Showing some untested code below.) The reason I'm adding an answer instead of just a comment is that I wanted to recommend you add one more branch to your logic, to handle a failed code (i.e., to present an error message).

public ActionResult Verify(Nullable<Guid> id)
{
    if (!id.HasValue)
    {
        // nothing was submitted
        ViewData["message"] = "Please enter your ID and press Submit";
        return View("Verify");
    }
    if (!ValidId(id))
    {
        // something was submitted, but wasn't valid
        ViewData["message"] = "ID is invalid or incomplete. Pleaes check your speeling";
        return View("Verify");
    }
    // must be valid
    return RedirectToAction("Index", "Dashboard");

}

You then of course could display <%=ViewData["message"]%> in your Verify view. This is of course just a simple example.

** OK, here is my note RE: not bothering with the AcceptVerbs attribute:
In your scenario you could also just choose to make your form's method GET instead of POST. Because you're already "taking action" and modifying state on the handy link your users click on, I wouldn't see any difference. I'm just mentioning this to be thorough even though I'd personally opt for my previous recommendation.

Good luck!


I'm modifying data in a GET method ... and that's a big NO NO

I wouldn't say it's always a big no no. HTTP says that the GET method "SHOULD" be "safe", that is it SHOULD have no effect other than information retrieval. In this case, I think it's reasonable to stretch the definition of "safe" to mean that it doesn't have any harmful side effects, and indeed the only possible side effect your verification link can have is a desirable one.

The other property that the GET method is supposed to have is idempotence: if the user clicks the verification link multiple times, it's the same as if they clicked it just once. Hopefully you have this property, since a verification link is generated with a single-use code.


I have to say it is rare to find somebody so concerned with using the proper HTTP verb. I don't believe the original intention of the HTTP spec was to confine all data editing submissions to POST and all retrievals to GET. I think what you're doing is just fine.


if you are worried about it then what is wrong with this?

        [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult Verify()
    {
        return View("Verify");
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Verify(Guid? id)
    {
        if (ValidId(id))
        {
            return RedirectToAction("Index", "Dashboard");
        }

        return View("Verify");
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜