【发布时间】:2017-05-02 12:16:20
【问题描述】:
在我的应用程序中,我有一个表单,用户可以在其中将银行账户添加到他们的账户中。我通过控制器上的两个操作实现了这一点,即:
public async Task<IActionResult> Add()
{
var client = await _clientFactory.CreateClientAsync();
// We obtain the available account types from a remote service.
var accountTypes = await client.GetAccountTypesAsync();
var viewModel = new AddAccountViewModel
{
AccountTypes = accountTypes;
}
return View(viewModel);
}
[HttpPost]
public async Task<IActionResult> Add(AddAccountViewModel model)
{
if (!ModelState.IsValid)
return View(model);
// Store the account for the user, and redirect to a result page.
}
我的AddAccountModel目前看起来是这样的,有两个目的:
public class AddAccountViewModel
{
public List<AccountTypeModel> AccountTypes { get; set; }
[Required]
[StringLength(100)]
public string AccountName { get; set; }
[Required]
[Range(1, int.MaxValue]
public decimal CurrentBalance { get; set; }
[Required]
public Guid AccountTypeId { get; set; }
}
一方面,AccountTypes 属性用于填充视图中的列表:
@{
var accountTypeList = new SelectList(accountTypes, "Id", "Name");
}
<select class="form-control" id="accountType" asp-for="AccountTypeId" asp-items="@accountTypeList">
</select>
当我通过GET /Add 到达初始页面时,一切正常。表单呈现,选择框填充了服务中的项目,正如我所期望的那样。
但是,表单还包括验证,如果用户输入无效数据或将字段留空,POST /Add 会被调用,通过模型,运行验证,最终将用户重定向回GET /Add,具体验证失败的原因。这就是问题出现的地方。
当用户被重定向回表单并被要求更正他们的输入时,我的模型中的AccountTypes 是null。这是有道理的,因为我们没有将它作为POST 请求的一部分发送——它仅作为表单呈现的输入。由于表单不知道帐户类型,用户将永远无法更正他们的输入,因为他们将无法选择有效的帐户类型。
如上所述,我的模型是双重的:一方面它包含视图需要呈现的数据,另一方面它包含用户提供的数据,然后由应用程序处理。
鉴于上述情况,我的问题是:当模型验证失败时,我应该如何正确保存视图呈现所需的输入数据?即,我的ViewModel 是保存AccountTypeModels 集合的正确位置,还是应该将它们保存在ViewData 或什至TempData?
目前,我的应用程序和服务都是无状态的,这就是为什么我还没有走“把它放在 TempData 中”的路线,因为据我所知,TempData 存储在服务器的会话中。如果可以避免的话,我也不想在视图开始时查询可用帐户类型的服务,因为它似乎违反了 MVC 的关注点分离。
感谢阅读,希望有人能帮我解决这个问题。
【问题讨论】:
-
您只需在 POST 方法中返回视图之前重新填充
AccountTypes。但是你的视图模型最好包含IEnumerable<SelectListItem> AccountTypes,而不是在视图中生成SelectList。 -
我不知道我怎么没想到。我已将视图模型更改为包含
IEnumeable<SelectListItem>并将视图直接绑定到该模型,并添加了代码以重新获取 POST 中的可用帐户类型。如果您发表评论作为答案,我会很乐意接受。
标签: c# asp.net-mvc asp.net-core