通过TempData在ASP.NET Core 6 MVC中在所有页面传递参数

huangapple go评论62阅读模式
英文:

passing parameters through all pages using TempData in asp.net core6 mvc

问题

我有一个学校数据库,其中有诸如“Year”、“Grade”、“Major”等实体...
我试图在“_Layout.cshtml”中创建一个年份列表,当用户从列表中选择一年时,所有视图必须基于所选年份检索数据。
因此,我首先需要创建列表,然后将所选年份传递给所有视图。
我尝试使用一个viewModel,但它不起作用。现在我试图以一种方式使用TempData来保存年份列表和所选年份,但我一直收到以下错误消息。

> System.NullReferenceException: 对象引用未设置为对象的实例。

这是我的AdminController:

public async Task<IActionResult> Index()
{
    var allYears = await _context.Years.ToListAsync();
    List<SelectListItem> yearList = new List<SelectListItem>();
    foreach (var item in allYears)
    {
        yearList.Add(new SelectListItem { Text = item.Name, Value = item.Id.ToString() });
    }
    TempData["YearList"] = yearList;
    TempData["CurrentYear"] = allYears.FirstOrDefault().Id.ToString();
    return View(TempData);
}

这是在_Layout.cshtml中的局部视图中的列表。这是我得到错误的地方。TempData为null。:

<select class="form-control" asp-for="@TempData["CurrentYear"]">
    @foreach (var item in (List<SelectListItem>)TempData["YearList"])
    {
        <option>@item.Text</option> 
    }    
</select>

我还将这个添加到_viewStart.cshtml中。

TempData["CurrentYear"] = 1;
TempData["YearList"] = null;

我还尝试了这个,但问题仍然存在。
有没有办法可以使用TempData实现这一点?
还是有更好的方法?

Edit1: 我从viewStart.cshtml中删除了初始化。但当导航到另一个视图时,我仍然收到null异常错误。

Edit2: 我使用了Session而不是TempData。另外,我将下拉列表移到了一个单独的视图,因为我在将列表添加到会话中时遇到了问题。但后来RahulSharma在评论部分发送了一个教程,非常有帮助。
谢谢大家。

英文:

I have a school database, where there are entities such as Year, Grade, Major, ...
I'm trying to create a list of years in the _Layout.cshtml and when the user chooses a year from the list, all views must retrieve data based on the selected year.
So I need to first create the list and then pass the selected year to all views.
I tried using a viewModel but it didn't work. Now I'm trying to make use of TempData in a way to keep the list of years and the selected year, but I keep receiving the following error.

> System.NullReferenceException: Object reference not set to an instance of an object.

Here is my AdminController:

public async Task<IActionResult> Index()
{
    var allYears = await _context.Years.ToListAsync();
    List<SelectListItem> yearList = new List<SelectListItem>();
    foreach (var item in allYears)
    {
        yearList.Add(new SelectListItem { Text = item.Name, Value = item.Id.ToString() });
    }
    TempData["YearList"] = yearList;
    TempData["CurrentYear"] = allYears.FirstOrDefault().Id.ToString();
    return View(TempData);
}

This is the list in the partial view in _Layout.cshtml. This is where I get the error. TempData is null.:

<select class="form-control" asp-for="@TempData["CurrentYear"]">
    @foreach (var item in (List<SelectListItem>)TempData["YearList"])
    {
        <option>@item.Text</option> 
    }    
</select>

I have also added this to _viewStart.cshtml.

TempData["CurrentYear"] = 1;
TempData["YearList"] = null;

I have also tried this, but the issue still remains.
Is there any way I can achieve this using TempData?
Or Is there a better way?

Edit1: I removed the initialization in viewStart.cshtml. But still I get the null exception error when navigating to another view.

Edit2: I used Session instead of TempData. Also I moved the dropdownlist to a separate view because I had a problem with adding a list to the session. But then RahulSharma sent a tutorial in the comment section which is very helpful.
Thank you everyone.

答案1

得分: 2

以下是您情境的原型代码翻译:

Controller

