.NET Core卡牌游戏视图不显示及404错误问题排查
问题原因与修复方案
1. 控制器名称配置错误
ASP.NET Core标签助手的asp-controller属性不需要加Controller后缀,你写的asp-controller="CardController"会被解析成寻找名为CardControllerController的控制器,自然找不到对应页面。
修复:
将所有asp-controller="CardController"改成asp-controller="Card",同时视图里的asp-controller="Game"也需要改成Card(因为PlayTurn方法属于CardController,不存在GameController)。
修正后的核心链接代码:
<a asp-controller="Card" asp-action="PlayTurn" class="card">
视图完整修正后的分支代码:
@if (TempData.Peek("CardName") != null) { <a asp-controller="Card" asp-action="PlayTurn" class="card"> <ul> <li>@TempData.Peek("CardName")</li> <li>@TempData.Peek("CardValue")</li> <li>@TempData.Peek("CardSuit")</li> </ul> </a> } else { <a asp-controller="Card" asp-action="PlayTurn" class="card"> </a> } <a asp-controller="Card" asp-action="PlayTurn" class="card"> </a>
2. 硬编码重定向路径存在风险
PlayTurn方法里用return Redirect("Card/Create");硬编码路径,一旦路由配置变更就会出错,不符合ASP.NET Core规范写法。
修复:
改用RedirectToAction方法,自动根据路由规则生成正确路径:
public IActionResult PlayTurn() { var card = CreateCard(); TempData["CardName"] = card.DisplayName; TempData["CardValue"] = card.Value; TempData["CardSuit"] = card.Suit.ToString(); return RedirectToAction("Create", "Card"); }
3. 随机数生成逻辑缺陷
静态方法CreateCard里每次都实例化Random,短时间内多次调用会因系统时钟种子重复,生成相同的随机值,导致卡牌不随机。
修复:
把Random实例声明为静态字段,确保整个应用生命周期内只用一个实例:
private static readonly Random _rnd = new Random(); public static Card CreateCard() { Card[] card1 = new Card[11]; Array suitvalues = Enum.GetValues(typeof(Suit)); Suit randomSuit = (Suit)suitvalues.GetValue(_rnd.Next(suitvalues.Length)); var i = _rnd.Next(card1.Length); var card = new Card() { Suit = randomSuit, Value = i, DisplayName = GetShortName(randomSuit.ToString()) }; return card; }
4. 确认TempData依赖配置
TempData默认依赖Session,需确保Program.cs/Startup.cs中已配置Session服务:
// Program.cs 示例代码 var builder = WebApplication.CreateBuilder(args); // 添加Session服务 builder.Services.AddSession(options => { options.IdleTimeout = TimeSpan.FromMinutes(30); options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; }); builder.Services.AddControllersWithViews(); var app = builder.Build(); // 启用Session中间件(需在UseRouting之后、UseEndpoints之前) app.UseSession(); app.UseRouting(); app.UseAuthorization(); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run();
额外优化建议
可以直接将Card对象序列化后存入TempData,避免拆分多个键值对,代码更简洁:
// 控制器代码 public IActionResult PlayTurn() { var card = CreateCard(); TempData["Card"] = JsonSerializer.Serialize(card); return RedirectToAction("Create", "Card"); }
<!-- 视图代码 --> @if (TempData.Peek("Card") != null) { var card = JsonSerializer.Deserialize<SnapCardGame.Models.Card>((string)TempData.Peek("Card")); <a asp-controller="Card" asp-action="PlayTurn" class="card"> <ul> <li>@card.DisplayName</li> <li>@card.Value</li> <li>@card.Suit</li> </ul> </a> }
内容的提问来源于stack exchange,提问作者Rob644
相关产品推荐
相关产品推荐

