分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 代码编程

ASP.NET MVC 通过ActionFilterAttribute来实现防止重复提交

发布时间:2023-09-06 01:09责任编辑:熊小新关键词:.NETMVC

实现思想:每个页面打开的时候会在页面的隐藏控件自动生成一个值并将这个值赋值session,当提交方法的时候会在过滤器的时候进行获取session和页面传值过来的隐藏控件的值进行比较,如果值相同的话,重写session值。否则的话给出提示。

ActionFilter:

using System;
using System.Web;
using System.Web.Mvc;
using EwayFramework.Utils.Token;

namespace EwayFramework.BaseController.Filter
{

???/// <summary>
???/// 防止重复提交
???/// </summary>
???[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
???public sealed class CurrentApproveActionFilterAttribute : ActionFilterAttribute
???{
???????/// <summary>
???????/// 审批页面的控制器+Action方法
???????/// </summary>
???????public string SessionMyToken { get; set; }
???????public string ID { get; set; }
???????public IPageTokenView PageTokenView { get; set; }

???????/// <summary>
???????/// Called when authorization is required.
???????/// </summary>
???????/// <param name="filterContext">The filter context.</param>
???????public override void OnActionExecuting(ActionExecutingContext filterContext)
???????{
???????????PageTokenView = new SessionPageTokenView(SessionMyToken + HttpContext.Current.Request.Params[ID]);
???????????if (filterContext == null)
???????????{
???????????????throw new ArgumentNullException("filterContext");
???????????}

???????????if (!PageTokenView.TokensMatch)
???????????{
???????????????filterContext.Result = new JsonResult
???????????????{
???????????????????Data = new { Result =false, Message = "该单子已在其它地方打开,请在最新打开的页面审批或者刷新该页面!" }
???????????????};
???????????}

???????}
???}
}

定义生成随机码的接口和实现:

1、IPageTokenView.cs

namespace EwayFramework.Utils.Token
{
??public interface IPageTokenView
???{
???????/// <summary>
???????/// Generates the page token.
???????/// </summary>
???????string GeneratePageToken();

???????/// <summary>
???????/// Gets the get last page token from Form
???????/// </summary>
???????string GetLastPageToken { get; }

???????/// <summary>
???????/// Gets a value indicating whether [tokens match].
???????/// </summary>
???????/// <value>
???????/// ??<c>true</c> if [tokens match]; otherwise, <c>false</c>.
???????/// </value>
???????bool TokensMatch { get; }
???}
}

2、PageTokenViewBase.cs

namespace EwayFramework.Utils.Token
{
???public abstract class PageTokenViewBase : IPageTokenView
???{
???????public static readonly string HiddenTokenName = "hiddenToken";
???????/// <summary>
???????/// Generates the page token.
???????/// </summary>
???????/// <returns></returns>
???????public abstract string GeneratePageToken();

???????/// <summary>
???????/// Gets the get last page token from Form
???????/// </summary>
???????public abstract string GetLastPageToken { get; }

???????/// <summary>
???????/// Gets a value indicating whether [tokens match].
???????/// </summary>
???????/// <value>
???????/// ??<c>true</c> if [tokens match]; otherwise, <c>false</c>.
???????/// </value>
???????public abstract bool TokensMatch { get; }

???}
}

3、SessionPageTokenView.cs

using System;
using System.Security.Cryptography;
using System.Text;
using System.Web;

namespace EwayFramework.Utils.Token
{
???public class SessionPageTokenView : PageTokenViewBase
???{
???????public string SessionMyToken { get; set; }

???????public SessionPageTokenView(string sessionmytoken)
???????{
???????????SessionMyToken = sessionmytoken;
???????}

???????#region PageTokenViewBase

???????/// <summary>
???????/// Generates the page token.
???????/// </summary>
???????/// <returns></returns>
???????public override string GeneratePageToken()
???????{
???????????if (HttpContext.Current.Session[SessionMyToken] != null)
???????????{
???????????????return HttpContext.Current.Session[SessionMyToken].ToString();
???????????}
???????????else
???????????{
???????????????var token = GenerateHashToken();
???????????????HttpContext.Current.Session[SessionMyToken] = token;
???????????????return token;
???????????}
???????}

???????/// <summary>
???????/// Gets the get last page token from Form
???????/// </summary>
???????public override string GetLastPageToken
???????{
???????????get { return HttpContext.Current.Request.Params[HiddenTokenName]; }
???????}

???????/// <summary>
???????/// Gets a value indicating whether [tokens match].
???????/// </summary>
???????/// <value>
???????/// ??<c>true</c> if [tokens match]; otherwise, <c>false</c>.
???????/// </value>
???????public override bool TokensMatch
???????{
???????????get
???????????{
???????????????string formToken = GetLastPageToken;
???????????????if (formToken != null)
???????????????{
???????????????????if (formToken.Equals(GeneratePageToken()))
???????????????????{
???????????????????????//Refresh token
???????????????????????HttpContext.Current.Session[SessionMyToken] = GenerateHashToken();
???????????????????????return true;
???????????????????}
???????????????}
???????????????return false;
???????????}
???????}

???????#endregion

???????#region Private Help Method

???????/// <summary>
???????/// Generates the hash token.
???????/// </summary>
???????/// <returns></returns>
???????private string GenerateHashToken()
???????{
???????????return Encrypt(
???????????????HttpContext.Current.Session.SessionID + DateTime.Now.Ticks.ToString());
???????}

???????#endregion

???????public static string Encrypt(string plaintext)
???????{
???????????string cl1 = plaintext;
???????????string pwd = string.Empty;
???????????MD5 md5 = MD5.Create();
???????????byte[] s = md5.ComputeHash(Encoding.Unicode.GetBytes(cl1));
???????????for (int i = 0; i < s.Length; i++)
???????????{
???????????????pwd = pwd + s[i].ToString("X");
???????????}
???????????return pwd;
???????}
???}
}

Htmlhelper:

using System;
using System.Web;
using System.Web.Mvc;

namespace EwayFramework.Utils.Token
{
???public static class HtmlTokenHelper
???{
???????/// <summary>
???????/// 自动生成隐藏控件
???????/// </summary>
???????/// <param name="htmlhelper"></param>
???????/// <param name="id">表单唯一标识ID</param>
???????/// <returns></returns>
???????public static MvcHtmlString GenerateVerficationToken(this HtmlHelper htmlhelper,dynamic id)
???????{
???????????string formValue = SessionPageTokenView.Encrypt(HttpContext.Current.Session.SessionID + DateTime.Now.Ticks.ToString());
???????????string sessionname = HttpContext.Current.Request.Path + htmlhelper.ViewData[id];
???????????HttpContext.Current.Session[sessionname] = formValue;
???????????string fieldName = PageTokenViewBase.HiddenTokenName;
???????????TagBuilder builder = new TagBuilder("input");
???????????builder.Attributes["type"] = "hidden";
???????????builder.Attributes["name"] = fieldName;
???????????builder.Attributes["value"] = formValue;
???????????return new MvcHtmlString(builder.ToString(TagRenderMode.SelfClosing));
???????}
???}
}

调用和实现:

控制器:

在对应的Action方法上加上下述:

SessionMyToken :触发该Action方法的页面路由

ID:该单子的唯一标识ID(Action方法的参数必须有对应的值)

  [CurrentApproveActionFilter(SessionMyToken = "/PPHVPM_SecondForecastBOM/SecondForecastBOMPending_P", ID = "MainId")]

页面:

参数值为:该页面的唯一标识的 ViewBag.MainId不为空

 @Html.GenerateVerficationToken("MainId")

ASP.NET MVC 通过ActionFilterAttribute来实现防止重复提交

原文地址:http://www.cnblogs.com/Wtomato/p/7483754.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved