Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在模型验证失败时正确保留视图渲染数据?_C#_Asp.net Mvc_Asp.net Core - Fatal编程技术网

C# 如何在模型验证失败时正确保留视图渲染数据?

C# 如何在模型验证失败时正确保留视图渲染数据?,c#,asp.net-mvc,asp.net-core,C#,Asp.net Mvc,Asp.net Core,在我的应用程序中,我有一个表单,用户可以在其中向其帐户添加银行帐户。我在控制器上通过两个操作实现了这一点,即: public async Task<IActionResult> Add() { var client = await _clientFactory.CreateClientAsync(); // We obtain the available account types from a remote service. var accountType

在我的应用程序中,我有一个表单,用户可以在其中向其帐户添加银行帐户。我在控制器上通过两个操作实现了这一点,即:

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.
}
一方面,
AccountTypes
属性用于填充视图中的列表:

@{
    var accountTypeList = new SelectList(accountTypes, "Id", "Name");
}

<select class="form-control" id="accountType" asp-for="AccountTypeId" asp-items="@accountTypeList">

</select>
@{
var accountTypeList=新的选择列表(accountTypes,“Id”,“名称”);
}
当我通过
GET/Add
到达初始页面时,这一切都很好。表单呈现时,选择框将填充来自服务的项目,正如我所期望的那样

但是,表单还包括验证,如果用户输入无效数据或将字段留空,则调用
POST/Add
,传递模型,运行验证,并最终将用户重定向回
GET/Add
,以及验证失败的具体原因。这就是问题所在

当用户被重定向回表单并要求更正其输入时,我的模型中的
AccountTypes
null
。这是有道理的,因为我们没有将其作为
POST
请求的一部分发送-它只作为表单呈现的输入。由于表单不知道帐户类型,用户将永远无法更正其输入,因为他们将无法选择有效的帐户类型

如上所述,我的模型有两个方面:一方面它包含视图需要渲染的数据,另一方面它包含用户提供的数据,然后由应用程序处理

鉴于上述情况,我的问题是:当模型验证失败时,我应该如何正确保存视图渲染所需的输入数据?也就是说,我的
ViewModel
是保存
AccountTypeModel
集合的正确位置,还是应该将它们保存在
viewmata
,或者甚至是
TempData

目前,我的应用程序和服务都是无状态的,这就是为什么我还没有走上“只在TempData中使用TempData”的路线,据我所知,TempData存储在服务器的会话中。如果可以避免的话,我也不想在视图开始时查询服务中的可用帐户类型,因为这似乎违反了MVC的关注点分离


感谢阅读,我希望有人能帮我解决这个问题。

在返回视图之前,需要在POST方法中重新填充
AccountTypes
集合。我建议您的视图模型包含一个属性
public IEnumerable AccountTypes{get;set;}
,而不是
List
,这样您就不需要在视图中生成
SelectList

要保持干燥,请创建一个私有方法来配置视图模型

public async Task<IActionResult> Add()
{
    var model = new AddAccountViewModel();
    ConfigureViewModel(model);
    return View(model);
}

[HttpPost]
public async Task<IActionResult> Add(AddAccountViewModel model)
{
    if (!ModelState.IsValid)
    {
        ConfigureViewModel(model);
        return View(model);
    }
    ....
}

private async Task ConfigureViewModel(AddAccountViewModel model)
{
    var client = await _clientFactory.CreateClientAsync();
    var accountTypes = await client.GetAccountTypesAsync();
    model.AccountTypes = new SelectList(accountTypes, "Id", "Name");
}
公共异步任务添加() { var模型=新的AddAccountViewModel(); 配置视图模型(模型); 返回视图(模型); } [HttpPost] 公共异步任务添加(AddAccountViewModel模型) { 如果(!ModelState.IsValid) { 配置视图模型(模型); 返回视图(模型); } .... } 专用异步任务配置ViewModel(AddAccountViewModel模型) { var client=wait_clientFactory.createClientSync(); var accountTypes=await client.GetAccountTypesAsync(); model.AccountTypes=新的选择列表(AccountTypes,“Id”,“Name”); }
POST方法返回视图之前,只需重新填充
AccountTypes
。但是您的视图模型最好包含
IEnumerable AccountTypes
,而不是在视图中生成
SelectList
。我不确定我怎么会没有想到这一点。我已经更改了视图模型,以包含一个
IEnumable
,并将视图直接绑定到该视图,并且添加了代码以重新获取帖子中可用的帐户类型。如果你把你的评论作为回答,我很乐意接受。
public async Task<IActionResult> Add()
{
    var model = new AddAccountViewModel();
    ConfigureViewModel(model);
    return View(model);
}

[HttpPost]
public async Task<IActionResult> Add(AddAccountViewModel model)
{
    if (!ModelState.IsValid)
    {
        ConfigureViewModel(model);
        return View(model);
    }
    ....
}

private async Task ConfigureViewModel(AddAccountViewModel model)
{
    var client = await _clientFactory.CreateClientAsync();
    var accountTypes = await client.GetAccountTypesAsync();
    model.AccountTypes = new SelectList(accountTypes, "Id", "Name");
}