Tim Barcz

Sponsors

The Lounge

Wicked Cool Jobs

Groups and Affiliations

Syndication

News

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
PRG Pattern in the ASP.NET MVC Framework

Have you ever been traveling through the "internets" and have been presented with the following?

As web developers we know what this means; a form was posted to the page and now you're trying to refresh that same page.  I'm not sure if there's been any significant usability study on the subject but I would imagine my Grandmother wouldn't know what to do here.  Enter the PRG pattern.

What is the PRG Pattern?

While the PRG pattern isn't knew, there isn't much out there on it for the .NET community.  PRG stands for "Post/Redirect/Get", I'll let Wikipedia explain the rest:

instead of returning an HTML page directly, the POST operation returns a redirection command (using the HTTP 303 response code (sometimes 302) together with the HTTP "Location" response header), instructing the browser to load a different page using an HTTP GET request. The result page can then safely be bookmarked or reloaded without unexpected side effects.

While this could be accomplished in webforms, it would be much more difficult since the postback model hangs on pages posting to themselves to implement button clicks and the like.  The MVC Framework on the other hand makes the implementation of the PRG pattern extremely easy. 

But How?  Can I See an Example?

I'm going to use an Login function as an example.  If the login attempt is successful, the user should be redirected to their account page, otherwise they should be redirected back to the login page.

We first will need two actions, one for displaying the login view and one for processing the login attempt, which I've provided below:

   1: /// <summary>
   2: /// Displays the login view (the form to enter credentials)
   3: /// </summary>
   4: public ActionResult Login()
   5: {
   6:     return View("Login");
   7: }
   8:  
   9: /// <summary>
  10: /// Handles form data from the login view, in other words, the form, which
  11: /// is on "login.aspx" has a form tag with it's action set to "ProcessLogin",
  12: /// the name of this method.
  13: /// </summary>
  14: public ActionResult ProcessLogin(string email, string password)
  15: {
  16:     IUser user = userRepository.GetByEmail(email);
  17:  
  18:     if (user != null && authenticator.VerifyAccount(user, password))
  19:     {
  20:         authenticator.SignIn(user);
  21:  
  22:         return RedirectToAction("Index", "Account");
  23:     }   
  24:     
  25:     //login failed
  26:     // add some message here in TempData to tell the user the login failed
  27:     return RedirectToAction("Login");
  28: }
Notice the different return types in the both of the methods.  Login() has one exit point, "return View("Login")"  and ProcessLogin has two exit points both of which use RedirectToAction() call, which instead returns an objected of RedirectToRouteResult, a subclass of ViewResult.  To properly perform PRG you must return a redirecting ViewResult from your action, such as RedirectToRouteResult, otherwise you'll get the dialog box pictured above.
 
Here is the login view (login.aspx).  The important part to pay attention to is the "action" attribute.
 
   1: <form name="loginActionForm" method="post" action="ProcessLogin" id="loginActionForm">
   2:    <fieldset class="login">
   3:        <legend>Login</legend>
   4:        <label for="email">Email</label>
   5:        <input type="textbox" id="lemail" name="email" maxlength="100" value="" class="required" />
   6:        <label for="password">Password</label>
   7:        <input type="password" id="lpassword" name="password" maxlength="256" class="required" />
   8:        
   9:        <input type="image" src="<%= AppHelper.ImageUrl("btn_go.gif") %>" class="submit" />
  10:        <div class="errorlist"></div>
  11:    </fieldset>
  12: </form>

By implementing the PRG pattern, I get nice clean urls that are bookmarkable.  My users also get a nice site that is traversable and aren't presented with confusing security dialog messages


Posted 08-22-2008 11:38 AM by Tim Barcz

[Advertisement]

Comments

sergiopereira wrote re: PRG Pattern in the ASP.NET MVC Framework
on 08-22-2008 1:36 PM

In the case of a login screen most of the times this is just an annoyance. Things can be worse in forms that persist or destroy data. Issuing a redirect after posted actions that modify data can avoid greater headaches like duplication.

Tim Barcz wrote re: PRG Pattern in the ASP.NET MVC Framework
on 08-22-2008 1:40 PM

@Sergio

As programmers I think we typically know whether it's safe to push that button or not.  Something still could go wrong by pushing the button again even if we think we know what we're doing.

How much more are non-programmers confused by the dialog?  What do they push?  What types of safeguards have to be programmed into a site to handle the very case where some submits twice.....The fix of PRG is an elegant and easy fix.

Lucas Goodwin wrote re: PRG Pattern in the ASP.NET MVC Framework
on 08-23-2008 10:59 AM

Funny, this exact scenario is why I abandoned WebForms in favor of ProMesh.NET (an open source .NET MVC, but basically similar to ASP.NET MVC).

Frankly this is an inexcusable oversight on MSes part when they designed WebForms.  There's no reason WebForms couldn't have baked this in to the framework for all postbacks in such a way as to be totally invisible to everyone.

