iT邦幫忙

0

Net Core 2.0 - 在 TargetFramework 為 netcoreapp2.2 下時,無法取得引用(外部)組件的 Controller 類別

最近遇到一個奇怪的問題,假設我有一個主要的 Web 專案名稱 Test.Web,它的專案檔內容如下:

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

  <PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>
    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\TestWeb.Infrastructure\TestWeb.Infrastructure.csproj" />
  </ItemGroup>

</Project>

這邊可以看到他引用了一個外部專案名稱為 TestWeb.Infrastructure,然後它的專案檔內容如下:

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

  <PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>
  </PropertyGroup>

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

接著我在 TestWeb.Infrastructure 專案下建立一個 Class 名稱為 TestController 並放置一個名為Fire 的 Action 如下:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace TestWeb.Infrastructure.Controllers
{
    public class TestController : Controller
    {
        [HttpGet]
        public async Task<IActionResult> Fire()
        {
            return Content("Hello!!!!!");
        }
    }
}

一切設置好後啟動專案 Test.Web 並發了一個 request 到 https://localhost:5001/Test/Fire,我得到的回應為 404 找不到網頁(神奇了..我在 2.1 時沒遇過),所以我亂試了一陣子後發現如果我在專案 TestWeb.Infrastructure 的專案檔裡對 Microsoft.AspNetCore.App 添加 Version="2.2.0" 後,如以下:

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

  <PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>
  </PropertyGroup>

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

重新跑ㄧ次網站再 request ㄧ次 https://localhost:5001/Test/Fire,疑!? 竟然可以得到正常的回應 Hello!!!!!,但如果 Version 的參數改成 2.2.1、2.2.2、2.2.3 後,則會出現編譯失敗(NU1605),看起來只有在對 Microsoft.AspNetCore.App 設置成版本為2.2.0 才能達到我預期的回應

是我有漏掉什麼還是 TargetFramework 升級成 netcoreapp2.2 後有什麼設定才造成此問題的? 我目前使用的 SDK 為 2.2.105,我有試過2.2.104 也是一樣會有此問題,我這邊也建立了一個範例,連結為 https://github.com/linmasaki/TestWeb/tree/master

這邊付上我在 Debug 時,發現的一些差異點,如果加上 Version=2.2.0 時,主專案內外總共可以取到20個組件(ApplicationParts數量)
https://ithelp.ithome.com.tw/upload/images/20190314/20116165nOYseh8kRF.jpg

但如果移除 Version=2.2.0 後,則只剩下 10 個(即只剩下主專案自己的 Class 了)
https://ithelp.ithome.com.tw/upload/images/20190314/201161655VbvrzsHAA.jpg

1 個回答

1
暐翰
iT邦大師 1 級 ‧ 2019-03-15 11:35:59

我目前測試真的有這問題,添加版本號可以跑應該不是正常解決方式,因為vs提示這不是建議方式

警告	NETSDK1071	A PackageReference to 'Microsoft.AspNetCore.App' specified a Version of `2.2.0`. Specifying the version of this package is not recommended. For more information, see https://aka.ms/sdkimplicitrefs	TestWeb.Infrastructure	C:\Program Files\dotnet\sdk\2.2.103\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.DefaultItems.targets	153	

我幫你發問在S.O跟.NET FB社群看那邊有沒有高手可以解


更新S.O大大們的解決方式

因為沒有添加Microsoft.AspNetCore.MVC,cspoj改成以下就可以

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App"/>
    <PackageReference Include="Microsoft.AspNetCore.MVC" />
  </ItemGroup>
</Project>

假如不想要添加Microsoft.AspNetCore.MVC,可以在Web專案使用

service.AddMvc().AddApplicationPart(typeof(HomeController).Assembly);
看更多先前的回應...收起先前的回應...
linmasaki iT邦新手 5 級 ‧ 2019-03-15 12:57:22 檢舉

