ASP.NET MVC 3 Шаблон представления - PullRequest
5 голосов
/ 04 марта 2012

Я пытаюсь найти наилучший способ использования модели представления в случае создания нового объекта.

У меня очень простая модель представления, которая содержит контактный объект и список избранных компаний.

private ICompanyService _Service;
public SelectList ContactCompanyList { get; private set; }
public Contact contact { get; private set; }

public ContactCompanyViewModel(Contact _Contact)
{
    _Service = new CompanyService();
    contact = _Contact;
    ContactCompanyList = GetCompanyList();
}

private SelectList GetCompanyList()
{
    IEnumerable<Company> _CompanyList = _Service.GetAll();
    return new SelectList(_CompanyList, "id", "name");       
}

Затем у меня есть контроллер контактов, который использует эту модель представления и позволяет мне выбрать связанную компанию для моего контакта.

[Authorize]
public ActionResult Create()
{                       
    return View(new ContactCompanyViewModel(new Contact()));
}

Моя проблема связана с методом create на контроллере.

[Authorize]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Contact _Contact)
{
    try
    {
        _Service.Save(_Contact);
        return RedirectToAction("Index");
    }
    catch
    {
       return View();
    }
}

Проблема в том, что представление возвращает пустой контактный объект, но!идентификатор компании заполнен, это потому, что раскрывающийся список явно объявляет имя своего поля.

 @Html.DropDownList("parent_company_id",Model.ContactCompanyList)

Стандартные поля формы html передают значения объектов в формате contact.forename при использовании HTML.EditorForхелпер ...

@Html.EditorFor(model => model.contact.forename)

Я могу получить к ним доступ, если использую FormCollection в качестве моего параметра метода создания действия, а затем явно ищу contact.value, но не могу использовать объект Contact в качестве параметра для сохранениямой код хорош и чист и не должен каждый раз создавать новый контактный объект.

Я попытался передать реальный объект модели представления обратно в качестве параметра, но это просто приводит к ошибке конструктора (что сбивает с толку видение, поскольку представление связано с моделью представления, а не с объектом контакта).

Есть ли способ, которым я могу определить имя поля Html.EditFor, чтобы значение корректно отображалось обратно в объект контакта при передаче обратно методу create action на моем контроллере?Или я где-то допустил ошибку FUBAR (это наиболее вероятное объяснение, поскольку это учебное упражнение!).

1 Ответ

15 голосов
/ 04 марта 2012

Ваша модель обзора выглядит неправильно.Просмотр моделей не должен ссылаться на какие-либо услуги.Модели представлений не должны ссылаться на какие-либо доменные модели.Модели представления должны иметь конструкторы без параметров, чтобы их можно было использовать в качестве параметров действия POST.

Итак, вот более реалистичная модель представления для вашего сценария:

public class ContactCompanyViewModel
{
    public string SelectedCompanyId { get; set; }
    public IEnumerable<SelectListItem> CompanyList { get; set; }

    ... other properties that the view requires
}

, и тогда вы можете получить GETдействие, которое подготовит и заполнит эту модель представления:

public ActionResult Create()
{
    var model = new ContactCompanyViewModel();
    model.CompanyList = _Service.GetAll().ToList().Select(x => new SelectListItem
    {
        Value = x.id.ToString(),
        Text = x.name
    });
    return View(model);
}

и действие POST:

[HttpPost]
public ActionResult Create(ContactCompanyViewModel model)
{
    try
    {
        // TODO: to avoid this manual mapping you could use a mapper tool
        // such as AutoMapper
        var contact = new Contact
        {
            ... map the contact domain model properties from the view model
        };
        _Service.Save(contact);
        return RedirectToAction("Index");
    }
    catch 
    {
        model.CompanyList = _Service.GetAll().ToList().Select(x => new SelectListItem
        {
            Value = x.id.ToString(),
            Text = x.name
        });
        return View(model);
    }
}

, и теперь в вашем представлении вы работаете с моделью представления:

@model ContactCompanyViewModel
@using (Html.BeginForm())
{
    @Html.DropDownListFor(x => x.SelectedCompanyId, Model.CompanyList)

    ... other input fields for other properties

    <button type="submit">Create</button>
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...