ASP.NET Core 8 MVC中asp-route-id传值为0引发空引用问题求助
问题描述
我正在开发ASP.NET Core 8 MVC项目,项目包含产品和客户两张数据表。当点击查看或编辑实体时,页面应加载对应的产品或客户信息,但出现了空引用异常。
经调试发现,调用详情视图时传递的ID值为0。明明系统能够正常获取并展示产品和客户列表,且我已经通过asp-route-id传递ID,请问这一问题的原因是什么?
相关代码
Dashboard.cshtml
<div class="row"> <h2>Products</h2> <table class="table table-striped"> <thead> <tr> <th scope="col">#</th> <th scope="col">Product Name</th> <th scope="col">Part Number</th> <th scope="col">UPC</th> <th scope="col">Price</th> <th scope="col">Actions</th> </tr> </thead> <tbody> @foreach(var product in @ViewBag.Products) { <tr> <td>@product.Id</td> <td>@product.ProductName</td> <td>@product.PartNumber</td> <td>@product.UPC</td> <td>$@product.Price</td> <td> <a class="btn btn-primary" asp-area="" asp-controller="Admin" asp-action="ViewProductDetails" asp-route-id="@product.Id">View</a> <a class="btn btn-primary" asp-area="" asp-controller="Admin" asp-action="UpdateProduct" asp-route-id="@product.Id">Update</a> </td> </tr> } </tbody> </table> </div> <div class="row"> <h2>Clients</h2> <table class="table table-striped"> <thead> <tr> <th scope="col">#</th> <th scope="col">Address</th> <th scope="col">Phone Number</th> <th scope="col">Actions</th> </tr> </thead> <tbody> @foreach(var client in @ViewBag.Clients) { <tr> <td>@client.Id</td> <td>@client.Address</td> <td>@client.PhoneNumber</td> <td> <a class="btn btn-primary" asp-area="" asp-controller="Admin" asp-action="ViewClientDetails" asp-route-id="@client.Id">View</a> <a class="btn btn-primary" asp-area="" asp-controller="Admin" asp-action="UpdateClient" asp-route-id="@client.Id">Update</a> </td> </tr> } </tbody> </table> </div>
AdminController
public async Task<IActionResult> Dashboard() { List<Client> clients = await _dbContext.Clients.OrderBy(client => client.Id).ToListAsync(); List<Product> products = await _dbContext.Products.OrderBy(products => products.Id).ToListAsync(); // Gets both Lists just fine and displays them ViewBag.Clients = clients; ViewBag.Products = products; return View(); } // Other code // These methods are doing the same behavior. int of either productId or clientId are 0 // It shouldn't be 0 public async Task<IActionResult> UpdateProduct(int productId) { Product prod = await _dbContext.Products.FirstOrDefaultAsync(product => product.Id == productId); return View(prod); } public async Task<IActionResult> ViewProductDetails(int productId) { Product prod = await _dbContext.Products.FirstOrDefaultAsync(product => product.Id == productId); return View(prod); } public async Task<IActionResult> UpdateClient(int clientId) { Client client = await _dbContext.Clients.FirstOrDefaultAsync(client => client.Id == clientId); return View(client); } public async Task<IActionResult> ViewClientDetails(int clientId) { Client client = await _dbContext.Clients.FindAsync(clientId); return View(client); }
原因及解决方法
核心问题是路由参数名称与控制器方法参数名称不匹配:
- 视图中通过
asp-route-id传递的参数名为id,但控制器方法接收的参数名是productId或clientId。ASP.NET Core的模型绑定无法自动匹配不同名称的参数,因此会给int类型的参数赋予默认值0,最终导致查询不到数据引发空引用异常。
有两种修复方式可选:
方式一:修改控制器参数名,匹配路由参数
将控制器方法的参数名改为id,和视图中传递的参数名保持一致:
public async Task<IActionResult> UpdateProduct(int id) { Product prod = await _dbContext.Products.FirstOrDefaultAsync(product => product.Id == id); return View(prod); } public async Task<IActionResult> ViewProductDetails(int id) { Product prod = await _dbContext.Products.FirstOrDefaultAsync(product => product.Id == id); return View(prod); } public async Task<IActionResult> UpdateClient(int id) { Client client = await _dbContext.Clients.FirstOrDefaultAsync(client => client.Id == id); return View(client); } public async Task<IActionResult> ViewClientDetails(int id) { Client client = await _dbContext.Clients.FindAsync(id); return View(client); }
方式二:修改视图路由参数名,匹配控制器参数
调整视图中asp-route-*的后缀,使其和控制器方法的参数名一致:
<!-- 产品操作链接修改后 --> <td> <a class="btn btn-primary" asp-area="" asp-controller="Admin" asp-action="ViewProductDetails" asp-route-productId="@product.Id">View</a> <a class="btn btn-primary" asp-area="" asp-controller="Admin" asp-action="UpdateProduct" asp-route-productId="@product.Id">Update</a> </td> <!-- 客户操作链接修改后 --> <td> <a class="btn btn-primary" asp-area="" asp-controller="Admin" asp-action="ViewClientDetails" asp-route-clientId="@client.Id">View</a> <a class="btn btn-primary" asp-area="" asp-controller="Admin" asp-action="UpdateClient" asp-route-clientId="@client.Id">Update</a> </td>
额外建议
为控制器参数添加[Required]特性,这样当参数未正确传递时,会直接返回400错误,避免默认值导致的隐性问题:
public async Task<IActionResult> UpdateProduct([Required] int productId) { // ... }
内容的提问来源于stack exchange,提问作者DonDavid12
相关产品推荐
相关产品推荐

