SPA - 基于服务器端验证的操作确认
SPA - confirmation for an action based on server side validation
我正在寻找可重复使用的解决方案,以解决用户执行的某些操作在完成之前可能需要用户进一步确认的问题。
我正在使用 React 前端和 WebAPI 后端开发应用程序。
假设用户正在发起资金转账,假设我们无法在发起转账之前检查 his/her 账户客户端中的可用资金。当用户提交请求时(通过 HTTP POST),如果用户的帐户有足够的资金,请求应该正常完成,而如果资金不足并且用户在透支限额内,则应该提示用户使用透支并且只有当用户确认使用透支时,请求才会完成。
另一种情况是,假设用户想要删除其中一个收款人帐户(通过 HTTP DELETE)。当收款人账户没有定期付款设置时,删除应该正常完成。当存在经常性付款设置时,应进一步提示用户(检查经常性帐户只能在服务器端完成,并且仅在需要时才会完成(因此不能提前执行此操作并提供给客户端)。
我相信这在任何应用程序中都是常见的情况,但在互联网上找不到合理的解决方案。
提前致谢
与其说是场景不常见,不如说是你对它提出了一个奇怪的要求。在理想的设计中 - 您会要求客户 turn-on 透支功能,这可能是对 api/settings
端点的单独 API 调用。您将其与常规请求有效负载相结合,这会使事情稍微复杂一些。
您只需要足够详细的响应合同和处理这些情况的 front-end,仅此而已。
我在下面嘲笑过一个。
以下是您对转账案例的描述。您可以修改其中一些响应合同,使其更具描述性,这样您就可以处理更多的案例。
- 发起从客户端 (react-app) 到服务器的传输请求。通过传输详细信息。请注意,您将其标记为
DirectTry
.
DirectTry
由于帐户资金问题而失败/但您已验证您可以透支。我们将 guid 和交易信息、客户信息添加到字典中,以防客户想要验证透支。你可能也应该在这里过期。
- Return提示状态为react-app。您可以通过从服务器向客户端传递一条消息来扩展它
We need you to approve going into overdraft for this transaction
/ follow-up 状态是什么等等...我们还传输一个 guid,只是为了确保它实际上是同一台设备,将启用透支的相同交易请求。
- 在 react-app 一侧,您会看到提示状态,boot-up 通知组件说点击此处批准您的透支。
- 您点击批准,相同的 guid 被传递到带有不同 属性 包的服务器端,表明这现在也允许透支。
- 交易完成。
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) {...}
}
在你的 front-end 中是这样的...
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.
}
});
我正在寻找可重复使用的解决方案,以解决用户执行的某些操作在完成之前可能需要用户进一步确认的问题。
我正在使用 React 前端和 WebAPI 后端开发应用程序。
假设用户正在发起资金转账,假设我们无法在发起转账之前检查 his/her 账户客户端中的可用资金。当用户提交请求时(通过 HTTP POST),如果用户的帐户有足够的资金,请求应该正常完成,而如果资金不足并且用户在透支限额内,则应该提示用户使用透支并且只有当用户确认使用透支时,请求才会完成。
另一种情况是,假设用户想要删除其中一个收款人帐户(通过 HTTP DELETE)。当收款人账户没有定期付款设置时,删除应该正常完成。当存在经常性付款设置时,应进一步提示用户(检查经常性帐户只能在服务器端完成,并且仅在需要时才会完成(因此不能提前执行此操作并提供给客户端)。
我相信这在任何应用程序中都是常见的情况,但在互联网上找不到合理的解决方案。
提前致谢
与其说是场景不常见,不如说是你对它提出了一个奇怪的要求。在理想的设计中 - 您会要求客户 turn-on 透支功能,这可能是对 api/settings
端点的单独 API 调用。您将其与常规请求有效负载相结合,这会使事情稍微复杂一些。
您只需要足够详细的响应合同和处理这些情况的 front-end,仅此而已。
我在下面嘲笑过一个。
以下是您对转账案例的描述。您可以修改其中一些响应合同,使其更具描述性,这样您就可以处理更多的案例。
- 发起从客户端 (react-app) 到服务器的传输请求。通过传输详细信息。请注意,您将其标记为
DirectTry
. DirectTry
由于帐户资金问题而失败/但您已验证您可以透支。我们将 guid 和交易信息、客户信息添加到字典中,以防客户想要验证透支。你可能也应该在这里过期。- Return提示状态为react-app。您可以通过从服务器向客户端传递一条消息来扩展它
We need you to approve going into overdraft for this transaction
/ follow-up 状态是什么等等...我们还传输一个 guid,只是为了确保它实际上是同一台设备,将启用透支的相同交易请求。 - 在 react-app 一侧,您会看到提示状态,boot-up 通知组件说点击此处批准您的透支。
- 您点击批准,相同的 guid 被传递到带有不同 属性 包的服务器端,表明这现在也允许透支。
- 交易完成。
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) {...}
}
在你的 front-end 中是这样的...
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.
}
});