ASP.Net MVC中的PRG模式?

时间:2016-04-22 08:08:10

标签: asp.net asp.net-mvc post-redirect-get

我是ASP.Net MVC的新手。在PHP中,即使帖子请求无效,我也总是使用PRG模式。会话闪烁非常简单(也是用户友好的)。

然而,在ASP.Net MVC中,当请求无效时,我看不到一种简单的方法来执行PRG。我可以想到一些方法,但我不认为它们是好的做法,并且做了一些额外的不必要的工作。

此外,从我读过的几篇文章来看,当请求无效时,不建议使用PRG。如果这是一个不好的做法,那么处理不成功的帖子请求的更好方法是什么?没有PRG真的会更好吗?当用户尝试刷新页面时,我应该让讨厌的浏览器警告吗?

2 个答案:

答案 0 :(得分:0)

在Mvc中,按照以下方式处理您的帖子操作是正常的做法:

[HttpPost]
[ValidateAntiForgeryToken]
public virtual ActionResult LoginForm(LoginViewModel loginViewModel)
{
    if (!ModelState.IsValid) 
        return View("Login", loginViewModel);

    return Redirect("/");
}

如您所见,属性ModelState.IsValid将告诉您请求是否无效,因此,当Post请求包含错误时,您可以返回相同的视图并在ValidationSummary中显示错误消息。这是视图的代码:

@using (Html.BeginForm("LoginForm", "Account"}))
    {
        @Html.ValidationSummary() // THIS WILL SHOW THE ERROR MESSAGES
        @Html.AntiForgeryToken()
        @Html.TextBoxFor(x => x.Email)
        @Html.PasswordFor(x => x.Password)
        <button type="submit">Submit</button>
    }

答案 1 :(得分:0)

我们在asp.net mvc网络应用程序中使用PRG模式已有5年了。我们采用PRG的主要原因是支持浏览器导航(例如后退,前进)。我们的网络应用程序由客户使用,用于前台/后台操作。我们的典型网页流程从登录开始,然后通过许多列表/详细信息视图进行。我们还合并了部分视图,这些视图也有自己的视图模型。列表视图将具有用于导航的链接(GETS)。详细视图将具有用于导航的表单(POSTS)。

我们PRG的关键方面:

  1. 我们合并了视图模型,因此每个视图都有一个viewmodel(所有数据访问都在viewmodel中完成)。
  2. 每个viewmodel都有一个set()&amp; get()方法用于维护与最新视图实例关联的关键数据字段值。 set / get值保存在sessionstate中。
  3. set方法为每个需要设置的值都有一个参数。 get方法只是从viewmodel构造函数调用,以填充viewmodel的public&#34; key&#34;值。
  4. viewmodel还有一个公共的load()方法,可以获取其视图的所有必要数据。
  5. 我们的PRG模式概述:

    1. 在控制器中,我们为每个操作都有一个单独的GET方法和一个POST方法。 GET只显示一个视图; POST处理发布的数据。
    2. 对于列表(菜单)视图,控制器GET方法调用目标视图的设置(此处为&#39;项键值)方法,然后调用RedirectToAction到目标视图&#39; s控制器GET动作。
    3. 控制器GET方法将实例化viewmodel(从而导致获取设置值),调用其load方法,该方法使用set / get键值来获取数据,并返回view / viewmodel。
    4. 控制器POST方法将使viewmodel保存有效的发布数据,然后重定向到下一个所需页面(可能是上一个列表菜单) - 或者 - 如果数据无效则重新显示当前视图。
    5. 我没有记录我们实施的所有PRG流程,但上面是基本流程。
    6. 示例视图模式设置/获取方法

      private void GetKeys() {
        Hashtable viewModelKeys;
        if (SdsuSessionState.Exists("RosterDetail"))
        {
          viewModelKeys   = (Hashtable)SdsuSessionState.Get("RosterDetail");
          EventId         = (int)viewModelKeys["EventId"];
          SessionNo       = (int)viewModelKeys["SessionNo"];
          viewModelKeys   = null;
        }
      }
      public static void SetKeys(int eventId, int sessionNo) {
        Hashtable viewModelKeys = new Hashtable();
        viewModelKeys.Add("EventId",eventId);
        viewModelKeys.Add("SessionNo",sessionNo);
        SdsuSessionState.Set("RosterDetail",viewModelKeys);
        viewModelKeys = null;
      }
      

      样本控制器

      [AcceptVerbs("Get")]
      
      public ActionResult MenuLink(int eventId, int sessionNo, string submitButton) {
        if (submitButton == RosterMenu.Button.PrintPreview) {
          // P-R-G: set called viewmodel keys.
          RosterDetail.SetKeys(eventId,sessionNo);
          // Display page.
          return RedirectToAction("Detail","Roster");
        }
        if (submitButton == RosterMenu.Button.Export) { etc ...}
      }