嗯嗯,非常感謝您的幫忙及測試,事實上我也有再S.O.發過此問題了,不知道是不是英文太差沒有表達出問題核心的關係,目前得到的回應都沒有幫助就是XD。 這邊也付上我發問的連結
.Net Core - Can't get any reference assembly's controller action when used framework netcoreapp2.2

暐翰 iT邦大師 1 級 ‧ 2019-03-15 12:58:27 檢舉

我這邊也沒得到回應 XD

暐翰 iT邦大師 1 級 ‧ 2019-03-15 13:03:59 檢舉

linmasaki 有人回應了
在Startup.cs ConfigureServices添加

service.AddMvc().AddApplicationPart(typeof(Controller的類別).Assembly);

可以解決問題,但沒辦法只添加參考解決

linmasaki iT邦新手 5 級 ‧ 2019-03-15 13:16:44 檢舉

哈,沒有關係,現階段至少還能先上版號 2.2.0 緩解一下,昨天花了將近一天還去爬了有關 MvcServiceCollectionExtensions 的原始碼,懷疑是不是更新到 2.2.1 以上時有修改了什麼,也是白忙一場就是.../images/emoticon/emoticon03.gif

linmasaki iT邦新手 5 級 ‧ 2019-03-15 13:23:34 檢舉

暐翰是可以這樣做沒錯,但通常會這樣做的原因是因為 AddApplicationPart 裡的 Controller 也不在我引用的外部專案裡,有點像是我直接去讀取一個單獨的 Dll 檔,只是我已經在專案 build 前將外部的專案引用進來,正常來說應該是不太需要我在另外加上 AddApplicationPart 這段才對

暐翰 iT邦大師 1 級 ‧ 2019-03-15 13:25:34 檢舉

感覺微軟團隊有修改邏輯導致,可能改成只抓啟動專案的Assembly

暐翰 iT邦大師 1 級 ‧ 2019-03-15 13:52:29 檢舉

linmasaki S.O有高手看出原因是沒有添加Microsoft.AspNetCore.MVC,cspoj改成以下就可以

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App"/>
    <PackageReference Include="Microsoft.AspNetCore.MVC" />
  </ItemGroup>
</Project>
linmasaki iT邦新手 5 級 ‧ 2019-03-15 14:50:28 檢舉

暐翰嗯嗯,我有注意到,該解法也有點讓我匪夷所思就是,畢竟 Microsoft.AspNetCore.App 就已經包含了Microsoft.AspNetCore.MVC,在引用一次好像也有點多餘就是,另外就是我還發現假設引用外部的專案不只一個時,只要其中一個引用加上版本號 2.2.0 即可,例如主專案如下

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

  <PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>
    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\TestWeb.OtherModuleA\TestWeb.OtherModuleA.csproj" />
    <ProjectReference Include="..\TestWeb.OtherModuleB\TestWeb.OtherModuleB.csproj" />
    <ProjectReference Include="..\TestWeb.OtherModuleC\TestWeb.OtherModuleC.csproj" />
  </ItemGroup>

</Project>

只要在 OtherModuleA、B、C 任一個專案裡的 Microsoft.AspNetCore.App 加上版號 2.2.0 後,則其它兩個沒加的類別也都能夠正確被主專案讀到,嗯...頗耐人尋味就是= =

暐翰 iT邦大師 1 級 ‧ 2019-03-16 01:59:24 檢舉

我在想其實專案csproj可以改成以下
這樣更輕量、避免該問題,也可以兼容多版本

但還是沒解釋這次異常原因 XD

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>netcoreapp2.1;netcoreapp2.2;</TargetFrameworks>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App"/>
  </ItemGroup>
  <ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.2'">
    <PackageReference Include="Microsoft.AspNetCore.MVC" version="2.2.0"/>
  </ItemGroup>
  <ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.1'">
    <PackageReference Include="Microsoft.AspNetCore.MVC" version="2.1.1"/>
  </ItemGroup> 
</Project>

我要發表回答

立即登入回答