zoukankan      html  css  js  c++  java
  • ASP.NET MVC 通过ActionFilterAttribute来实现防止重复提交

    实现思想:每个页面打开的时候会在页面的隐藏控件自动生成一个值并将这个值赋值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")

  • 相关阅读:
    Jerry入职SAP成都研究院14周年纪念日
    深入学习SAP UI5框架代码系列之七:控件数据绑定的三种模式
    深入学习SAP UI5框架代码系列之六:SAP UI5控件数据绑定的实现原理
    让电影票房飞一会儿,五一换个姿势重温经典
    云图说|ModelArts Pro,为企业级AI应用打造的专业开发套件
    抵制羊毛党,图计算“加持”互联网电商风控
    Faiss源码剖析:类结构分析
    一文带你了解华为云GaussDB的五大黑科技
    华为云云原生数据库GaussDB加速创新,企业核心数据上云信赖之选
    云图说|华为数据安全中心,助你保障云上数据安全!
  • 原文地址:https://www.cnblogs.com/Wtomato/p/7483754.html
Copyright © 2011-2022 走看看