通过RedirectToAction()从同一控制器和其他控制器调用的操作

时间:2019-02-27 10:03:43

标签: c# asp.net-mvc

我正在将在线支付平台集成到当前现有的电子商务平台中。这是一个B2B平台,客户可以预先付款(使用上述的在线付款平台)下订单,并在月底结算。

以下操作位于OrdersController中,其中包含一旦客户希望确认其订单便触发的逻辑:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Resume(ResumeViewModel viewModel)
{
    if (!_orderService.CanConfirmOrder(UserId, viewModel.TemporaryOrderId))
    {
        return Resume(viewModel.TemporaryOrderId, _settingsRepository.OrderTooLateMessage());
    }

    if (_customerService.MustPayDirectly(PaniproId))
    {
        return RedirectToAction("Initialize", "Payments", new { orderId = viewModel.TemporaryOrderId, amount = viewModel.OrderViewModel.Total });
    }

    return RedirectToAction("Confirm", new { id = viewModel.TemporaryOrderId });
}

如果在远程付款平台上付款成功,则PaymentsController负责重定向到Confirm操作:

public ActionResult Finalize(int orderId)
{
    var finalizeResult = _saferpay.FinalizeTransaction((string)_tokens[orderId.ToString()]);
    if (finalizeResult.IsSuccess)
    {
        return RedirectToAction("Confirm", "Orders", new { id = orderId });
    }
    else
    {
        LogTools.AddLog(finalizeResult.Error.ToString());
        return RedirectToAction("Resume", "Orders", new { id = orderId, errorMessage = finalizeResult.Error.Description });
    }
}

因此,最终,两个“流程”都以下面的操作结束,该操作最终确认了订单并重定向以显示其确认:

public ActionResult Confirm(int id)
{
    return HandleResult(_orderService.ConfirmOrder(UserId, id), order => RedirectToAction("Confirmation", new { id = order.ID }));
}

我对上述操作的担心是双重的:

  • 我正在修改GET操作中的状态,该操作应该是无状态操作
  • 手动调用URL / Orders / Confirm / {id}将绕过付款,这对企业来说也是一件很糟糕的事情

理想情况下,我想执行一些操作,例如向此操作中添加属性[HttpPost][ValidateAntiForgeryToken],但随后无法重定向到该操作。我怎么解决这个问题 ?我的设计有缺陷并且需要重构吗?

1 个答案:

答案 0 :(得分:1)

我建议将确认订单的实际任务移到“确认”操作之外。该操作应仅用于显示一些UI以响应成功的确认。

而是将逻辑放在其他一些类中,您可以直接从其他流中调用该逻辑。一旦这些流程知道确认已记录在数据库中,便可以将其重定向到“确认”操作,仅向用户显示一条消息。

那样,如果有人决定手动访问“确认” URL,那么它只会向他们显示错误消息,但实际上不会做任何有害的事情。