【问题标题】:Initialize collections in ASP.NET Core Controller在 ASP.NET Core 控制器中初始化集合
【发布时间】:2017-12-27 20:27:37
【问题描述】:

我有一个控制器,它应该显示几个具有预定义值的选择(下拉菜单)。

我显示一个记录列表,每个Record 可以有一个预定义的Theme,并对应预定义值列表中的一个City

在我的控制器中我有

private IEnumerable<Record> records;
private static IEnumerable<Theme> themes;
private static IEnumerable<City> cities;

private async Task<bool> LoadThemes()
{
    themes = await repository.GetTableEntitiesAsync<Theme>(lang);
    return true;
}

private async Task<bool> LoadCities()
{
    themes = await repository.GetTableEntitiesAsync<City>(lang);
    return true;
}

和行动

public async Task<IActionResult> Index()
{
    // records = from DB, then
    await LoadThemes(); ViewData["themes"] = this.themes;
    await LoadCities(); ViewData["cities"] = this.cities;

    return View(records);
}

public async Task<IActionResult> Edit(string id)
{
    // record => from id, then
    await LoadThemes(); ViewData["themes"] = this.themes;
    await LoadCities(); ViewData["cities"] = this.cities;

    return View(record);
}

由于我不能执行 async 构造函数,也不能确定通过 Index 视图传递,我怎样才能只初始化我的“静态”集合一次?

【问题讨论】:

  • 您是否在 LoadCities() 方法中加载城市或主题?即cities = await...
  • 我编辑了 OP 来解释这一点
  • 控制器中的静态变量不能很好地替代实现真正的缓存。从一个方法返回一个布尔值,返回的唯一值是 true 也没有意义。

标签: asp.net asp.net-core asp.net-core-1.1


【解决方案1】:

在这种情况下,您不应该使用静态变量。相反,您只需将它们存储在局部变量中。

查看

<form asp-controller="Index" asp-action="Sample" method="post">
    <select asp-for="Cities" asp-items="@Model.Cities"></select>
    <select asp-for="ThemeId" asp-items="@Model.Themes"></select>
    <button type="submit">Submit</button>
</form>

视图模型

public class RecordViewModel
{
    public string Id { get; set; }
    public string ThemeId { get; set; }
    public string CityId { get; set; }
    public IList<SelectListItem> Themes { get; set; }            
    public IList<SelectListItem> Cities { get; set; }

    public RecordViewModel()
    {
        Themes = new List<SelectListItem>();
        Cities = new List<SelectListItem>();
    }
}

控制器

public async Task<IActionResult> Index()
{
    var lang = "???";
    var model = new RecordViewModel
    {
        Themes = (await repository.GetTableEntitiesAsync<Theme>(lang))
            .Select(x => new SelectListItem {Value = x.Id,Text = x.Text}),
        Cities = (await repository.GetTableEntitiesAsync<City>(lang))
            .Select(x => new SelectListItem { Value = x.Id, Text = x.Text })
    };
    return View(model);
}

public async Task<IActionResult> Edit(string id)
{
    var lang = "???";
    var model = new RecordViewModel
    {
        Id = id,
        Themes = (await repository.GetTableEntitiesAsync<Theme>(lang))
            .Select(x => new SelectListItem { Value = x.Id, Text = x.Text }),
        Cities = (await repository.GetTableEntitiesAsync<City>(lang))
            .Select(x => new SelectListItem { Value = x.Id, Text = x.Text })
    };
    return View(model);
}

其他想法

如果您不想创建两个视图 - 一个用于创建,一个用于编辑,您可能需要考虑创建一个局部视图 _CreateOrUpdate.cshtml,并像 this 一样在它们之间共享它。这里是对应的CreateEdit 方法。

如果您不想每次都查询数据库,您可能需要考虑使用 MemoryCache,例如 this

【讨论】:

  • 好的,但是主题和城市列表没有改变。是相同的 const 值列表。真的有必要在每个视图中每次都加载吗?我的意思是,我可以在控制器的构造函数中再次加载它并将其用于所有视图吗?
  • 在这种情况下使用静态变量缓存数据不是一个好习惯。此外,我们很少在 Web 应用程序中使用静态/单例。相反,您应该考虑使用 MemoryCache。
  • 我们不应该在构造函数中加载数据,更不用说构造函数不能是异步的。否则,我们将在每次网络隐藏该控制器时查询数据,尽管某些操作方法不需要它们。
  • 也许我应该看看 MemoryCache 解决方案然后...... :)
  • 是的,here 是使用 MemoryCache 的示例代码。
猜你喜欢
  • 1970-01-01
  • 2011-12-14
  • 2018-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-04
  • 2012-10-14
  • 2018-02-10
相关资源
最近更新 更多