Нужно ли добавлять скрытые поля для всей модели при обновлении только некоторых свойств? - PullRequest
0 голосов
/ 18 апреля 2020

Рассмотрим эту модель и модель представления:

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")]?

1 Ответ

1 голос
/ 18 апреля 2020

Ваша форма содержит только имена полей Id и Email, поэтому только эти значения будут отправлены обратно на веб-сервер (и метод действия). ASP. NET MVC mechani c может заполнить эти значения в указанном вами объекте / классе, в данном случае объект Person, но все остальные значения остаются неопределенными и имеют значения по умолчанию (например, null, 0, et c.).

Вы можете изменить сигнатуру метода UpdateEmail(), чтобы сохранить данные формы в отдельных аргументах, например:

public async Task<IActionResult> UpdateEmail(int id, string email)

Из там вы можете загрузить сущность из базы данных и изменить значение ( или сделать это напрямую ).

Если вы хотите работать с одним объектом вместо нескольких параметров для каждого элемента формы, Вы можете определить новую модель и использовать ее вместо:

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 имеет некоторую зависимость от базы данных, в которой хранятся данные, чего не должно быть. Он должен работать только с моделями, указанными в сборке контроллера. Но это всего лишь предположение и, очевидно, основанное на мнении.

...