ASP.NET MVC4 PRG模式

2023-11-23 22:58
文章标签 模式 asp net mvc4 prg

本文主要是介绍ASP.NET MVC4 PRG模式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一. 传统的Asp.net页面问题

一个传统的Asp.net页面的请求会是这样的:
    HTTP GET 请求"Register.aspx"
    HTTP POST 请求 "Register.aspx"(点击按钮等触发服务器端事件)
    数据检验失败, 重新返回到"Register.aspx"
    在HTTP POST到"Register.aspx"
    数据创建成功, 重新返回到"Register.aspx",提示创建成功
 
看看好像没有什么问题呀, 但是如果在标记为红色的这步之后,你在浏览器上点击"刷新"按钮, 就会弹出下面的对话框。


 
这个对话框的意思是, 为了显示你点击"刷新"按钮的页面, 浏览器需要发送你上次提交的数据到服务器端, 之所以会这样的原因是浏览器记录的是上次你的Post请求, 所以你点击"刷新"按钮, 也是重复执行一次Post请求, 而用户其实是想得到初始的页面,也就是GET请求"Register.aspx"页面. 对于大多数不清楚原理的普通用户来说,这样的对话框会让用户会非常困扰.
 
web系统应当是以URL为标记的资源, 一个URL最好代表的一种资源. 当你收藏一个网页,分享一个网页给你朋友的时候, 你用的是网页的URL, 那是因为网页的URL就对应了你想分享的资源.
所以上面方式带来的另外一个问题就是, Get, POST, 以及POST成功后的页面实际上代表了3中不同的资源,但是这三种资源的URL是同一个URL.
 

二. Asp.net MVC中也存在同样的问题

假如我们在完成一个注册页面, Controller中的代码是这样的:
 

复制代码
 //// GET: /Home/
        [HttpGet]public ActionResult Register(){return View();}[HttpPost]public ActionResult Register(Models.RegisterModel registerModel){return View();}
复制代码

View中的代码是:

复制代码
@using(Html.BeginForm()){<fieldset><legend>Register</legend>@Html.ValidationSummary(true)<ol><li>@Html.LabelFor(m => m.NickName)@Html.TextBoxFor(m => m.NickName)@Html.ValidationMessageFor(m => m.NickName)</li><li>@Html.LabelFor(m => m.Email)@Html.TextBoxFor(m => m.Email)@Html.ValidationMessageFor(m => m.Email)</li></ol><input type="submit" value="Sumbit" /></fieldset>
}
复制代码

运行以后,当你提交表单的时候,你会发现出现了同样的问题.
 

三. 使用PRG模式

PRG模式是Post/Redirect/Get的简称.
当一个Post请求过来的时候, 服务端会处理Post请求后,再发送Redirect(HTTP 303状态码)到浏览器,浏览器之后再发送Get请求到其它页面.
这样做, 浏览器的上一个操作就总是Http Get操作, 而不是Post操作, 也就解决了刷新弹出框的问题.


 

四. PRG模式在MVC上的实现

针对上面的例子,我们的修改思路是:
创建3个不同的Action对应, Post请求到"RegisterProcess"之后,无论成功还是失败, 都会转换成Get请求, 成功转向"RegisterSuccess", 失败转向"Register"
 
 
修改之后的Controller代码如下:

复制代码
 //// GET: /Home/
        [HttpGet, ImportModelStateFromTempData]public ActionResult Register(){return View();}[HttpPost, ExportModelStateToTempData]public ActionResult RegisterProcess(Models.RegisterModel registerModel){if (ModelState.IsValid){return RedirectToAction("RegisterSuccess");}return RedirectToAction("Register");}[HttpGet]public ActionResult RegisterSuccess(){return View();}
复制代码

上面的ImportModelStateFromTempData和ExportModelStateToTempData是ActionFilter, 是为了解决Redirect不能保存Model的验证错误的问题.
实现的基本原理是通过ExportModelStateToTempData把Model的验证错误存放到TempData中, 通过ImportModelStateFromTempData从TempData中把验证错误导入.


View代码是:

复制代码
@using (Html.BeginForm("RegisterProcess", "Home"))
{<fieldset><legend>Register</legend>@Html.ValidationSummary(true)<ol><li>@Html.LabelFor(m => m.NickName)@Html.TextBoxFor(m => m.NickName)@Html.ValidationMessageFor(m => m.NickName)</li><li>@Html.LabelFor(m => m.Email)@Html.TextBoxFor(m => m.Email)@Html.ValidationMessageFor(m => m.Email)</li></ol><input type="submit" value="Sumbit" /></fieldset>
}
复制代码


