将 ASP.Net Core 2 (.NET Framework) Web Api 拆分为类库和托管项目是否可能/明智?

2024-02-27

我正在尝试使用 Visual Studio 2017 (v15.4.5) 将现有的 WCF Web API(针对 .NET Framework 4.6.1)移植到 ASP.Net Core 2,但在找出组织项目的良好/通用/受支持的方法时遇到困难,以及它们应该是什么类型的项目。

例如:

  • 服务器和托管的单个项目,or用于托管的服务器和控制台应用程序的类库

  • 用于控制台应用程序的 Windows 经典桌面项目和用于服务器库的(新型 csproj)Web 应用程序,or两个 Web 应用程序(一个输出类库,另一个输出控制台应用程序)

我偷偷怀疑我缺少一些基本的东西,这意味着一种方法应该比其他方法更受青睐,甚至是强制性的,但发现很难从ASP.Net Core 2 文档 https://learn.microsoft.com/en-us/aspnet/core/.

具体要求

  • 应针对 .NET Framework 4.6.1
    由于我需要从 Web API 的内部访问 Windows 注册表,因此我的目标是 .NET Framework 4.6.1 而不是 .NET Core。

  • 使用 HTTP.sys 的主机
    我打算将来使用 Windows 身份验证,并相信 Kestrel 不会支持它(基于HTTP.sys 功能 https://learn.microsoft.com/en-us/aspnet/core/fundamentals/servers/httpsys).

  • 主机应作为 Windows 服务运行
    最终,Web API 应由 Windows Installer 安装并作为服务运行。
    目前,我只是想让 API 独立构建/正确工作,但也希望了解项目选择如何影响发布/部署的任何见解。

首选解决方案

虽然默认情况下,新的 ASP.NET Core 2 Web 应用程序是输出控制台应用程序的单个项目,但我更愿意将解决方案拆分为 2 个主要项目:

  • “服务器” - ASP.NET Core 2 (.NET Framework)类库包含Web API、控制器和Startup类的业务逻辑
  • “Host” - 引用“Server”并负责托管 Web API 的控制台应用程序

这种安排对我来说似乎很合适,因为任何单元/集成测试项目都可以引用“服务器”类库,而不是可执行文件(根据在 C# 项目中引用 exe 文件是一种不好的做法吗 https://stackoverflow.com/questions/22835635/is-it-a-bad-practice-to-reference-an-exe-file-in-c-sharp-project/22836012#22836012).

此外,我相信这是合理的,因为我可以在项目属性中将输出类型更改为“类库”。

我假设由于我的目标是 .Net Framework,只要我安装与“服务器”项目相同的 NuGet 包,“主机”项目就没有理由不能成为 Windows 经典桌面控制台应用程序。

是否存在任何隐藏的问题(可能与发布/部署相关)使得这种安排成为一个坏主意? 将托管项目设为 Web 应用程序(仍会引用服务器项目)是否有任何优势?

Attempt

以下是我用来尝试实现我喜欢的项目组织的步骤。虽然它有效,但我在构建过程中收到了生成的警告 - 见下文。

Server

  • 添加新项目“服务器”

    • 选择 Visual C#、Web、ASP.NET Core Web 应用程序

      在以下对话框中,目标为 .NET Framework、ASP.NET Core 2.0,然后选择 Web API

  • 将项目属性中的输出类型更改为“类库”
  • 删除程序.cs

Host

  • Add New Project "Host"
    • 选择 Visual C#、Windows 经典桌面、控制台应用程序 (.NET Framework)
  • 将 Program.cs 的内容替换为:

    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.Logging;
    using Server;
    
    namespace Host
    {
      internal class Program
      {
        private static void Main(string[] args)
        {
          BuildWebHost(args).Run();
        }
    
        private static IWebHost BuildWebHost(string[] args) =>
          new WebHostBuilder()
            .UseStartup<Startup>()
            .UseHttpSys(options =>
            {
              options.UrlPrefixes.Add("http://localhost:8080/");
            })
            .ConfigureLogging((hostingContext, logging) =>
            {
              logging.AddConsole();
              logging.AddDebug();
            })
            .Build();
      }
    }
    
  • 添加对服务器项目的引用

  • Install these NuGet packages
    • Microsoft.AspNetCore (2.0.1)
    • Microsoft.AspNetCore.Mvc (2.0.1)
    • Microsoft.AspNetCore.Server.HttpSys (2.0.2)
  • 设置为启动项目

问题:构建生成警告

该解决方案在调试中运行,并正确响应http://localhost:8080/api/values and http://localhost:8080/api/values/1, but构建解决方案后会显示以下警告:

Warning     The referenced component 'System.Security.Cryptography.Encoding' could not be found.    Host            
Warning     The referenced component 'System.Xml.XPath' could not be found. Host            
Warning     The referenced component 'System.IO.FileSystem.Primitives' could not be found.  Host            
Warning     The referenced component 'System.IO.FileSystem' could not be found. Host            
Warning     The referenced component 'System.Diagnostics.StackTrace' could not be found.    Host            
Warning     The referenced component 'System.Xml.XmlDocument' could not be found.   Host            
Warning     The referenced component 'System.Security.Cryptography.X509Certificates' could not be found.    Host            
Warning     The referenced component 'System.Diagnostics.FileVersionInfo' could not be found.   Host            
Warning     The referenced component 'System.Security.Cryptography.Algorithms' could not be found.  Host            
Warning     The referenced component 'System.Xml.ReaderWriter' could not be found.  Host            
Warning     The referenced component 'System.Security.Cryptography.Primitives' could not be found.  Host            
Warning     The referenced component 'System.ValueTuple' could not be found.    Host            
Warning     The referenced component 'System.Xml.XPath.XDocument' could not be found.   Host            
Warning     The referenced component 'System.IO.Compression' could not be found.    Host            
Warning     The referenced component 'System.AppContext' could not be found.    Host            
Warning     The referenced component 'System.Threading.Thread' could not be found.  Host            
Warning     The referenced component 'System.Console' could not be found.   Host            

如果这是一个合理的项目安排,为什么我会收到这些警告?


我们正在做类似的事情。我们的宿主是一个 .NET Framework 4.7.1 项目:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net471</TargetFramework>
    <IsPackable>true</IsPackable>
    <PlatformTarget>x86</PlatformTarget>
    <OutputType>Exe</OutputType>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <Prefer32Bit>false</Prefer32Bit>
  </PropertyGroup>

  <ItemGroup>
    <Folder Include="wwwroot\" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNet.WebApi.Core" Version="5.2.6" />
    <PackageReference Include="Microsoft.AspNetCore" Version="2.1.0" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.1.0" />
    <PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="2.1.0" />
    <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.1.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.1.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.1.0" />
    <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.1.0" />
    <PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="2.1.0" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.0" />
  </ItemGroup>

  <ItemGroup>
    <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\Business.csproj" />
    <ProjectReference Include="..\Apis.Shared.csproj" />
    <ProjectReference Include="..\Apis.Contracts.csproj" />
  </ItemGroup>

</Project>

而我们的库项目是NetStandard2.0:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugType>full</DebugType>
    <DebugSymbols>true</DebugSymbols>
  </PropertyGroup>

</Project>

Program.cs 看起来像这样:

public class Program
{
    public static void Main(string[] args)
    {
        var host = new WebHostBuilder()
            .UseKestrel()
            .ConfigureServices(services => services.AddAutofac())
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup<Startup>()
            .Build();

        host.Run();
    }

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .Build();
}

Startup.cs 看起来像这样:

public class Startup
{
    public Startup(IHostingEnvironment hostingEnvironment)
    {
        Settings = new AppSettings(hostingEnvironment);
    }

    public AppSettings Settings { get; private set; }

    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        services.AddMvc(); 
        services.AddOptions();      
        // any other services registrations...    

        var builder = new ContainerBuilder();           
        // all autofac registrations...
        builder.Populate(services);

        return new AutofacServiceProvider(builder.Build(););
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseMvc();
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 ASP.Net Core 2 (.NET Framework) Web Api 拆分为类库和托管项目是否可能/明智? 的相关文章

  • C# 异步任务比同步慢

    你知道为什么同步斐波那契方法比异步 等待更快并且比异步任务更快吗 我在每个项目方法上都使用了异步 所以主要是这是一个非常糟糕的方法 Code static int FibonacciSync int number if number 0 r
  • 如何使用c#从数据桶中获取所有文档?

    如何获取数据桶中的所有文档 我尝试过一个示例 但我只能获得一个特定的文档 这是我的代码 CouchbaseClient oclient oclient new CouchbaseClient vwspace data bucket name
  • 预编译头和 Visual Studio

    有没有办法设置 Visual Studio 解决方案参数 以便它只创建预编译头而不构建整个解决方案 具体来说 它是一个巨大的 C 解决方案 本身有许多项目 谢谢 仅选择 pch 创建者源文件 通常是 stdafx cpp 然后编译该文件 C
  • QSpinBox 输入 NaN 作为有效值

    我正在尝试扩展 QSpinBox 以能够输入 NaN 或 nan 作为有效值 根据文档 我应该使用 textFromValue valueFromText 和 validate 函数来完成此操作 但我无法让它工作 因为它仍然不允许我输入除数
  • 如何使用 CUDA/Thrust 对两个数组/向量根据其中一个数组中的值进行排序

    这是一个关于编程的概念问题 总而言之 我有两个数组 向量 我需要对一个数组 向量进行排序 并将更改传播到另一个数组 向量中 这样 如果我对 arrayOne 进行排序 则对于排序中的每个交换 arrayTwo 也会发生同样的情况 现在 我知
  • FluentAssertions ShouldNotThrow 无法识别异步方法/Func

    我正在尝试检查异步方法是否抛出具体异常 为此 我使用 MSTEST 和 FluentAssertions 2 0 1 我已经检查过这个关于 Codeplex 的讨论 http fluentassertions codeplex com wo
  • 原子存储抛出错误

    我最近升级到了 C 11 兼容编译器 并且尝试将一些代码从 boost 更新到 c 11 标准 我在使用atomic store转换一些代码时遇到了问题 这是一些简单的测试代码 似乎会引发编译器错误 int main std shared
  • 您认为 ASP.NET MVC 会与 ASP.NET Webforms 竞争吗?

    您认为 ASP NET MVC 会在 Microsoft Web 开发市场中占据重要份额吗 还是会占市场的 10 15 哦是的 它将让 Web 表单脱颖而出 我们已经看到了真正的 MVC 框架在 Java 世界中的价值 在 MS 世界中 这
  • 列表到优先队列

    我有一个 C 大学编程项目 分为两个部分 在开始第二部分时应该使用priority queues hash tables and BST s 我 至少 在优先级队列方面遇到了麻烦 因为它迫使我自己重做第一部分中已经实现的许多代码 该项目是关
  • 表单上的 KeyEvents 只能与 CTRL 结合使用

    Code Private Sub KeyHandling ByVal sender As Object ByVal e As System Windows Forms KeyEventArgs Handles Me KeyDown Sele
  • 如何禁用基于 ValidationRule 类的按钮?

    如何禁用基于 ValidationRule 类的 WPF 按钮 下面的代码可以很好地突出显示 TextBox
  • 在特定线程上运行工作

    我想要一个特定的线程 任务队列并在该单独的线程中处理任务 应用程序将根据用户的使用情况创建任务并将其排队到任务队列中 然后单独的线程处理任务 即使队列为空 保持线程活动并使用它来处理排队任务也至关重要 我尝试过几种实现TaskSchedul
  • 如何释放字符串未使用的容量

    我正在程序中处理很多字符串 这些字符串数据在读入我的程序后的整个生命周期内都不会改变 但由于 C 字符串保留了容量 因此浪费了大量肯定不会被使用的空间 我尝试释放这些空间 但没有成功 以下是我尝试过的简单代码 string temp 123
  • 如何重用具有稍微不同的 ProcessStartInfo 实例的 Process 实例?

    我有以下开始的代码robocopy https technet microsoft com en us library cc733145 aspx as a Process 我还需要进行数据库查询以确定每次需要复制哪些目录robocopy被
  • 基础设施 - 同步和异步接口和实现? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 在实现库 基础设施时 并且该 API 的用户希望同步和异步使用代码 我读到混合同步和异步并不是一个好主意 例如 同步实现包括等待异步实现 显然
  • 如何通过代理将套接字连接到http服务器?

    最近 我使用 C 语言编写了一个程序 用于连接到本地运行的 HTTP 服务器 从而向该服务器发出请求 这对我来说效果很好 之后 我尝试使用相同的代码连接到网络上的另一台服务器 例如 www google com 但我无法连接并从网络中的代理
  • Unity - 在生成时获取随机颜色

    我有一个小问题 我想在我的场景中生成四边形 它们都应该有红色或绿色作为材质 但 Random Range 函数只能是 int 我该如何解决它 void SpawningSquadsRnd rndColor 0 Color red rndCo
  • 强制函数调用的顺序?

    假设我有一个抽象基类 并且我想要一个必须由派生类实现的纯虚方法 但我想确保派生方法以特定顺序调用函数 我可以做什么来强制执行它 I E base class virtual void doABC 0 virtual void A 0 vir
  • 在 LP2844Z(Zebra 打印机)上的收据中包含 PNG [重复]

    这个问题在这里已经有答案了 我正在致力于创建一个基于 HTML5 画布的签名 绘图框 目前我们在服务器上将画布保存为PNG 但可以轻松地将base64字符串保存在数据库中 现在的问题是我们如何在打印的收据上添加签名 目前我们使用 GF 字段
  • 创建进程默认浏览器

    我目前正在使用 ShellExecute 打开 在用户浏览器中打开 URL 但在 Win7 和 Vista 中遇到了一些麻烦 因为该程序作为服务运行提升 我想获取线程 id 因此 ShellExecute 无法获取线程 id 因此我开始使用

随机推荐