I love the diagram btw.  Much easier then trying to explain this pattern verbally to my coworkers ;)

One other thing.  AJAX postbacks can be used to achieve this pattern as well.  But, ofcourse, people with JS turned off need a fallback solution.

ASP.NET MVC Archived Blog Posts, Page 1 wrote ASP.NET MVC Archived Blog Posts, Page 1
on 08-23-2008 11:03 AM

Pingback from  ASP.NET MVC Archived Blog Posts, Page 1

IHateSpaghetti {code} wrote RPG Pattern using ASP.NET MVC
on 08-24-2008 6:36 AM

Tim posted a great post and in that post he implements the PRG pattern (it&#39;s basically a way to overcome

Reflective Perspective - Chris Alcock » The Morning Brew #165 wrote Reflective Perspective - Chris Alcock &raquo; The Morning Brew #165
on 08-26-2008 2:35 AM

Pingback from  Reflective Perspective - Chris Alcock  &raquo; The Morning Brew #165

joshka wrote re: PRG Pattern in the ASP.NET MVC Framework
on 08-29-2008 8:14 AM
links for 2008-09-03 « Praveen’s Blog wrote links for 2008-09-03 &laquo; Praveen&#8217;s Blog
on 09-03-2008 12:38 PM

Pingback from  links for 2008-09-03 &laquo; Praveen&#8217;s Blog

Anders Liu wrote [翻译] ASP.NET MVC中的PRG模式
on 09-08-2008 12:22 AM

POST操作不是直接返回一个HTML页面,而是返回一个重定向命令(使用HTTP 303响应码(有时是302)以及HTTP的“Location”响应头),引导浏览器使用HTTP GET请求加载另一个页面。这个结果页可以安全地作为书签进行保存或重新加载,而不会带来非预期的副作用。

尘非尘 wrote 转:ASP.NET MVC 第五个预览版和表单提交场景
on 09-09-2008 3:38 AM

上个星期四,ASP.NETMVC开发团队发布了ASP.NETMVC框架的

ASP.NET Preview 5 y escenarios Form Post « Thinking in .NET wrote ASP.NET Preview 5 y escenarios Form Post &laquo; Thinking in .NET
on 09-12-2008 12:59 PM

Pingback from  ASP.NET Preview 5 y escenarios Form Post &laquo; Thinking in .NET

zhangh wrote ASP.NET MVC Preview 5 and Form Posting Scenarios
on 10-26-2008 2:35 AM

ThispastThursdaytheASP.NETMVCfeatureteampublishedanew

Daniel wrote re: PRG Pattern in the ASP.NET MVC Framework
on 12-07-2008 7:27 AM

thanks for nice post.

I have one question, if in case I need to display again the username or email address on the form, how to that?

菜 鸟2008 wrote ASP.NET MVC Preview 5 and Form Posting Scenarios
on 12-31-2008 5:47 AM
Sample Weblog wrote 14、ASP.NET MVC 第五个预览版和表单提交场景
on 02-18-2009 10:54 AM

【原文地址】 ASP.NET MVC Preview 5 and Form Posting Scenarios 【原文发表日期】 Tuesday, September 02, 2008 5:22 AM

Kazi Manzur Rashid's Blog wrote ASP.NET MVC Best Practices (Part 1)
on 04-01-2009 11:45 AM

In this post, I will share some of the best practices/guideline in developing ASP.NET MVC applications

Community Blogs wrote ASP.NET MVC Best Practices (Part 1)
on 04-01-2009 11:45 AM

In this post, I will share some of the best practices/guideline in developing ASP.NET MVC applications

Kazi Manzur Rashid's Blog wrote ASP.NET MVC Best Practices (Part 1)
on 04-01-2009 11:45 AM

In this post, I will share some of the best practices/guideline in developing ASP.NET MVC applications

Mickey Williams @ Neudesic wrote Avoiding Previous Page Issues
on 04-09-2009 3:45 PM

Surfacing a discussion that popped up on email recently... If you use HTTP-POST to send information from...

kenali dan kunjungi objek wisata di pandeglang wrote re: PRG Pattern in the ASP.NET MVC Framework
on 10-26-2009 7:03 AM

hell, this post is very useful for me. thanks.

I'm September wrote ASP.NET MVC 第五个预览版和表单提交场景
on 11-27-2009 11:04 PM

【原文地址】ASP.NETMVCPreview5andFormPostingScenarios【原文发表日期】Tuesday,September02,20085:22AM...

Fabrício Fujikawa wrote re: PRG Pattern in the ASP.NET MVC Framework
on 12-27-2009 6:40 AM

Simple, clear and effective. Great post! I'll try to apply the concept in my working systems!

Add a Comment

(required)  
(optional)
(required)  
Remember Me?

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)

CodeBetter.Com