首页 > 解决方案 > 使用 TemData.Keep() 时的 Asp.net 核心 HTTP 500 错误

问题描述

城市控制器

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using MVC.Models;

namespace MVC.Controllers
{
    public class CityController : Controller
    {
        private readonly ILogger<CityController> _logger;

        public CityController(ILogger<CityController> logger)
        {
            _logger = logger;
        }

        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 });
           cities.Add(new City { CityName = "Istanbul", Latitude = 123, Longtitude = 435 });
           cities.Add(new City { CityName = "Izmir", Latitude = 123, Longtitude = 435 });
           cities.Add(new City { CityName = "Samsun", Latitude = 123, Longtitude = 435 });
           cities.Add(new City { CityName = "Antalya", Latitude = 123, Longtitude = 435 });
           cities.Add(new City { CityName = "Bursa", Latitude = 123, Longtitude = 435 });
           cities.Add(new City { CityName = "Manisa", Latitude = 123, Longtitude = 435 });
           cities.Add(new City { CityName = "Mersin", Latitude = 123, Longtitude = 435 });
           cities.Add(new City { CityName = "Ankara", Latitude = 123, Longtitude = 435 });
  
           TempData["cities"] = cities;
           return View(); 
        }

       
        [HttpPost]
        public IActionResult CitiesOnMap(string SelectedCity)
        {

            if (TempData["cities"] != null)
            {
                foreach (var redirectedCity in TempData["cities"] as List<City>)
                {
                    
                    if (String.Equals(redirectedCity.CityName, SelectedCity))
                    {

                        TempData["selectedCity"] = redirectedCity;
                        return RedirectToAction(redirectedCity.CityName, "City");
                    }


                }
            }


            return RedirectToAction(SelectedCity, "City"); ;
        }




        public IActionResult Hatay()
        {
            return View();
        }



        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}

在我的索引页面中,有一个下拉菜单可以选择地图。用户选择一张地图并单击按钮,然后我使用 RedirectToAction 使用此 CityController 重定向 CitiesOnMap.cshtml。

CitiesOnMap.cshtml

@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 TempData["cities"] as List<MVC.Models.City>)
                        {

                            <option>@name.CityName </option>
                        }
                        
                    </select>
                    

                    <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>


我正在发送城市列表,这是我的城市模型的类。在此页面上,用户从 CitiesOnMap.cshtml 文件的下拉列表中选择一个城市。选择后,我想将用户重定向到正确的城市页面。但是当用户选择提交按钮时,如果我不使用 TempData["cities"].Keep() 方法,.net 会抛出 NullReferenceError,因为据我所知,在使用它后我无法再次保留我的数据。如果我使用 TempData["cities"].Keep() 方法,我会收到 HTTP 500 错误。而且我认为我必须序列化我的 TempData["cities"] 但我很困惑我有很多问题:(请帮助我

标签: c#asp.net-coreasp.net-core-mvc

解决方案


首先,您的代码犯了一个错误,即您无法将 TempData["KeyName"] 重定向传递给另一个控制器操作。否则它将返回 500 错误并显示以下错误消息。那是因为TempDatauses Session,它本身使用IDistributedCacheIDistributedCache没有能力接受对象或序列化对象:

InvalidOperationException: The 'Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.TempDataSerializer' cannot serialize an object of type ....

这是一个使用 JSON.Net 的工作演示(您也可以使用 System.Text.Json):

public IActionResult CitiesOnMap()
{

    List<City> cities = new List<City>();
    //....
    cities.Add(new City { CityName = "Ankara", Latitude = 123, Longtitude = 435 });
    //Serialize manually by JSON.Net....        
    TempData["cities"] = Newtonsoft.Json.JsonConvert.SerializeObject(cities);  
    TempData.Keep("cities");  
    return View();
}
[HttpPost]
public IActionResult CitiesOnMap(string SelectedCity)
{
    if (TempData["cities"] != null)
    {
        foreach (var redirectedCity in JsonConvert.DeserializeObject<List<City>>(TempData["cities"] as string))
        {
            if (String.Equals(redirectedCity.CityName, SelectedCity))
            {
                //not sure what is your selected city page
                //but if you redirect to another action
                //you also need to serialize the model data manually
                TempData["selectedCity"] = JsonConvert.SerializeObject(redirectedCity);                
                return RedirectToAction(redirectedCity.CityName, "City");
            }
        }
    }
    return RedirectToAction(SelectedCity, "City"); ;
}

CitiesOnMap.cshtml:

<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         
Newtonsoft.Json.JsonConvert.DeserializeObject<List<MVC.Models.City>>(TempData["cities"] as string))
                {
                    <option>@name.CityName </option>
                }

            </select>
        </div>
    </div>

</form>

推荐阅读