【问题标题】:SPA - confirmation for an action based on server side validationSPA - 基于服务器端验证的操作确认
【发布时间】:2020-09-05 23:02:09
【问题描述】:

我正在寻找一种可重复使用的解决方案来解决用户执行的某些操作在完成之前可能需要用户进一步确认的问题。

我正在使用 React 前端和 WebAPI 后端开发应用程序。

假设用户正在发起资金转账,并假设在发起转账之前我们无法检查他/她的账户客户端中的可用资金。当用户提交请求时(通过 HTTP POST),如果用户的帐户有足够的资金,则请求应该正常完成,而如果资金不足并且用户在透支限制内,则应提示用户使用透支,并且仅当用户确认使用透支请求应该完成。

另一种情况是,假设用户想要删除一个收款人帐户(通过 HTTP DELETE)。当收款人帐户没有定期付款设置时,删除应该正常完成。当存在定期付款设置时,应进一步提示用户(检查定期帐户只能在服务器端完成,并且只会在需要时完成(因此提前这样做并且不能向客户端提供数据)。

我确信这是任何应用程序中的常见情况,但在互联网上找不到此问题的合理解决方案。

提前致谢

【问题讨论】:

    标签: rest architecture single-page-application software-design webapi


    【解决方案1】:

    场景并不常见 - 你对它提出了一个奇怪的要求。在理想的设计中 - 您会要求客户打开透支功能,这可能是对 api/settings 端点的单独 API 调用。您将其与常规请求有效负载相结合,这会使事情稍微复杂一些。

    您只需要足够详细的响应合同和处理这些情况的前端即可。

    我在下面嘲笑了一个。

    以下是您转移资金案例的说明。您可以修改其中一些响应合同,使其更具描述性,以便处理更多案例。

    1. 发起从客户端(react-app)到服务器的传输请求。通行证转让详情。请注意,您将其标记为DirectTry
    2. DirectTry 因账户资金问题而失败/但您确认您可以透支。我们将 guid 和交易信息、客户信息添加到字典中,以防客户想要验证透支。您可能也应该在这里过期。
    3. 向 react-app 返回提示状态。您可以通过从服务器传递到客户端 We need you to approve going into overdraft for this transaction 的消息来扩展它/后续状态是什么等......我们还传输一个 guid,只是为了确保它实际上是同一个设备,同一个事务请求将启用透支。
    4. 在 react-app 端,您会看到提示状态,启动一个通知组件,提示单击此处批准您的透支。
    5. 您单击批准,相同的 guid 以不同的属性包传递到服务器端,表明现在也允许透支。
    6. 交易成功。
    
    public enum State
    {
       // everything worked
       Done,
    
       // error - no retry needed.
       CriticalError,
    
       // additional prompt
       Prompt,
    }
    
    public class ServiceResult
    {
       // some state.
       public State State { get; set; }
    
       ... some other props...
    }
    
    
    
    /// Part of some api controller
    [Route("api/funds")]
    [HttpPost]
    public async Task<ServiceResult> TransferFunds(FundTransferPayload payload)
    {
       // ... do some ops.
       ValidationResult validationResult; = new ValidationResult();
       if (payload.OperationType == OperationType.DirectTry)
       {
           validationResult = new ValidationResult();
       }
       // pass the guid we returned to front-end back to service to make sure
       else if (payload.OperationType == OperationType.PromptProvided)
       {
          validationResult = ValidateOp(
               ValidationDictionary[payload.promptGuid],
               payload.customerId,
               payload.operationType,
               payload.operationId);
       }
    
       var transferResult = await SomeService.SomeOps(validationResult);
       if (transferResult.Succeeded) {...}
       else if (transferResult.NeedsOverdraft)
       {
          var someGuid = new Guid();
          ValidationDictionary.Add(new Key(someGuid), new Value(payload.customerId, 'overdraft', transferResult.operationId));
          return new ServiceResult() { State=Prompt, ...otherprops... };
       }
       else if (transferResult.Failed) {...}
    }
    
    

    在你的前端是这样的......

    
    axios.post('/api/funds', {
        operationType: 'DirectTry',
        ...some other props...
      })
      .then(function (response) {
        if (response.data.state === 'Prompt') {
          // save the guid or whatever token you're using - you'll call your API again with that.
          // change the UX with the prompt. Upon prompt, fire the request appropriately.
        }
      });
    
    

    【讨论】:

    • @kodebot - 你有机会考虑这个解决方案吗?
    • 感谢您的回答。我开发了一个与您的答案非常相似的框架。再次感谢。
    • @kodebot 很酷。你认为它符合绿色勾号的条件吗?
    • 确实如此:)
    猜你喜欢
    • 1970-01-01
    • 2013-01-10
    • 2017-02-07
    • 1970-01-01
    • 2022-10-07
    • 2019-05-19
    • 2022-06-16
    • 1970-01-01
    • 2016-06-25
    相关资源
    最近更新 更多