У нас есть приложение ASP.NET MVC 5, которое загружает представление MVC: Purchase.cshtml
. В этом представлении загружается iframe в DIV для стороннего процессора кредитных карт: пользователь вводит данные своей кредитной карты в iframe и нажимает кнопку «PAY». Когда закончите,
- Обработчик кредитной карты вызывает метод Web API,
api/callback
, чтобы сообщить нам, что платеж был успешным в течение нескольких секунд после нажатия пользователем кнопки «PAY». Здесь мы регистрируем платеж в нашей системе и используем объект Progress
, чтобы уведомить пользователя о ходе этого процесса.
- Кроме того, iframe процессора кредитных карт перенаправляет на одну из наших страниц MVC -
Receipt.cshtml
. Мы используем немного JavaScript, чтобы вырваться из iframe при загрузке страницы. Здесь мы все еще находимся в том же сеансе MVC, потому что мы никогда не покидали наш сайт.
Контроллер веб-API вызывается сторонней компанией, но у него будет имя пользователя, который инициировал вызов (который мы храним в приватном поле _userEmail
). В методе api/callback
здесь мы используем это для отслеживания прогресса:
var progress = new Progress<IPaymentProgress>();
progress.ProgressChanged += OnPaymentProgressChanged;
И эти обработчики:
private async void OnPaymentProgressChanged(object obj, IPaymentProgress e)
{
await NotifyClientPaymentProgressChanged(e);
}
private async Task NotifyClientPaymentProgressChanged(IPaymentProgress progress)
{
var context = Microsoft.AspNet.SignalR
.GlobalHost.ConnectionManager.GetHubContext<PurchaseHub>();
await context.Clients.User(_userEmail).handlePaymentProgressUpdate(progress);
}
В Receipt.cshtml
у нас есть этот JavaScript:
$(function () {
// If page is in iframe, exit it and display fullscreen.
if (self !== top) {
top.location.replace(self.location.href);
}
$("#progressModal").modal("show");
var purchaseHubProxy = $.connection.purchaseHub;
purchaseHubProxy.client.handlePaymentProgressUpdate = function (progress) {
console.log(progress);
$('.progress-bar').css("width", progress.Percentage + "%");
$("#progressMessage").text(progress.Message);
};
// Start the connection to get events
$.connection.hub.start().done(function () {
console.log("SignalR connected");
});
});
Приведенный выше console.log
выдает оператор SignalR connected
через несколько секунд. Однако мы больше ничего не получаем.
Возможно ли, чтобы метод веб-API, запускаемый сторонним приложением, связывался с нашей страницей MVC через SignalR? Имеем ли мы дело с двумя отключенными сеансами между ними - Web API и MVC - и мы не можем отправить SignalR между ними? Если нет, каков наилучший способ показать прогресс в представлении после запуска метода обработки внешних кредитных карт компанией-веб-API?
Примечание. Мы использовали этот же код для успешного общения через SignalR на страницах MVC. Тем не менее, мы никогда не пытались сделать это от Web API до MVC.
Обновление : найдено решение, позволяющее полностью избежать этой головной боли: сторонний процессор cc-1 сначала вызывает наш метод веб-API , а затем перенаправляет iframe в наш метод MVC для загрузки представления ( это не асинхронный, а синхронизация). Поэтому в веб-API мы напишем в нашу базу данных запись об успешном платеже. Затем в методе MVC мы проверим это; если он есть, мы будем обновлять индикатор выполнения через SignalR, что должно быть очень просто.