Проблема передачи сложных данных между представлением и контроллером в ASP.NET MVC - PullRequest
0 голосов
/ 20 декабря 2009

Вот упрощение моих реальных моделей в ASP.NET MVC, которое, я думаю, поможет сосредоточиться на проблеме:

Допустим, у меня есть два объекта домена:

public class ObjectA
{
    public ObjectB ObjectB;
}

public class ObjectB
{
}

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

Я создал новый класс для украшения ObjectA этим списком возможностей, я думаю, это действительно моя модель представления.

public class ObjectAViewModel
{
    public ObjectA ObjectA { get; private set; }
    public SelectList PossibleSelectionsForObjectB { get; private set; }

    public ObjectAViewModel(ObjectA objectA, IEnumerable<Location> possibleObjectBs)
    {
        ObjectA = objectA;
        PossibleSelectionsForObjectB = new SelectList(possibleObjectBs, ObjectA.ObjectB);
    }
}

Теперь, каков наилучший способ создания моего представления и контроллера, чтобы позволить пользователю выбрать ObjectB в представлении, а затем заставить контроллер сохранить ObjectA с этим выбором ObjectB (ObjectB уже существует и сохранен)?

Я попытался создать строго типизированное представление типа ObjectAViewModel и связать Html.DropDownList с Model.PossibleSelectionsForObjectB. Это хорошо, и я могу выбрать объект просто отлично. Но я пытаюсь вернуть его обратно в контроллер.

Попытка решения 1:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(ObjectAViewModel objectAViewModel)

Эта проблема заключается в том, что свойство objectAViewModel.ObjectA.ObjectB имеет значение null. Я думал, что DropDownList, связанный с этим свойством, обновит модель, когда пользователь выберет это в представлении, но это не по какой-то причине.

Попытка решения 2:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(ObjectA objectA)

Эта проблема заключается в том, что свойство ObjectA.ObjectB имеет значение null. Опять же, я подумал, что, возможно, выбор DropDownList обновит это.

Я также пытался использовать метод UpdateModel в каждом из приведенных выше решений, но безуспешно. У кого-нибудь есть какие-либо идеи? Я предполагаю, что мне не хватает привязки или чего-то еще ...

Спасибо!

Ответы [ 2 ]

1 голос
/ 20 декабря 2009

Я использую код следующим образом:

    [HttpPost]
    public ActionResult Create([Bind(Exclude = "Id")]ObjectA objectAToCreate)
    {
        try
        {
            Repository.AddObjectA(objectAToCreate);
            return RedirectToAction("Details", new { id = objectAToCreate.Id });
        }
        catch
        {
            return View();
        }
    }

Со следующим кодом в репозитории (специфично для Entity Framework):

    public void AddObjectA(ObjectA objectAToAdd)
    {
        objectAToAdd.ObjectB = GetObjectB(objectAToAdd.ObjectB.Id);
        _entities.AddToObjectAs(objectAToAdd);
        _entities.SaveChanges();
    }

    public void GetObjectB(int id)
    {
        return _entities.ObjectBs.FirstOrDefault(m => m.id == id);
    }

Согласно вашим комментариям, это, по сути, перезагрузка объекта из базовой службы данных, однако я не нашел необходимости использовать ModelState для доступа к запрашиваемому значению.

Это основано на представлении, закодированном по следующим линиям:

        <p>
            <%= Html.LabelFor( f => f.ObjectB.Id) %>
            <%= Html.DropDownList("ObjectB.Id", new SelectList((IEnumerable)ViewData["ObjectBList"], "Id", "Descriptor"),"") %>
            <%= Html.ValidationFor( f => f.ObjectB, "*") %>
        </p>

Обратите внимание, что это может быть улучшено для использования строго типизированной ViewModel (что, я думаю, вы уже делаете), а также для создания пользовательского шаблона редактора для ObjectB таким образом, чтобы вызов мог выполняться с использованием:

<%= Html.EditorFor( f => f.ObjectB ) %>
0 голосов
/ 20 декабря 2009

После еще одного исследования это не выглядит так, как будто ASP.NET MVC позаботится обо мне. Возможно, есть модель привязки службы данных, которую я могу использовать (поэтому MVC будет автоматически извлекать соответствующий объект из памяти на основе того, что было выбрано в раскрывающемся списке), но сейчас я могу это исправить, обработав его в контроллере: 1001 *

  1. Получить выбранный элемент из раскрывающегося списка, используя Controller.ModelState
  2. Перезагрузите этот ObjectB из базовой службы данных
  3. Назначьте этот ObjectB для ObjectA.ObjectB
  4. Сохранить объект A

Итак, мой метод контроллера выглядит следующим образом:

Отредактировано на основе комментария от LukLed

   [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Create(ObjectA objectA, string objectBStr)
    {
        ObjectB objectB = _objBService.Get(objectBStr);
        objectA.ObjectB = objectB;
        _objAService.Save(objectA);
        return RedirectToAction("Details", new { id = objectA.Id });
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...