首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ASP.Net核心有时动作控制器会被调用两次

ASP.Net核心有时动作控制器会被调用两次
EN

Stack Overflow用户
提问于 2017-05-15 21:53:29
回答 1查看 4K关注 0票数 1

我有一个应用程序是ASP.net的核心,并集成了处理支付的支付网关。在我的日志文件中,我可以看到支付控制器有时会执行两次。我根据接收请求的时间生成一个ID,这些ID有时相差1秒,有时完全相同。这导致只有在少数情况下才会对卡进行两次充电。我似乎想不出是什么触发了这一切。

下面是我使用的代码

用户填写申请表,并在pay按钮上单击I am using this code to spreedly

代码语言:javascript
复制
 $('#REG').click(function () {
            var options = {
                company_name: "abcd",
                sidebar_top_description: "Fees",
                sidebar_bottom_description: "Only Visa and Mastercard accepted",
                amount: "@string.Format("{0:c}",Convert.ToDecimal(Model.FeeOutstanding))"
            }
            document.getElementById('payment').value = 'App'
            SpreedlyExpress.init(environmentKey, options);
            SpreedlyExpress.openView();
            $('#spreedly-modal-overlay').css({ "position": "fixed", "z-index": "9999", "bottom": "0", "top": "0", "right": "0", "left": "0" });
        });

这将以弹出窗口的形式打开spreedly表单,用户在其中输入所有卡信息并单击pay按钮。它执行支付控制器

代码语言:javascript
复制
public async Task<IActionResult> Index(DynamicViewModel model)
{
    if (ModelState.IsValid)
    {
        try
        {
            if (TempData.ContainsKey("PaymentFlag") && !String.IsNullOrEmpty(TempData["PaymentFlag"].ToString()))
            {
                // Some code logic that calls few async methods
                //generate a id based on the time of current request
                "APP-" + DateTime.Now.ToString("yyyyMMddHmmss-") + model.UserID;

                // ... Other code here     
}

我生成的id被记录下来,我可以在日志文件中看到,它为ID为相同时间或相差1秒的客户运行了两次。我已经测试了双击场景,还放入了一些代码来防止双击。但是我仍然不能理解为什么有时会发生这种情况。这种情况并不常见。这就像100次支付中发生的1次一样。

我有一个action属性来处理重复的请求。在放入这段代码后,它确实停止了重复请求的数量,但并没有完全停止。在少数情况下,控制器如何被调用两次。

代码语言:javascript
复制
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class NoDuplicateRequestAttribute : ActionFilterAttribute
{
    public int DelayRequest = 10;
    // The Error Message that will be displayed in case of 
    // excessive Requests
    public string ErrorMessage = "Excessive Request Attempts Detected.";

    // This will store the URL to Redirect errors to
    public string RedirectURL;

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // Store our HttpContext (for easier reference and code brevity)
        var request = filterContext.HttpContext.Request;
        // Store our HttpContext.Cache (for easier reference and code brevity)
        var cache = filterContext.HttpContext.RequestServices.GetService<IMemoryCache>();

        // Grab the IP Address from the originating Request (example)
        var originationInfo = request.HttpContext.Connection.RemoteIpAddress.ToString() ?? request.HttpContext.Features.Get<IHttpConnectionFeature>()?.RemoteIpAddress.ToString();

        // Append the User Agent
        originationInfo += request.Headers["User-Agent"].ToString();

        // Now we just need the target URL Information
        var targetInfo = request.HttpContext.Request.GetDisplayUrl() + request.QueryString;

        // Generate a hash for your strings (appends each of the bytes of
        // the value into a single hashed string
        var hashValue = string.Join("", MD5.Create().ComputeHash(Encoding.ASCII.GetBytes(originationInfo + targetInfo)).Select(s => s.ToString("x2")));
        string cachedHash;
        // Checks if the hashed value is contained in the Cache (indicating a repeat request)
        if (cache.TryGetValue(hashValue,out cachedHash))
        {
            // Adds the Error Message to the Model and Redirect

        }
        else
        {
            // Adds an empty object to the cache using the hashValue
            // to a key (This sets the expiration that will determine
            // if the Request is valid or not)
            var opts = new MemoryCacheEntryOptions()
            {
                SlidingExpiration = TimeSpan.FromSeconds(DelayRequest)
            };
            cache.Set(hashValue,cachedHash,opts);
        }
        base.OnActionExecuting(filterContext);
    }
EN

回答 1

Stack Overflow用户

发布于 2017-05-17 09:01:24

这不是ASP.NET核心问题。我有99%的把握,实际上有多个请求来自客户端,而ASP.NET核心只是按照它的意图来处理它们。

您可以选择将guid或其他标识符放在页面上,并将其与请求一起发送。在您的控制器中,检查您的缓存或会话以查看该标识符是否已经存在。如果是,抛出一个异常,或者返回Ok(),或者记录发生的事件,或者在这种情况下做任何你想做的事情,但是不要向卡收费。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43981360

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档