首页 > 解决方案 > F# docker 应用程序:标有“EntryPointAttribute”属性的函数必须是最后一个文件中的最后一个声明......?

问题描述

通过从头开始创建一个新项目,可以轻松地重现该问题。

Visual Studio 版本为 V15.7.5。我创建了一个新的 F# .Net core 2.1 应用程序,支持 docker (Linux)。但是,它得到了以下错误。

标有“EntryPointAttribute”属性的函数必须是编译序列中最后一个文件中的最后一个声明。

以下是Dockerfile.

FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 64890
EXPOSE 44390

FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY WebApplication8/WebApplication8.fsproj WebApplication8/
RUN dotnet restore WebApplication8/WebApplication8.fsproj
COPY . .
WORKDIR /src/WebApplication8
RUN dotnet build WebApplication8.fsproj -c Release -o /app

FROM build AS publish
RUN dotnet publish WebApplication8.fsproj -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "WebApplication8.dll"]

以下是Program.fs

namespace WebApplication8

open System
open System.Collections.Generic
open System.IO
open System.Linq
open System.Threading.Tasks
open Microsoft.AspNetCore
open Microsoft.AspNetCore.Hosting
open Microsoft.Extensions.Configuration
open Microsoft.Extensions.Logging

module Program =
    let exitCode = 0

    let CreateWebHostBuilder args =
        WebHost
            .CreateDefaultBuilder(args)
            .UseStartup<Startup>();

    [<EntryPoint>]
    let main args =
        CreateWebHostBuilder(args).Build().Run()
        exitCode

.fsproj

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

  <PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <DockerComposeProjectPath>..\docker-compose.dcproj</DockerComposeProjectPath>
    <UserSecretsId>b379991e-83d8-444e-b888-62e9ac139864</UserSecretsId>
  </PropertyGroup>

  <ItemGroup>
    <Compile Include="Controllers/ValuesController.fs" />
    <Compile Include="Startup.fs" />
    <Compile Include="Program.fs" />
  </ItemGroup>

  <ItemGroup>
    <None Include="Dockerfile" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>

</Project>

完全错误,

1>----- 构建开始:项目:docker-compose,配置:调试任何 CPU ------
1>docker ps --filter "status=running" --filter "name=dockercompose15479956486365536117_webapplication8_" --format {{.ID}} -n 1
1>e95714bd0022
1>docker exec -i e95714bd0022 /bin/bash -c “如果 PID=$(pidof -x dotnet); 然后杀死 $PID;fi”
1>c:\source\repos\WebApplication8\WebApplication8\WebApplication8.fsproj:警告 NU1701:使用 '.NETFramework,Version=v4.6.1' 而不是项目目标框架恢复了包 'System.Linq.Queryable 4.0.1' '.NETCoreApp,版本 = v2.1'。此软件包可能与您的项目不完全兼容。
1>c:\source\repos\WebApplication8\WebApplication8\Program.fs(22,9):错误 FS0433:标有“EntryPointAttribute”属性的函数必须是编译序列中最后一个文件中的最后一个声明。
1>完成构建项目“WebApplication8.fsproj”——失败。
========== 构建:0 成功或最新,1 失败,0 跳过 ==========

VS生成的start.fs

namespace WebApplication8

open System
open System.Collections.Generic
open System.Linq
open System.Threading.Tasks
open Microsoft.AspNetCore.Builder
open Microsoft.AspNetCore.Hosting
open Microsoft.AspNetCore.HttpsPolicy;
open Microsoft.AspNetCore.Mvc
open Microsoft.Extensions.Configuration
open Microsoft.Extensions.DependencyInjection

type Startup private () =
    new (configuration: IConfiguration) as this =
        Startup() then
        this.Configuration <- configuration

    // This method gets called by the runtime. Use this method to add services to the container.
    member this.ConfigureServices(services: IServiceCollection) =
        // Add framework services.
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1) |> ignore

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    member this.Configure(app: IApplicationBuilder, env: IHostingEnvironment) =
        if (env.IsDevelopment()) then
            app.UseDeveloperExceptionPage() |> ignore
        else
            app.UseHsts() |> ignore

        app.UseHttpsRedirection() |> ignore
        app.UseMvc() |> ignore

    member val Configuration : IConfiguration = null with get, set

VS生成的value.fs

namespace WebApplication8.Controllers

open System
open System.Collections.Generic
open System.Linq
open System.Threading.Tasks
open Microsoft.AspNetCore.Mvc

[<Route("api/[controller]")>]
[<ApiController>]
type ValuesController () =
    inherit ControllerBase()

    [<HttpGet>]
    member this.Get() =
        let values = [|"value1"; "value2"|]
        ActionResult<string[]>(values)

    [<HttpGet("{id}")>]
    member this.Get(id:int) =
        let value = "value"
        ActionResult<string>(value)

    [<HttpPost>]
    member this.Post([<FromBody>] value:string) =
        ()

    [<HttpPut("{id}")>]
    member this.Put(id:int, [<FromBody>] value:string ) =
        ()

    [<HttpDelete("{id}")>]
    member this.Delete(id:int) =
        ()

标签: visual-studiodockerf#.net-core

解决方案


.fsproj 中的 UserSecretsId 标记导致了问题,因为 .net 核心编译器在错误的位置为其生成代码。解决方案是删除标签并将其添加到单独的 assemblyinfo.fs 文件中:

module Your.Namespace.AssemblyInfo

open Microsoft.Extensions.Configuration.UserSecrets

[<assembly: UserSecretsIdAttribute(“b379991e-83d8-444e-b888-62e9ac139864”)>]

do()

有关问题和解决方法的更详细描述,请参阅本文:使 ASP.NET Core 用户机密在 F# 项目中工作


推荐阅读