Blazor Server应用点击下单按钮无法跳转至外部支付URL求助
问题解决:Blazor Server点击下单按钮在新标签页打开支付链接
核心问题分析
你的代码中页面刷新的根源是表单默认提交行为:点击type="submit"按钮会触发浏览器自带的表单提交,直接刷新页面,打断后续的JS跳转逻辑,即使ProcessCheckout方法被执行,页面刷新也会重置组件状态,导致OnAfterRenderAsync中的跳转代码无法生效。
最优解决方案
方案1:保留表单并阻止默认提交
修改表单的onsubmit事件,先阻止浏览器默认提交行为,再调用下单逻辑:
<form @onsubmit="async (e) => { e.PreventDefault(); await ProcessCheckout(); }"> <div> <h2>Checkout</h2> <button type="submit" class="btn btn-primary">Place Order</button> <a href="/cart" class="btn btn-secondary">Back to Shopping Bag</a> </div> </form>
方案2:移除表单,直接使用按钮点击事件
如果不需要表单的其他功能,直接用按钮的@onclick绑定方法,彻底避免表单提交问题:
<div> <h2>Checkout</h2> <button @onclick="ProcessCheckout" class="btn btn-primary">Place Order</button> <a href="/cart" class="btn btn-secondary">Back to Shopping Bag</a> </div>
调整后端逻辑
同时需要修正组件初始化逻辑,移除页面加载时自动调用ProcessCheckout的代码(否则页面一打开就会触发支付流程,不符合点击按钮下单的需求):
@code { private bool shouldRedirect; private string authorizationUrl; @inject IJSRuntime JS // 确保已注入IJSRuntime protected override async Task OnInitializedAsync() { // 移除自动调用,仅在点击按钮时触发下单 // await ProcessCheckout(); } private async Task ProcessCheckout() { try { var userId = await GetUserIdAsync(); var netTotal = await _cartService.GetBasketNetTotalAsync(userId); var authState = await _authStateProvider.GetAuthenticationStateAsync(); var user = authState.User; string strEmail = user.FindFirst(System.Security.Claims.ClaimTypes.Email)?.Value; string token = _configuration["PayStackSettings:PayStackSecretKey"]; var payStack = new PayStackApi(token); TransactionInitializeRequest request = new() { AmountInKobo = Convert.ToInt32(netTotal) * 100, Email = strEmail, Reference = Generate().ToString(), Currency = "GHS" }; var response = payStack.Transactions.Initialize(request); if (response.Status) { authorizationUrl = response.Data.AuthorizationUrl; shouldRedirect = true; StateHasChanged(); // 触发组件重新渲染,执行OnAfterRenderAsync } } catch (Exception ex) { throw new Exception(ex.Message); } } protected override async Task OnAfterRenderAsync(bool firstRender) { if (shouldRedirect) { shouldRedirect = false; // 重置标记,避免重复执行 await JS.InvokeVoidAsync("open", authorizationUrl, "_blank"); } } private async Task<string> GetUserIdAsync() { var authState = await _authStateProvider.GetAuthenticationStateAsync(); var user = authState.User; return user.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value; } private static int Generate() => new Random((int)DateTime.Now.Ticks).Next(100000000, 999999999); }
关键注意事项
- 确保组件已注入
IJSRuntime(代码中需添加@inject IJSRuntime JS) - 必须阻止表单默认提交或移除表单,否则页面刷新会破坏跳转逻辑
- 移除初始化时的自动下单调用,保证仅在用户点击按钮时触发流程
内容的提问来源于stack exchange,提问作者Somad
相关产品推荐
相关产品推荐

