简体   繁体   中英

Is it possible/sensible to split ASP.Net Core 2 (.NET Framework) Web Api into Class Library and Hosting projects?

I'm trying to port an existing WCF Web API (targeting .NET Framework 4.6.1) to ASP.Net Core 2 using Visual Studio 2017 (v15.4.5) and am having trouble figuring out good/common/supported ways to organize projects, and what types of project they should be.

For example:

  • Single project for Server and Hosting, or Class Library for Server and Console application for Hosting

  • Windows Classic Desktop project for Console application and (new style csproj) Web Application for Server library, or both Web Applications (one outputting a Class Library, the other a Console Application)

I have the sneaking suspicion that there is something fundamental that I'm missing which means that one approach should be favoured over the others, or is even mandatory, but have found it hard to discover this from the ASP.Net Core 2 documentation .

Specific Requirements

  • Should target .NET Framework 4.6.1
    Since I need to access the Windows Registry from the internals of the Web API, I am targeting .NET Framework 4.6.1 rather than .NET Core.

  • Host using HTTP.sys
    I intend to use Windows Authentication in future and believe that Kestrel will not support that (Based upon HTTP.sys features ).

  • Host should run as a Windows Service
    Ultimately, the Web API should be installed by Windows Installer and run as a service.
    For the moment, I'm just trying to get the API to build/work correctly stand-alone, but would also appreciate any insight into how the choice of projects might affect publishing/deployment.

Preferred Solution

Whilst, by default, a new ASP.NET Core 2 Web Application is a single project outputting a Console Application, I would prefer to split the solution into 2 main projects:

  • "Server" - An ASP.NET Core 2 (.NET Framework) Class Library containing the business logic of the Web API, controllers and Startup class
  • "Host" - Console application which references "Server" and is responsible for hosting the Web API

This arrangement seems appropriate to me since any unit/integration test projects can reference the "Server" class library, not an executable (according to advice in Is it a bad practice to reference an exe file in C# project ).

Furthermore, I'm led to believe this is reasonable because I can change the Output Type to "Class Library" in the project properties.

I'm assuming that since I'm targeting the .Net Framework, so long as I install the same NuGet packages as the "Server" project, there is no reason why the "Host" project cannot be a Windows Classic Desktop Console application.

Are there any hidden issues, perhaps relating to publishing/deployment, that make this arrangement a bad idea? Would there be any advantage to making the Hosting project a Web Application (which would still reference the Server project)?

Attempt

Here are the steps I used to try to achieve my preferred project organization. Whilst it works, I get warnings generated during the build - see below.

Server

  • Add New Project "Server"

    • Choose Visual C#, Web, ASP.NET Core Web Application

      In the following dialog, target .NET Framework, ASP.NET Core 2.0, and choose Web API

  • Change Output Type in Project properties to "Class Library"
  • Delete Program.cs

Host

  • Add New Project "Host"
    • Choose Visual C#, Windows Classic Desktop, Console App (.NET Framework)
  • Replace contents of Program.cs with:

     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(); } } 
  • Add a reference to the Server project

  • Install these NuGet packages
    • Microsoft.AspNetCore (2.0.1)
    • Microsoft.AspNetCore.Mvc (2.0.1)
    • Microsoft.AspNetCore.Server.HttpSys (2.0.2)
  • Set as Startup Project

Problem: Build generates warnings

This solution runs under debugging, and responds correctly to http://localhost:8080/api/values and http://localhost:8080/api/values/1 , but the following warnings are shown after building the solution:

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            

If this is a reasonable arrangement of projects, why am I getting these warnings?

We are doing something similar. Our host is a .NET Framework 4.7.1 project:

<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>

And our library projects are 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 looks like this:

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 looks like this:

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();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM