jjzjj

c# - ASP.NET MVC 大型项目架构

coder 2024-05-21 原文

关闭。这个问题是opinion-based .它目前不接受答案。












想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题.

8年前关闭。




Improve this question




这是一个与如何为大中型应用程序构建 ASP.NET MVC 项目相关的问题。

我以为我理解了 MVC 的概念,但在研究了大中型应用程序的架构后,我感到很困惑。 (尝试考虑可扩展性、可扩展性和持续维护)

当我试图按照“最佳实践”(来自包括打印和网络在内的众多来源)的指导方针来思考如何构建应用程序时,我感到困惑

试图尊重诸如

  • Controller 应该保持非常简单
  • TDD 原则(或至少是一种使 future 测试更容易的方法)
  • 关注点分离
  • 服务和存储库
  • 依赖注入(inject)

  • 现在,当创建小型(基本的、简单的)MVC 应用程序时,所有这些几乎都在同一个项目中完成(在这种情况下我指的是 Visual Studio 项目),并且 MVC“层”之间的分离几乎是只是 VS 项目中的文件夹(完全独立的命名空间)。

    对于我们的其他一些项目,我们采用了服务 -> 存储库样式,因此这个样式不会有任何不同。

    我们使用 Entity Framework 作为数据库持久性(数据库优先方法)。

    我们已将我们的数据库访问(EF 内容)分离到另一个 VS 项目中,因此我们在解决方案中有一个 Web 项目和模型(或数据)项目。

    web 项目有 Controller 和 View ,数据项目有服务、存储库和 EF 的东西。

    我的困惑在于模型(或者可能是理解域模型与 View 模型)

    如果我尝试遵循该方法(我认为),我将拥有一个域模型(EF 和存储库层处理的模型),然后我将拥有一个 View 模型? ( Controller 和 View 将处理的模型),现在这些不是 90% 相同吗?这种分离关注点的方式不是只会让您编写模型代码两次吗?我确信我在某处读到过 Controller 和 View 不应该具有域模型?

    我们处理它的一种方法是 EF 使其所有模型类都是部分的。然后我们扩展同一个类并向它添加一个 MetaDataType 类以创建“ View 模型”(将 DataAnnotations 添加到属性),然后本质上相同的模型通过所有层,但这是“最佳”实践吗(有在我看来这是不对的)

    例如
    [MetadataType(typeof(Product_Metadata))]
    public partial class Product
    {
        //Pretty much deliberately kept empty, just so
        // the EF model class can have the attribute added
        //The other side of this partial class is of course in the EF models
    }
    
    public class Product_Metadata
    {
        [Required]
        [Display(Name = "Product name")]
        public string Name { get; set; }
    
        [Required]
        [Display(Name = "Unit Cost")]
        public decimal Cost { get; set; }
    
        //etc... for the rest of the properties on the product EF model
    }
    

    也许这是攻击它的“最佳”方式,但我以前从未遇到过这种方法。

    我们将所有服务和存储库创建为接口(interface),并使用结构映射作为 IoC 容器。我承认的另一件事,即使我们正在使用依赖注入(inject),我仍然在努力接受 TDD,感觉必须将所有内容都写两次(我认为是 DI 的全部内容)

    我想最终我会吸引那些在 SO 中比我更了解架构大型 ASP.NET MVC 应用程序的人,以获得一些帮助和指导。那里似乎有大量信息,但所有信息似乎都非常概念化。当我最终开始实现时,我迷失在概念中。

    编辑

    回应卡尔·安德森先生
  • View 中的数据分页 - 是的,完全同意这是 View 模型相关且有意义的地方,但同样是具有 List 属性的 CategoryListViewModel,它是 View 模型类别的列表还是域模型类别
  • 批量分配漏洞 - 我认为这个漏洞会存在于域模型或 View 模型中(毕竟如果真的需要设置,你将如何设置 IsAdmin,它肯定仍然会在 ViewModel 上)。我认为这需要在不同的层处理,即授权,以便仅使用窗帘角色只能设置 IsAdmin
  • 以特定格式显示 View 信息 - 当然,这只是与模型绑定(bind)和/或 View html 格式帮助程序有关 - 即仅存在 View 和模型绑定(bind)问题。毕竟,所有通过 View 渲染的模型,其属性都以 html 结尾并且此时都是字符串,因此无论如何都必须解析返回值,这是模型绑定(bind)的主要原则,所以如果我需要自定义一个,只需编写一个新的模型活页夹。
  • 将您的领域模型用作不仅仅是数据传输对象 (DTO) - 我实际上尽可能地避免这种情况,试图坚持模型正是 DTO 的事实。但是如果出现这种情况,我可能会在域模型上编写一个扩展方法,毕竟所有方法都不会被序列化,或者添加一个 View 模型但它可能包含一个域模型
  • 对同一领域模型信息有不同的抽象 - 部分同意。我会有一个 PagedAccountListViewModel(仍将包含域模型),但我只会为新帐户和更新帐户使用一个模型(我将新帐户视为更新,只是预先填充的),它将是域模型
  • 最佳答案

    When I finally come to the implementation I get lost in the concepts.



    这些概念非常重要,但也很抽象。很难想象在完成之前如何最好地构建您的解决方案(即为时已晚),而且没有人能真正告诉您如何构建它,因为每个项目都如此不同。

    I would have a domain model [...] and then I would have a view model? [...] wouldn't these be 90% the same?



    我相信这没问题。域模型描述实际对象(通常来自数据库)。 View 模型描述了 View 正确渲染所有内容所需的信息。两者通常都不包含逻辑,只包含一个属性列表。我认为这些几乎相同是可以的。使用 Automapper轻松地在模型之间进行映射。

    Controllers and Views shouldn't have the Domain model?



    大多数开发人员更喜欢这种方法,是的。我也是。应该给 View 一个 View 模型,如果需要, Controller 可以简单地在模型之间进行映射。

    EF makes all its model classes partial. We then extend that same class and add a MetaDataType class to it to make the 'View Model'



    这是一个有趣的方法,但我不能推荐它。复制模型是可以接受的。

    TDD, feels like to have to write everything twice



    是的,它可以。您采用的方法将抽象和实现分开了很多。它确实让人感觉有更多的东西要写,但它也更容易理解。特别是因为您与接口(interface)而不是实现进行通信。

    I am appealing [...] for some assistance and guidance


  • 虽然你提到了 TDD,但我不记得你提到过 onion architecture .请务必通读 The Onion Architecture作者:杰弗里·巴勒莫
  • watch Put your controllers on a diet通过吉米博加德。
  • 查看一些现有的示例解决方案,例如 EFMVCCodeCampServer .
  • 关于c# - ASP.NET MVC 大型项目架构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18648972/

    有关c# - ASP.NET MVC 大型项目架构的更多相关文章

    1. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

      如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

    2. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

      我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

    3. ruby-on-rails - 新 Rails 项目 : 'bundle install' can't install rails in gemfile - 2

      我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="

    4. c# - 如何在 ruby​​ 中调用 C# dll? - 2

      如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

    5. Ruby 从大范围中获取第 n 个项目 - 2

      假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit

    6. C# 到 Ruby sha1 base64 编码 - 2

      我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

    7. 基于C#实现简易绘图工具【100010177】 - 2

      C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

    8. ruby - 在 ASP 页面上 Mechanize 中断 - 2

      require'mechanize'agent=Mechanize.newlogin=agent.get('http://www.schoolnet.ch/DE/HomeDE.htm')agent.clicklogin.link_withtext:/Login/然后我得到Mechanize::UnsupportedSchemeError。 最佳答案 Mechanize不支持javascript但您可以将搜索字段添加到表单并为其分配搜索词并使用mechanize提交表单form=page.forms.firstform.add_fie

    9. ruby - 如何在 Ruby 字符串中插入项目符号字符? - 2

      我正在尝试创建一个带有项目符号字符的Ruby1.9.3字符串。str="•"+"helloworld"但是,当我输入它时,我收到有关非ASCII字符的语法错误。我该怎么做? 最佳答案 你可以把Unicode字符放在那里。str="\u2022"+"helloworld" 关于ruby-如何在Ruby字符串中插入项目符号字符?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/1195

    10. ruby - 在 Rails 项目中测试本地版本的 gem - 2

      我的Rails站点使用了一个确实不是很好的gem。每次我需要做一些新的事情时,我最终不得不花费与向实际Rails项目添加代码一样多的时间来为gem添加功能。但我不介意,我将我的Gemfile设置为指向我的gem的GitHub分支(我尝试提交PR,但维护者似乎已经下台)。问题是我真的没有找到一种合理的方法来测试我添加到gem的新东西。在railsc中测试它会特别好,但我能想到的唯一方法是a)更改~/.rvm/gems/.../foo。rb,这看起来不对或者b)升级版本,推送到Github,然后运行​​bundleup,这除了耗时之外显然是一场灾难,因为我不确定我所做的promise是否正

    随机推荐