Asp.net mvc 为什么模型、视图和控件之间的交互看起来不同?

Asp.net mvc 为什么模型、视图和控件之间的交互看起来不同?,asp.net-mvc,Asp.net Mvc,我是ASP.NET MVC新手,正在尝试学习基本知识。 我现在试图学习模型、视图和控制器之间的关系 这三者之间的互动看起来不同,为什么?(看箭头) 资料来源1: 资料来源2(第65页): 如果你能帮我解决我的困惑,我会很高兴的 谢谢 编辑: 你的意思是mvc可以以不同的方式实现? (仍在询问asp.net mvc,而不是一般的mvc) 我一直在看报纸 看起来是这样的。 控制器: public ActionResult Details(int id) { var album

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

这三者之间的互动看起来不同,为什么?(看箭头)

资料来源1:

资料来源2(第65页):

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

谢谢

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

我一直在看报纸 看起来是这样的。 控制器:

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中的版本是很好的。

我想区别在于,在asp.net MVC中,您可以拥有强类型视图,这些视图“了解”您的模型和传递到视图的实体。从最纯粹的意义上讲,视图不应该(或者更确切地说,不需要)对模型有任何了解。因此,我认为史蒂文·桑德森的例子更好


顺便说一句,这本书太棒了

我不会担心的——斯蒂芬·桑德森的图表显示的周期更少,但更详细

我将MS文章箭头解释为:

  • 控制器填充模型(来自服务等)
  • 控制器指向视图
  • 视图通过绑定模型填充
在我看来,微软的图表并没有那么有用、信息丰富或有用。你同样可以说箭头可以指向不同的方向——甚至像桑德森的箭头一样指向两个方向。例如,控制器还从binding等接收模型


Sanderson箭头注释得很好,并且是自显式的,这本书很棒。

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

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

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

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

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

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


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

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

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

展望未来,如果视图还需要其他数据,该怎么办?也许视图需要了解与
相册
不属于同一聚合的其他模型。修改域模型以适应视图是没有意义的。这是倒退。演示文稿应该围绕域展开
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
    }
}
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);
}