1

我是 ASP.NET MVC 的新手,正在尝试学习基础知识。我现在正在尝试学习模型、视图和控制器之间的关系。

这三者的互动看起来不一样,为什么呢?(看箭头)

来源 1: MSDN

资料来源 2(第 65 页):史蒂文·桑德森

如果你能帮我解决我的困惑,我会很高兴

谢谢

编辑:你的意思是 mvc 可以以不同的方式实现?(仍在询问 asp.net mvc - 一般不是 mvc)

我一直在看mvcmusicstore ,它看起来像这样。控制器:

public ActionResult Details(int id)
    {
        var album = storeDB.Albums.Find(id);
        return View(album);
    }

模型:

public class Album
{
    public int AlbumId { get; set; }
    public int GenreId { get; set; }
    public int ArtistId { get; set; }
    public string Title { get; set; }
    public decimal Price { get; set; }
    public string AlbumArtUrl { get; set; }

    public Genre Genre { get; set; }
    public Artist Artist { get; set; }
}

查看:(必须添加为图像,以正常方式添加代码不起作用) 风景

这看起来像 MSDN 版本,如何重写以适合 Sandersons 图?也许这会帮助我理解!

再次编辑:

你好,我们又见面了

让我总结一下。如果我错了,请回复。微软希望我们使用 mvc 的方式是我们在上面的 MSDN 链接和 MusicStore 中看到的方式。然后还有 mvc 的其他“版本”,例如 Sandersons(或任何它起源的地方)。所以微软给了我们一个基本的如何使用mvc框架的方法,但是用其他方法也可以。

新手不应该因为看到不同的版本而感到压力,坚持在 MSDN/MusicStore 中看到的版本是完全可以的。

4

3 回答 3

2

关键的区别是在 Sanderson 的图表中包含了“表示模型”。ASP.NET MVC 实现经常使用模型作为表示模型,即使它们可以不同(我认为它们应该不同,但这是一场圣战,没有必要深入探讨)。

在大多数非常简单的 ASP.NET MVC 应用程序中,模型就是数据实体。无论是 EF 实体还是 Linq2Sql 实体,都没有区别。这是因为大多数应用程序都是简单的表单数据,并且表示可能与持久性是一对一的。

然而,MVC 模式本身并不需要这个。在更纯粹的框架无关形式中,Sanderson 的图表说明了控制器正在与模型交互的事实。从这个意义上说,该模型实际上是“领域核心的门户”。控制器和视图是应用程序的一部分,但模型具有底层业务逻辑,在此之下还有持久层和其他应用程序未知的基础设施信息(当然是适当分离的)。控制器和模型之间的边界是应用程序边界,其他应用程序也可以在该点连接到域核心并与之交互。

表示模型通常只是一个简单的值对象。它不是任何类型的实体,因为它不必像可持久化的业务实体那样展示任何业务行为或维护其生命周期。它只是一个具有某些数据属性的平面对象。

它可以有一些行为,但这种行为是针对应用程序的,而不是针对域核心的。例如,也许它有一些视图可以使用的方法或属性。表示模型是应用程序的一部分,因此它是表示层感知的。本质上,它只是保存控制器需要传递给视图的数据(甚至从请求中接收,具体取决于框架)。

在 ASP.NET MVC 中,您会经常看到该模型也用作表示模型。在这些情况下,同一个对象可能扮演两个角色,但这两个角色肯定是不同的。


编辑:刚刚注意到你更新的问题......

在那个例子中,Album扮演着领域模型和表示模型的角色。(事实上​​,我认为它根本不是领域模型,因为它太贫乏了。请注意,它没有功能,只有裸数据。)在更丰富的领域模型中,Album可能会有更多的功能。对于一个人为的例子,想象一下它不是自动实现的属性,而是在设置时强制执行业务逻辑的属性,并且它具有诸如AddSong(Song song)Play()其他此类行为之类的方法。

这种更丰富的模型仍然可以用作表示模型,但该功能在视图范围内可能没有意义。视图确实更适合裸数据元素。控制器将与模型的功能交互。因此,您可能会创建一个在结构上类似于Album域模型的表示模型,它看起来就像您的示例中的那个。

展望未来,如果视图还需要其他数据怎么办?也许视图需要了解与Album. 修改域模型以适应视图是没有意义的。那是倒退。演示文稿应该围绕领域核心,而不是相反。因此,您可以向表示模型添加属性,这些属性是从控制器内部的其他事物中填充的。

所以你最终可能会得到这样的东西......