[HttpGet]
public async Task<IActionResult> Index()
{
    TempData["YearList"] = new List<SelectListItem> { new SelectListItem("2021", "2021"), new SelectListItem("2022", "2022"), new SelectListItem("2023", "2023") };
    return View();
}

[HttpPost]
public async Task<IActionResult> Index(int year)
{
    TempData["CurrentYear"] = year;
    return RedirectToAction(nameof(Index));
}

View

<form method="post">
    <select name="year">
        @foreach (var year in (List<SelectListItem>)TempData["YearList"])
        {
            <option value="@year.Value">@year.Text</option>
        }
    </select>
    <input type="submit" value="Send"/>
</form>

<h3>Selected year: @TempData["CurrentYear"]</h3>

解释:

  1. [HttpGet]Index 动作方法呈现年份,此步骤中没有选定的年份。
  2. 视图从 TempData 中检索值并显示 select 控件。
  3. 用户选择年份,然后点击按钮(提交表单)。
  4. [HttpPost]Index 接受年份参数(名称与选择控件的 name 属性匹配)。将选择放入 TempData
  5. 重定向到 [HttpGet]Index
  6. 渲染列表和选定的值。这里的关键点是,如果只是刷新页面,它不会再次恢复选定的值。从 TempData 中提取是一次性操作(阅读答案https://stackoverflow.com/a/32571656/2091519)。

要考虑的要点:

  1. 通过重定向和查询字符串参数传递选定的年份,而不是提交表单(https://stackoverflow.com/a/10175571/2091519)。
  2. 使用 Ajax(异步)方法在用户选择后获取其他数据(https://stackoverflow.com/a/29122117/2091519)。
  3. 使用 ViewBag/ModelViews 或任何其他容器来从控制器传递数据到视图。
  4. 使用 Cookies/Session 在页面重新加载之间保持数据持久性。
    等等。
英文:

Here is the prototype for your scenario

Controller:

[HttpGet]
public async Task&lt;IActionResult&gt; Index()
{
    TempData[&quot;YearList&quot;] = new List&lt;SelectListItem&gt; { new (&quot;2021&quot;, &quot;2021&quot;), new (&quot;2022&quot;, &quot;2022&quot;), new (&quot;2023&quot;, &quot;2023&quot;) };
    return View();
}

[HttpPost]
public async Task&lt;IActionResult&gt; Index(int year)
{
    TempData[&quot;CurrentYear&quot;] = year;
    return RedirectToAction(nameof(Index));
}

View:

&lt;form method=&quot;post&quot;&gt;
    &lt;select name=&quot;year&quot;&gt;
        @foreach (var year in (List&lt;SelectListItem&gt;)TempData[&quot;YearList&quot;])
        {
            &lt;option value=&quot;@year.Value&quot;&gt;@year.Text&lt;/option&gt;
        }
    &lt;/select&gt;
    &lt;input type=&quot;submit&quot; value=&quot;Send&quot;/&gt;
&lt;/form&gt;

&lt;h3&gt;Selected year: @TempData[&quot;CurrentYear&quot;]&lt;/h3&gt;

Explanation:

  1. [HttpGet]Index action method renders years, no selected year on this step
  2. View retrieves the values from TempData and display select control
  3. User choose the year, and click button (submit form)
  4. [HttpPost]Index accept year argument (name matches name attribute of select control). Put the selection into TempData
  5. Redirect to [HttpGet]Index
  6. Renders both list and selected value. The key point here is that if you just refresh the page it won't recover selected value again. Extraction from TempData is one-time operation (read answer https://stackoverflow.com/a/32571656/2091519)

Points to consider:

  1. pass the selected year via redirect & query string parameters rather than submitting the form (https://stackoverflow.com/a/10175571/2091519)
  2. Use Ajax (async) approach to fetch additional data after user selection (https://stackoverflow.com/a/29122117/2091519)
  3. Use ViewBag/ModelViews or any other container for passing data from contoller to view
  4. Use Cookies/Session to persist data between page reloads
    etc

huangapple
  • 本文由 发表于 2023年6月19日 21:13:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/76506988.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定