Spotted
Spotted

Reputation: 4091

Action called from both the same and other controller via RedirectToAction()

I'm integrating an online payment platform inside a currently existing eCommerce platform. This is a B2B platform and customers may pay beforehand (using the aforementionned online payment plaform) or place their orders and are billed at the end of the month.

The following action is located in OrdersController and contains the logic that is triggered once the customer want to confirm its order:

[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 });
}

The PaymentsController is responsible for redirecting to the Confirm action if the payment has been successful on the remote payment platform:

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 });
    }
}

So ultimately, both "flows" end in the action below which finally confirms the order and redirect to display its confirmation:

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

My worry about the action above is twofold:

Ideally I'd like to do something like adding attributes [HttpPost] and [ValidateAntiForgeryToken] to this action but then it becomes impossible to do a redirect to it. How can I solve this problem ? Is my design flawed and needs a refactor ?

Upvotes: 0

Views: 34

Answers (1)

ADyson
ADyson

Reputation: 61925

I suggest moving the actual task of confirming the order outside the "confirm" action. That action should simply be for displaying some UI in response to a successful confirmation.

Instead put the logic in some other class which you can call from the other flows directly. Once those flows know that confirmation has been recorded in the database they can redirect to the "confirm" action just to display a message to the user.

And that way if someone decides to visit the "confirm" URL manually then it will just display an incorrect message to them, but won't actually do anything harmful.

Upvotes: 1

Related Questions