Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the PRG pattern incompatible with AJAX form posts?

I am using the post-redirect-get pattern for all my forms, but now need to add AJAX functionality to improve the user experience. My initial thoughts are that the two do not mix.

In the PRG scenario, I would have my post action that would then either redirect back to my get action if there is a validation error, or redirect to my success get action otherwise.

In the AJAX scenario, I need to return a partial view either way. More typically, I would check to see if it is an AJAX request first. If so, return the partial view, else return the view.

Any thoughts or suggestions?

like image 374
Paul Hiles Avatar asked Jul 31 '10 15:07

Paul Hiles


2 Answers

We use Post-Redirect-Get in our app. Here's the essence of what we do, which hinges around the Request.IsAjaxRequest() method and splitting your views into .aspx each of which host an .ascx so that each can action can be called both synchronously and asynchronously (i.e. via Ajax).

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Foo foo)
{
    try
    {
        // Save the changes to the data store
        unitOfWork.Foos.Attach(foo);
        unitOfWork.Commit();

        if (Request.IsAjaxRequest())
        {
            // The name of the view for Ajax calls will most likely be different to the normal view name 
            return PartialView("EditSuccessAsync");
        }
        else
        {
            return RedirectToAction("EditSuccess");
        }
    }
    catch (Exception e)
    {
        if (Request.IsAjaxRequest())
        {
            // Here you probably want to return part of the normal Edit View
            return PartialView("EditForm", foo);
        }
        else
        {
            return View(foo);
        }
    }
}

We have a slight variant on this as well where we specifically catch RulesException's (from the xVal in order to treat model validation errors differently to other 'more serious' exceptions.

catch (RulesException re)
{
    re.AddModelStateErrors(ModelState, "");

    return View(foo);
}

Saying all that though, sometimes I get a sneaking suspicion that we might be doing it slightly wrong.

like image 118
Phil Peace Avatar answered Sep 25 '22 23:09

Phil Peace


Well, part of the reason for PRG is to avoid the "Do you want to resubmit the form?" dialog. AJAX typically doesn't have this problem, since you aren't really doing a 'POST' (you are, but you catch my drift).

Anyways, Rails supports what you'd want to do, and I don't think it would be that rough translating it to ASP.NET MVC.

First, you can tell your client side JavaScript to send AJAX as text/javascript. Using jQuery:

jQuery.ajaxSetup({
    'beforeSend': function(xhr) { xhr.setRequestHeader("Accept", "text/javascript"); }
});

Put that somewhere before the AJAX is run. This will affect all other AJAX calls, but shouldn't do anything unintended unless you're looking for it on the backend.

Then, in your controller, look for the text/javascript header and respond accordingly. Check out this SO question, which references this article. Wish I could give more info, but I don't have VS handy to try it out right now.

like image 34
swilliams Avatar answered Sep 23 '22 23:09

swilliams