【问题标题】:Merging a common project with build variations in .NET MVC将通用项目与 .NET MVC 中的构建变体合并
【发布时间】:2017-12-05 13:32:52
【问题描述】:

我有一个 .net mvc 站点,该站点应该发布给许多不同的客户,因此会根据目标略有不同。

有什么方法可以设置核心项目结构,例如(简化):

  • 观看次数
  • 型号
  • 控制器
  • 资产
  • bin

并在构建时与当前目标可能具有的任何变化进行合并。例如:

核心项目:

  • 查看次数
    • view1.cshtml
    • view2.cshtml

(为简洁起见,删除了其余文件夹)

客户 1 目标:

  • 查看次数
    • view2.cshtml
    • view3.cshtml

想要的合并结果:

  • 查看次数
    • view1.cshtml(来自核心项目)
    • view2.cshtml(来自客户 1 目标)
    • view3.cshtml(来自客户 1 目标)

同样的规则应该适用于控制器、二进制文件等。

【问题讨论】:

  • 反对者,愿意发表评论吗?
  • 为每个客户维护不同版本的应用程序听起来会导致各种各样的问题。为什么不拥有单一版本的应用程序并根据设置启用/禁用功能?
  • @David 这在一定程度上可行,但如果客户只想要几个与他相关的视图怎么办?我更愿意将这些视图保留在仅与该客户相关的项目中,并且仅在我针对该特定客户时交付它们,而不是使用功能切换。
  • 如果你真的想做这样的事情,你应该将客户特定的功能作为核心系统的插件。我的两分钱。
  • 支持实际问题:)

标签: c# asp.net-mvc


【解决方案1】:

我要么使用多个项目、nuget,要么使用源代码管理。我将在下面讨论这些想法,但没有特别的顺序。到最后,我可能会包含对其中一个或另一个的偏好。

我要讨论的第一个想法是使用多个项目。创建你的基础项目,我们称之为 WebBase。创建您谈到的核心网站。接下来创建 Customer1 网站,如果将 Customer1 创建为空网站,则需要在 WebBase 中重新创建文件夹结构,或者您可以像使用 WebBase 一样创建它并删除所有文件(在 Visual Studio 中执行此操作);无论哪种方式,您最终都会得到没有文件的文件夹结构。我建议保留 web.config、packages.config、Properties 文件夹和 AssemblyInfo.cs。然后您将从 WebBase 添加文件,但不要只是正常添加它们。为了说明的目的,让我们做 Home Index View:展开 Customer1 中的 Views 文件夹,右键单击 home,选择 add,选择 Exising Item,浏览 Customer1,然后进入 WebBase/Views/Home 并单击 index.cshtml,现在注意到按钮上的下拉菜单了吗?单击它并选择“添加为链接”。现在对 WebBase 中的所有文件执行此操作!每次选择“添加为链接”似乎很麻烦,但是如果您只是单击添加,它将复制文件并且更新不会从 WebBase 传播到 Customer1!此外,您还会看到从项目中删除与删除(提示永久删除)等内容。

第二个想法是为 WebBase 创建一个 nuget 包,然后您可以将其安装为一个包,这种方法的好处是版本控制,并且不需要您对每个小改动都更新每个项目。它将使每个项目完全隔离。不利的一面是您需要单独更新每个项目以在全球范围内传播更改。您需要了解 nuget 的 nuspec 文件以及如何包含文件等。没那么糟糕,它只是 XML。但是您可以指明在安装/更新软件包时要包含哪些文件。

第三个是源代码控制,我知道使用 git 你可以使用子模块来包含一个单独的项目(甚至来自外部存储库)。这可能是一个选项,或者您可以创建一个 WebBase 分支,设置 WebBase,然后将其分支到每个客户的网站。于是创建一个叫Customer1的分支,开始添加自定义客户的东西。切换回 WebBase,创建一个名为 Customer2 的新分支……您就可以参加比赛了。切换回 WebBase,进行全局更改,然后将这些更改合并到 Customer1 和 Customer2 分支。

好吧,我承认,我可能会选择第三个选项。它给你带来很多好处而几乎没有缺点。它甚至可以给你历史!如果您当前没有使用源代码控制...您应该这样做!您可以在您的机器上安装 git 并能够在本地签入代码,并且您不必担心外部存储库(尽管我建议您拥有一个,因为它可以为您提供 DR)。

无论哪种方式,都有可用的选项。但没有什么能比得上一个包含可配置文件的单个项目了。

祝你好运!