ImportModelStateFromTempData和ExportModelStateToTempData的实现代码如下:

复制代码
 public abstract class ModelStateTempDataTransfer : ActionFilterAttribute{protected static readonly string Key = typeof(ModelStateTempDataTransfer).FullName;}public class ExportModelStateToTempData : ModelStateTempDataTransfer{public override void OnActionExecuted(ActionExecutedContext filterContext){//Only export when ModelState is not validif (!filterContext.Controller.ViewData.ModelState.IsValid){//Export if we are redirectingif ((filterContext.Result is RedirectResult) || (filterContext.Result is RedirectToRouteResult)){filterContext.Controller.TempData[Key] = filterContext.Controller.ViewData.ModelState;}}base.OnActionExecuted(filterContext);}}public class ImportModelStateFromTempData : ModelStateTempDataTransfer{public override void OnActionExecuted(ActionExecutedContext filterContext){var modelState = filterContext.Controller.TempData[Key] as ModelStateDictionary;if (modelState != null){//Only Import if we are viewingif (filterContext.Result is ViewResult){filterContext.Controller.ViewData.ModelState.Merge(modelState);}else{//Otherwise remove it.
                    filterContext.Controller.TempData.Remove(Key);}}base.OnActionExecuted(filterContext);}}
复制代码

这篇关于ASP.NET MVC4 PRG模式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/420821

相关文章

Linux系统配置NAT网络模式的详细步骤(附图文)

《Linux系统配置NAT网络模式的详细步骤(附图文)》本文详细指导如何在VMware环境下配置NAT网络模式,包括设置主机和虚拟机的IP地址、网关,以及针对Linux和Windows系统的具体步骤,... 目录一、配置NAT网络模式二、设置虚拟机交换机网关2.1 打开虚拟机2.2 管理员授权2.3 设置子

SpringBoot如何通过Map实现策略模式

《SpringBoot如何通过Map实现策略模式》策略模式是一种行为设计模式,它允许在运行时选择算法的行为,在Spring框架中,我们可以利用@Resource注解和Map集合来优雅地实现策略模式,这... 目录前言底层机制解析Spring的集合类型自动装配@Resource注解的行为实现原理使用直接使用M

C#原型模式之如何通过克隆对象来优化创建过程

《C#原型模式之如何通过克隆对象来优化创建过程》原型模式是一种创建型设计模式,通过克隆现有对象来创建新对象,避免重复的创建成本和复杂的初始化过程,它适用于对象创建过程复杂、需要大量相似对象或避免重复初... 目录什么是原型模式?原型模式的工作原理C#中如何实现原型模式?1. 定义原型接口2. 实现原型接口3

大数据spark3.5安装部署之local模式详解

《大数据spark3.5安装部署之local模式详解》本文介绍了如何在本地模式下安装和配置Spark,并展示了如何使用SparkShell进行基本的数据处理操作,同时,还介绍了如何通过Spark-su... 目录下载上传解压配置jdk解压配置环境变量启动查看交互操作命令行提交应用spark,一个数据处理框架

基于.NET编写工具类解决JSON乱码问题

《基于.NET编写工具类解决JSON乱码问题》在开发过程中,我们经常会遇到JSON数据处理的问题,尤其是在数据传输和解析过程中,很容易出现编码错误导致的乱码问题,下面我们就来编写一个.NET工具类来解... 目录问题背景核心原理工具类实现使用示例总结在开发过程中,我们经常会遇到jsON数据处理的问题,尤其是

Node.js net模块的使用示例

《Node.jsnet模块的使用示例》本文主要介绍了Node.jsnet模块的使用示例,net模块支持TCP通信,处理TCP连接和数据传输,具有一定的参考价值,感兴趣的可以了解一下... 目录简介引入 net 模块核心概念TCP (传输控制协议)Socket服务器TCP 服务器创建基本服务器服务器配置选项服

Java实现状态模式的示例代码

《Java实现状态模式的示例代码》状态模式是一种行为型设计模式,允许对象根据其内部状态改变行为,本文主要介绍了Java实现状态模式的示例代码,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来... 目录一、简介1、定义2、状态模式的结构二、Java实现案例1、电灯开关状态案例2、番茄工作法状态案例

.NET利用C#字节流动态操作Excel文件

《.NET利用C#字节流动态操作Excel文件》在.NET开发中,通过字节流动态操作Excel文件提供了一种高效且灵活的方式处理数据,本文将演示如何在.NET平台使用C#通过字节流创建,读取,编辑及保... 目录用C#创建并保存Excel工作簿为字节流用C#通过字节流直接读取Excel文件数据用C#通过字节

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n