Пользовательская модель Binder для сложных составных объектов ПОМОЩЬ - PullRequest
7 голосов
/ 03 апреля 2009

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

это класс, который я пытаюсь связать:

public class Fund
{
        public int Id { get; set; }
        public string Name { get; set; }
        public List<FundAllocation> FundAllocations { get; set; }
}

и вот как выглядит моя попытка написания пользовательского связующего:

public class FundModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        throw new NotImplementedException();
    }

    public object GetValue(ControllerContext controllerContext, string modelName, Type modelType, ModelStateDictionary modelState)
    {
        var fund = new Fund();

        fund.Id = int.Parse(controllerContext.HttpContext.Request.Form["Id"]);
        fund.Name = controllerContext.HttpContext.Request.Form["Name"];

        //i don't know how to bind to the list property :(
        fund.FundItems[0].Catalogue.Id = controllerContext.HttpContext.Request.Form["FundItem.Catalogue.Id"];
        return fund;
    }
}

Любые идеи

спасибо Tony

Ответы [ 2 ]

8 голосов
/ 22 апреля 2009

Вам действительно нужно реализовать собственный ModelBinder здесь? Связыватель по умолчанию может делать то, что вам нужно (так как он может заполнять коллекции и сложные объекты):

Допустим, ваше действие контроллера выглядит так:

public ActionResult SomeAction(Fund fund)
{
  //do some stuff
  return View();
}

И ваш HTML содержит это:

<input type="text" name="fund.Id" value="1" />
<input type="text" name="fund.Name" value="SomeName" />

<input type="text" name="fund.FundAllocations.Index" value="0" />
<input type="text" name="fund.FundAllocations[0].SomeProperty" value="abc" />

<input type="text" name="fund.FundAllocations.Index" value="1" />
<input type="text" name="fund.FundAllocations[1].SomeProperty" value="xyz" />

Связыватель модели по умолчанию должен инициализировать ваш объект фонда с двумя элементами в списке FundAllocations (я не знаю, как выглядит ваш класс FundAllocation, поэтому я создал единственное свойство SomeProperty). Просто обязательно включите те элементы «fund.FundAllocations.Index» (которые связыватель по умолчанию рассматривает для собственного использования), которые я получил, когда попытался заставить это работать).

3 голосов
/ 22 апреля 2009

В последнее время я слишком много трачу на эту же вещь!

Не видя вашу HTML-форму, я предполагаю, что она просто возвращает результаты выбора из списка с множественным выбором или что-то в этом роде? Если это так, ваша форма просто возвращает набор целых чисел, а не возвращает ваш гидратированный FundAllocations объект. Если вы хотите сделать это, то в вашем собственном ModelBinder вам нужно будет выполнить свой собственный поиск и увлажнить объект самостоятельно.

Что-то вроде:

fund.FundAllocations = 
      repository.Where(f => 
      controllerContext.HttpContext.Request.Form["FundItem.Catalogue.Id"].Contains(f.Id.ToString()); 

Конечно, мой LINQ приведен только для примера, и вы, очевидно, можете получить данные в любом случае, если захотите. Между прочим, и я знаю, что это не отвечает на ваш вопрос, но после долгих раздумий я решил, что для сложных объектов лучше использовать ViewModel и привязать ModelBinder по умолчанию к этому, а затем, если мне нужно, гидрировать модель, которая представляет мою сущность. Я столкнулся с рядом проблем, которые сделали этот выбор лучшим, я не буду утомлять вас ими, но с удовольствием экстраполирую, если хотите.

Последний подкаст Herding Code является отличным обсуждением этого вопроса, как и K Скотта Аллена Помещение М в сообщениях блога MVC .

...