考虑此模型和视图模型:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
}
public class PersonViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
}
仅用于编辑电子邮件的表单:
<form asp-action="UpdateEmail">
<input type="hidden" asp-for="Id" />
<label asp-for="Email"></label>
<input asp-for="Email" />
<button type="submit">Update e-mail address</button>
</form>
和UpdateEmail()
POST控制器方法:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> UpdateEmail(int id, [Bind("Id,Email")] Person person)
{
if (id != person.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
db.Update(person);
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
// ... stuff
}
return RedirectToAction("Details", new { id = person.Id });
}
return View(auto.Map<PersonViewModel>(person));
}
根据我的经验,在这种情况下,Email
以外的所有其他属性都将被NULL
值覆盖。我真的必须将它们添加为表单中的隐藏字段吗?如果是这样,那么使用[Bind("Id,Email")]
有什么意义?
您的表单仅包含字段名称Id
和Email
,因此只有这些值将被发送回Web服务器(和操作方法)。 ASP.NET MVC机械师可以将这些值填充到您提供的对象/类中,在本例中为Person
对象,但所有其他值保持未定义状态,并具有其默认值(如null
,0
等) 。)。
您可以更改UpdateEmail()
方法签名以将表单数据保存在单独的参数中,例如:
public async Task<IActionResult> UpdateEmail(int id, string email)
从那里您可以从数据库中加载实体并更改值(or doing it directly)。
如果要使用一个对象而不是每个表单元素都具有多个参数,则可以定义一个新模型并使用它:
public class UpdateEmailModel
{
public int Id { get; set; }
public string Email { get; set; }
}
然后您可以将方法更改为:
public async Task<IActionResult> UpdateEmail(UpdateEmailModel model)
或者您也可以将类型更改为PersonViewModel
,因为无论如何这都是您要使用return View(auto.Map<PersonViewModel>(person));
发送的型号。但这在某种程度上有点“过大杀伤力”,因为您向HTML表单发送的数据比使用它要多,但是这可能还可以,取决于您对“未使用”数据的处理方式。也许您应该使用return View(auto.Map<UpdateEmailModel>(person));
将代码更改为新模型。
作为建议,您不应将Person
实体用作表单数据的接收类/对象。这样,数据库中的列将指示如何命名HTML表单。这也意味着出于某种原因,HTML视图部分对存储数据的数据库有某种依赖性,而不应这样做。它仅应与控制器部件中定义的模型一起使用。但这只是一个建议,显然是基于意见的。