.NET MVC3首选模型初始化

时间:2011-09-19 18:03:46

标签: c# .net asp.net-mvc asp.net-mvc-3

我最近一直在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 个答案:

答案 0 :(得分:4)

一般来说,您需要重型和轻型控制器,因此您可以在控制器中尽可能少地工作。

一般设计模式的原因你应该在视图模型中初始化ViewModel?

  • DRY - 如果您有多个必须初始化ViewModel的操作,那么您将重复该代码,或者将其放在控制器中的私有方法中。对我来说,如果你需要在控制器中放置一个私有方法,那么这是一个相当强烈的迹象,表明代码根本不属于控制器。
  • 凝聚力 - 通常,Foo对象应该知道如何从其他对象实例化Foo对象,因为它有责任了解自己。将该逻辑放在其他地方会降低内聚力并引入耦合。

答案 1 :(得分:4)

默认情况下,我不相信MVC会使用DependencyResolver在回发时创建视图模型的实例。因此,它只会创建一个带无参数构造函数的模型。这使得在构造函数中初始化对象变得不那么容易。

您可以创建一个通过DependencyResolver创建对象的自定义模型绑定器,但是您正在偏离正常练习。

我更喜欢使用AutoMapper初始化我的视图模型。

答案 2 :(得分:3)

我总是使用第二种方法,但使用“all-properties as parameters”-contructor而不是将“Foobar”插入构造函数(违反MVVM模式的种类,因为ViewModel应该保持独立)。 / p>

对我而言,这是最佳实践,因为您可以在视图模型中隐藏其他逻辑,并且您可以通过使用不同的构造函数来创建不同的行为。

答案 3 :(得分:3)

我认为你在第二种情况下做得很好。在我看来,准备好使用对象是该对象本身的责任。

如果您在其他地方需要该类的其他实例,该怎么办?您必须先从初始化代码的任何位置复制初始化代码。