【讨论】:

    【解决方案2】:

    首先想到的(可能是最简单的,因为它不需要任何额外的工具)是创建具有核心功能、视图和控制器的核心项目。并为每个客户创建带有自定义视图和控制器的单独项目。然后对于客户特定的项目,只需从核心项目链接所有必需的文件。根据数量链接文件可能有点乏味,但似乎可行。

    另一种方法是使用CAKEFAKE 之类的工具,借助这些工具,您可以按照自己的方式编写整个构建过程的脚本,但我从未尝试过自己编写此类自定义脚本。

    我也可以使用的第三个选项是根据定义的常量有条件地包含文件,但这需要编辑 *.csproj 文件。代码可以是这样的:

    <Content Include="Views\View1.cshtml" />
    <Content Include="Views\View2.cshtml" Condition="$(DefineConstants.Contains('CORE'))" />
    <Content Include="Views\View2.cshtml" Condition="$(DefineConstants.Contains('CUSTOMER1'))" />
    <Content Include="Views\View3.cshtml" Condition="$(DefineConstants.Contains('CORE'))" />
    <Content Include="Views\View3.cshtml" Condition="$(DefineConstants.Contains('CUSTOMER1'))" />
    

    但不确定维护它有多容易。

    我可能会考虑将应用程序拆分为独立的组件/项目,这些组件/项目将包含与组件相关的所有功能。在构建过程中,根据特定客户端所需的组件,使用 FAKE 组合组件。

    【讨论】:

    • 我也考虑过链接。但是一旦我将一个新文件添加到核心项目中,它就需要手动链接到所有子项目,对吧? AFAIK,没有办法自动化
    • @filur,好吧,链接只是 csproj 文件中的一个标签。您可能可以创建一个工具甚至 VS 扩展,在创建/删除文件时自动创建/删除链接。
    • 我创建了一个扩展程序,用于跟踪文件之前用于不同目的bitbucket.org/andrii-litvinov/hgfiletracker。我相信你可以找到更多的例子。但这个问题似乎还是有点复杂。
    • 好吧,因为我们正在处理大约 50 个项目,所以为每个新文件手动添加链接对我来说不是一个选项 :)
    • @filur,如果您决定朝这个方向发展,请自动化 :)。但正如我在回答中提到的那样,我会使用定义明确的组件并为每个客户端配置这些组件。可以在每个客户端的组合根目录中的任一 DI 级别上完成,也可以在部署期间作为 CI 配置完成,具体取决于实现。
    【解决方案3】:

    您的要求非常适合自定义 Visual Studio 项目模板。

    我正在考虑准备一个包含您要部署给任何客户的所有功能的大型项目。该项目也可以是您在需要新功能或修复时更新的主干。然后,export the trunk-solution into a template。然后继续使用VSIX project templateincorporate a wizard 来收集用户对项目创建的输入。根据输入采取适当的操作并根据需要添加/删除必要的文件或启用/禁用功能。

    或者您可能只是将源文件保留在文件系统上,并在运行中将它们组织到模板中 - 即,作为向导期间用户输入的结果。在向导结束时,模板被部署并且......瞧。

    【讨论】:

      【解决方案4】:

      您需要的是超级管理员部分,您可以在其中[停用]网站的不同部分,具体取决于客户。

      【讨论】:

      • 恐怕随着客户数量的增长,功能切换将成为维护地狱
      • 应该是评论。
      • @filur 但这是正确的方法。所有功能 x 客户只是复选框的二维矩阵。这是您在构建 ERP 或 CMS 时会采用的一种方法。完全适合您的情况的工具。
      【解决方案5】:

      这里有一些非常好的代码答案,但如果您想要为每个客户提供一个自动构建系统并且您有负载,那么设置它们也可能会很痛苦。 什么时候可以为 Powershell 设置一个可以执行此操作的脚本

      伪代码

      For each client site
          download base code to code/
          download this client's changes to code/ overwriting files
          msbuild ....
          copy client/ bin to build/client/
          Delete code/
      End For each
      

      【讨论】:

        【解决方案6】:

        这个问题的答案需要一些创新。所以请看我的解决方案:

        为涵盖 ModelController 文件的类设置核心项目结构,然后使用它们使用名为Add Existing Item As a Link 的技术,可以共享以下内容:

        • 两个应用通用的应用逻辑,但不可移植
        • 不依赖平台的用户控件

        很遗憾,剃刀视图不支持该功能。因此,复制共享视图最简单的方法是拥有多个布局文件,例如著名的 _Layout.cshtml 文件,每个 Web 应用程序中都有一个。您也可以Compile your asp.net mvc Razor views into a separate dll 将它们用作参考(作为共享视图)。

        对于 Assets,您可以从主 Web 应用程序托管所有样式表(如果合适,还可以托管一些 javascript),并从每个 Web 应用程序访问它。 p>

        bin 文件夹包含核心 MVC dll 文件以及您添加以在项目中使用的文件以及将在构建后创建的 projectName.dll 文件。您可以通过使用添加引用工具右键单击引用来简单地添加/删除它们。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-23
          • 1970-01-01
          • 2021-03-31
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多