الگوی PRG در ASP.NET MVC
نویسنده: محسن اسماعیل پور
تاریخ: ۱۳۹۲/۰۳/۰۶ ۱۱:۰
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
دارید اطلاعات یک فرم داخل صفحه رو به سمت سرور میفرستید و پس از اتمام عملیات، صفحه دوباره نمایش داده میشه. در این حالت اگه دکمه F5 یا دکمه Refresh مرور گر رو بزنید، با این پنجره مواجه میشید که میگه دارید اطلاعات قبلی رو دوباره به سمت سرور میفرستید. بعضی وقتها کاربران به هر دلیل دوباره صفحه رو Refresh میکنند و با این پنجره روبرو میشن بدون اینکه بدونن جریان از چه قراره، دوباره اطلاعات رو به سمت سرور میفرستن و این کار باعث ثبت اطلاعات تکراری میشه. برای جلوگیری از این کار الگویی به نام Post/Redirect/Get هست که راه حلی رو برای اینکار پیشنهاد میده.
راه حل به این صورت هست که پس از پست شدن فرم به سمت سرور و انجام عملیات، بجای اینکه صفحه، دوباره با استفاده از متد GET به کاربر نشون داده بشه، کاربر Redirect بشه به صفحه. برای توضیح این مسئله به سراغ AccountController که بصورت پش فرض وقتی یک پروژه ASP.NET MVC رو از نوع Internet ایجاد میکنید، وجود داره.
[HttpGet]
[AllowAnonymous]
public ActionResult Register()
{
return View();
}[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// Attempt to register the user
try
{
WebSecurity.CreateUserAndAccount(model.UserName, model.Password);
WebSecurity.Login(model.UserName, model.Password);
ViewBag.Message = "Successfully Registered!";
// PRG has been maintained
return RedirectToAction("Index", "Home");
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
}
}
// If we got this far, something failed, redisplay form
return View(model);
}[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// Attempt to register the user
try
{
WebSecurity.CreateUserAndAccount(model.UserName, model.Password);
WebSecurity.Login(model.UserName, model.Password);
ViewBag.Message = "Successfully Registered!";
// PRG has been maintained
return RedirectToAction("Register");
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
}
}
// If we got this far, something failed, redisplay form
return View(model);
}using System.Web.Mvc;
namespace TestMvcPRG.Helper
{
public class Redirect303 : ActionResult
{
private string _url;
public Redirect303(string url)
{
_url = url;
}
public override void ExecuteResult(ControllerContext context)
{
context.HttpContext.Response.StatusCode = 303; // redirect using GET
context.HttpContext.Response.RedirectLocation = _url;
}
}
public abstract class BaseController : Controller
{
public Redirect303 Redirect303(string actionName)
{
return new Redirect303(Url.Action(actionName));
}
public Redirect303 Redirect303(string actionName, object routeValues)
{
return new Redirect303(Url.Action(actionName, routeValues));
}
public Redirect303 Redirect303(string actionName, string controllerName)
{
return new Redirect303(Url.Action(actionName, controllerName));
}
public Redirect303 Redirect303(string actionName, string controllerName, object routeValues)
{
return new Redirect303(Url.Action(actionName, controllerName, routeValues));
}
}
}using System.Web.Mvc;
using TestMvcRPG.Helper;
namespace TestMvcPRG.Controllers
{
public class HomeController : BaseController
{
[HttpGet]
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(string data)
{
if (ModelState.IsValid)
{
return Redirect303("Index"); // post-redirect-get
}
return View();
}
}
}