You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

HttpPost方法无法读取TempData引发NullReferenceException与500错误求助

问题根因
  • 触发NullReferenceException的核心原因是TempData默认不支持直接存储自定义类这类复杂类型,如果你使用的是ASP.NET Core默认的Cookie式TempData提供器,存储非字符串类型时会序列化失败,Post请求读取TempData["cities"]时会得到null,强制类型转换后依然是空引用,遍历null对象直接抛出空引用异常,进而触发HTTP 500错误。
  • 你的代码未对转换后的城市列表做空校验,一旦获取失败直接遍历就会触发报错。
  • 原有Post方法末尾未匹配到城市时直接用传入的SelectedCity跳转,若对应Action不存在也会触发500错误。
修复方案

方案1:手动序列化/反序列化(无需修改全局配置,推荐)

用.NET自带的JSON序列化工具将复杂类型转成字符串再存入TempData,避免类型丢失问题:

1. 修改GET方法存值逻辑

// 引入命名空间
using System.Text.Json;

public IActionResult CitiesOnMap()
{
   List<City> cities = new List<City>();
   // 原有城市赋值逻辑保持不变
   cities.Add(new City { CityName = "Hatay", Latitude = 123, Longtitude = 435 });
   cities.Add(new City { CityName = "Konya", Latitude = 123, Longtitude = 435 });
   // ...其他城市添加逻辑不变
   
   // 序列化后存字符串到TempData
   TempData["cities"] = JsonSerializer.Serialize(cities);
   return View(); 
}

2. 修改视图读取逻辑

@using System.Text.Json
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
    ViewData["Title"] = "CitiesOnMap";
}


<div class="text-center pt-5">
    <h1 class="display-4 pb-2 ">LET'S SEE THE CITIES!</h1>
    <p class="pb-3">Now, Please Choose A City You Want to See on Map.</p>
    <h3> @TempData["SelectedMap"] </h3>

    <div class="text-center mx-auto pt-5">
        <form asp-action="CitiesOnMap" asp-controller="City" method="post">

            <div class="row">
                <div class="col-9 mx-auto">
                    <select id="drpEmpList" name="SelectedCity" class="form-control">
                        <option disabled selected hidden>Choose a City </option>
                        <!-- 反序列化后遍历 -->
                        @foreach (var name in JsonSerializer.Deserialize<List<MVC.Models.City>>(TempData["cities"].ToString()))
                        {
                            <option>@name.CityName </option>
                        }

                    </select>
                    @{ TempData.Keep("cities"); }
                    <input type="hidden" />

                </div>
            </div>
            <div class="row">
                <div class="col-md-12 pt-4">
                    
                    <input type="submit" name="btnSubmit" value="Let's See" class="btn btn-success btn-lg" />
                </div>
            </div>

        </form>
    </div>
</div>

3. 修改Post方法逻辑,增加空校验

[HttpPost]
public IActionResult CitiesOnMap(string SelectedCity)
{
    // 先判空,避免空引用错误
    if (TempData["cities"] == null || string.IsNullOrEmpty(SelectedCity))
    {
        return RedirectToAction("CitiesOnMap");
    }
    // 反序列化得到城市列表
    var cities = JsonSerializer.Deserialize<List<MVC.Models.City>>(TempData["cities"].ToString());
    foreach (var redirectedCity in cities)
     {
        Console.WriteLine("bumbum");
        // 增加忽略大小写匹配,避免大小写不一致匹配失败
         if (String.Equals(redirectedCity.CityName, SelectedCity, StringComparison.OrdinalIgnoreCase))
         {             
             // 选中的城市如果要存TempData,同样序列化后存储
             TempData["selectedCity"] = JsonSerializer.Serialize(redirectedCity);
             return RedirectToAction(redirectedCity.CityName , "City");
         }
     }    
    // 匹配失败跳回选择页,避免跳转到不存在的Action报错
    return RedirectToAction("CitiesOnMap");
}

方案2:全局配置Session式TempData(可选)

如果不想手动序列化,可修改全局配置让TempData支持复杂类型存储,在Program.cs中添加以下配置即可保留原有存值逻辑:

// 注册Session服务
builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromMinutes(20);
    options.Cookie.HttpOnly = true;
    options.Cookie.IsEssential = true;
});
// 指定TempData用Session存储
builder.Services.AddControllersWithViews().AddSessionStateTempDataProvider();

// 中间件配置顺序不能变,要放在UseRouting之前
app.UseSession();
app.UseRouting();

配置完成后依然要给Post方法增加空校验,避免异常抛出。

内容的提问来源于stack exchange,提问作者Mertcan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 09:54:03