Инициализация предпочтительной модели .NET MVC3 - PullRequest
8 голосов
/ 19 сентября 2011

Я недавно работал в MVC, и мне любопытно, как лучше всего инициализировать мои модели представлений.Должен ли я отображать его непосредственно в контроллере или инициализировать свойства в конструкторе для модели представления.Кроме того, при наличии списков это более эффективная практика, поскольку вам не придется повторно заполнять их при наличии ошибки проверки.

Например, если у меня была следующая модель:

public FooBarViewModel
{
    public int FooBarId { get; set; }
    public string SomeInitialProperty1 { get; set; }
    public string SomeInitialProperty2 { get; set; }
    public string SomeInitialProperty3 { get; set; }
    public string SomeInitialProperty4 { get; set; }
    public int FooId { get; set; }
    public int BarId { get; set; }
    public IEnumerable<Foo> Foos { get; set; }
    public IEnumerable<Bar> Bars { get; set; }
}

и затем контроллер:

public MyController : Controller
{
    [HttpGet]
    public ActionResult FooBar(int foobarId)
    {
        var foobar = _fooBarRepository.GetById(foobarId);
        var model = new FooBarViewModel
                        {
                            FooBarId = foobar.Id;
                            SomeInitialProperty1 = foobar.SomeInitialProperty1;
                            SomeInitialProperty2 = foobar.SomeInitialProperty2;
                            SomeInitialProperty3 = foobar.SomeInitialProperty3;
                            SomeInitialProperty4 = foobar.SomeInitialProperty4;
                            Foos = foobar.Foos.ToList();
                            Bars = foobar.Bars.ToList();
                        }

        return View(model);
    }

    [HttpPost]
    public ActionResult FooBar(FooBarViewModel model)
    {
        if (ModelState.IsValid)
        {
             //process model
             return RedirectToAction("Index");
        }

        var foobar = _fooBarRepository.GetById(model.FoobarId);
        model.Foos = foobar.GetFoos.ToList();
        model.Bars = foobar.GetBars.ToList();
        return View(model);
    }
}

или я должен сделать это в моей модели:

public FooBarViewModel
{
    public int FooBarId { get; set; }
    public string SomeInitialProperty1 { get; set; }
    public string SomeInitialProperty2 { get; set; }
    public string SomeInitialProperty3 { get; set; }
    public string SomeInitialProperty4 { get; set; }
    public int FooId { get; set; }
    public int BarId { get; set; }

    public IEnumerable<Foo> Foos 
    { 
        get { return _foos; }
    }
    private IEnumerable<Foo> _foos;

    public IEnumerable<Bar> Bars
    { 
        get { return _bars; }
    }
    private IEnumerable<Bar> _bars;

    public MyViewModel(FooBar foobar)
    {
        FooBarId = foobar.Id;
        SomeInitialProperty1 = foobar.SomeInitialProperty1;
        SomeInitialProperty2 = foobar.SomeInitialProperty2;
        SomeInitialProperty3 = foobar.SomeInitialProperty3;
        SomeInitialProperty4 = foobar.SomeInitialProperty4;
        _foos = foobar.Foos.ToList();
        _bars = foobar.Bars.ToList();
    }
}

затем мой контроллер:

public MyController : Controller
{
    [HttpGet]
    public ActionResult FooBar(int foobarId)
    {
        var foobar = _fooBarRepository.GetById(foobarId);
        var model = new FooBarViewModel(foobar);

        return View(model);
    }

    [HttpPost]
    public ActionResult FooBar(FooBarViewModelmodel)
    {
        if (ModelState.IsValid)
        {
             //process model
             return RedirectToAction("Index");
        }

        return View(model);
    }
}

Какое предпочтительное соглашениев MVC и почему это лучшая практика?Кроме того, причины, почему стоит выбирать один над другим?Заранее спасибо.

Ответы [ 4 ]

4 голосов
/ 19 сентября 2011

По умолчанию я не верю, что MVC будет использовать DependencyResolver для создания экземпляра вашей модели представления при обратной передаче. Таким образом, он будет создавать только модель с конструктором без параметров. Это упрощает инициализацию объекта в конструкторе.

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

Я предпочитаю инициализировать свои модели представлений с помощью AutoMapper.

4 голосов
/ 19 сентября 2011

Вообще говоря, вам нужны тяжелые модели и легкие контроллеры, так что вы делаете как можно меньше в своем контроллере.

Общие причины проектирования модели Вы должны инициализировать ViewModel в модели представления?

  • DRY - если у вас есть более одного действия, которое должно инициализировать ViewModel, вы не повторяете этот код или помещаете его в закрытый метод вконтроллер.Для меня, если вам нужно поместить приватный метод в контроллер, это довольно убедительный признак того, что код вообще не принадлежит контроллеру.
  • cohesion - В общем,Объект Foo должен знать, как создать экземпляр объекта Foo из какого-либо другого объекта, поскольку он несет ответственность за знание о себе.Размещение этой логики в другом месте уменьшает сплоченность и вводит связь.
3 голосов
/ 19 сентября 2011

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

Что если вам понадобится еще один экземпляр этого класса где-нибудь еще?Вам нужно будет скопировать код инициализации, откуда бы вы его ни создавали.

3 голосов
/ 19 сентября 2011

Я всегда использую 2-й подход, но с конструктором "все свойства как параметры" вместо того, чтобы вставлять "Foobar" в конструктор (вид нарушения шаблона MVVM, так как ViewModel должен оставаться независимым).

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

...