领域模型:

public class Album
{
    public int ID { get; private set; } // might need to be immutable

    private string _title;
    public string Title
    {
        get { return _title; }
        set
        {
            // don't allow empty titles
            if (string.IsNullOrWhiteSpace(value))
                throw new ArgumentNullException("Title");
            _title = value;
        }
    }

    private Album() { }
    public Album(int id, string title)
    {
        ID = id;
        Title = title;
    }

    public void Play()
    {
        // some implementation
    }

    public void SomeOtherMethod()
    {
        // some implementation
    }
}

随着业务领域的增长和变化,这个模型可能会随之改变。要点是它根据领域核心和业务逻辑的要求进行更改,而不是根据 UI 实现的要求进行更改。

使用此域核心的特定网站上的特定“页面”可能需要有关专辑的特定信息,并且可能还需要一些其他信息。您将定制一个演示模型以适应它:

public class AlbumViewModel
{
    public int ID { get; set; }
    public string Title { get; set; }
    public string Owner { get; set; }
    public IEnumerable<Listener> Listeners { get; set; }
    public string SomeCompletelyUnrelatedValueNeededByTheView { get; set; }
}

然后控制器将为视图构建这个表示模型:

public ActionResult Details(int id)
{
    // TODO: validate and sanitize any inputs

    var album = AlbumRepository.Get(id); // after all, why bind the UI _directly_ to the DB?  that's just silly
    var someOtherObject = SomeOtherRepository.Get(someOtherValueFromSomewhereElse);

    var albumVM = new AlbumViewModel
    {
        ID = album.ID,
        Title = album.Title,
        Owner = somethingElse.SomeValue,
        Listeners = someOtherObject.GetListeners(album),
        SomeCompletelyUnrelatedValueNeededByTheView = "foo"
    };

    return View(albumVM);
}

总体而言,这是一种更加手动的方法。当您有更复杂的域模型、与该域交互的多个复杂应用程序、整个域中的不同技术堆栈等时,它很有用。对于简单的表单数据应用程序,标准的 ASP.NET MVC 实现通常可以正常工作。它的大多数教程都反映了这一点,将多个职责合并到更少的对象中,使用装饰器而不是显式代码(假设全面使用相同的工具堆栈)等。

您正在查看的示例可以让您使用很少的代码非常快速地获得一个工作应用程序。与任何框架一样,如果您按照框架希望您做的方式做事,它就会很好地工作。如果您需要跳出框架的界限,您仍然可以以更抽象和与框架无关的方式维护该模式。


编辑:再次为您的更新...

在某种程度上,是的。ASP.NET MVC 是一个从总体上借鉴了 MVC 模式的框架。与所有事情一样,有不止一种方法可以做到这一点。坚持简单的实现和快速的应用程序,由 ASP.NET MVC 框架提供并在其各种教程中解释的功能是完全可以接受的,并且是使用框架的一个很好的例子......使用工具完成工作。

他们以所有最有意义的方式坚持这种模式。然而,与此同时,在框架的真实性质(通常超出模式描述的范围)中,它们试图为您提供使实际开发工作变得非常轻松的工具。如果您没有迫切需要将域模型与表示模型分开,则不必这样做。一个模型可以同时扮演这两个角色。如果您没有迫切需要将数据访问抽象为存储库模式,那么您不必这样做。您可以直接在模型中组合一些快速的实体框架功能并使用它来完成。

最终取决于项目的需求、开发人员的偏好等等。模式更学术,框架更实用。平衡两者是关键。

于 2012-07-24T20:41:57.463 回答
1

I guess the distinction is that in asp.net MVC you can have strongly typed views which have 'knowledge' of your model and the entity being passed through to the view. In its purest sense though the View shouldn't (or rather, neednt) have any knowledge of the model. For that reason I say Steven Sandersons example is better.

Fantastic book by he way!

于 2012-07-24T20:26:59.287 回答
0

我不会汗流浃背 - 斯蒂芬桑德森的图表显示的周期更少,但更详细。

我将 MS 文章箭头解释为:

  • 控制器填充模型(来自服务等)
  • 控制器指示查看
  • 视图通过绑定模型填充

尽管在我看来,微软图表并不是那么有用或信息丰富或有用。你同样可以争辩说箭头可以朝不同的方向前进——甚至像桑德森那样朝两个方向前进。例如,控制器还从绑定等接收模型。

桑德森箭头注释很好并且不言自明,这本书很棒。

于 2012-07-24T20:41:52.940 回答