asp.net-core - Beta8 中的 Asp.Net 5 MVC 6 Startup.cs 装配解耦

标签 asp.net-core asp.net-core-mvc

我正在使用 Asp.Net 5 和 MVC6 遵循洋葱架构 (OA) 开发一个电子商务网站,以便各层之间具有松散耦合。我还想将启动代码解耦到它自己的程序集中,而不是将其放在 MVC 项目中。

在 beta7 中,将 Startup.cs 移动到类库(Bootstrapper)非常容易,如所述 here 。使用上述方法的一个有趣的事实是,我不必从 MVC 项目引用 Bootstrapper 程序集。在运行时,托管在 IISExpress 下,通过程序集扫描,它能够找到 Microsoft.AspNet.Hosting.ini 文件中提到的 Bootstrapper 程序集。这可以通过在 global.json 中指定位置来实现

{
  "projects": [ "Source/Projects","Source/Bootstrapper" ],
  "sdk": {
        "architecture": "x64",
        "runtime": "clr",
        "version": "1.0.0-beta7"
    }
}

Bootstrapper 项目将引用所有其他项目,例如基础设施、服务等,以便连接依赖注入(inject)。

遵循洋葱架构规则,在 MVC 项目中不引用 Bootstrapper 项目的原因是为了避免直接从 MVC 项目访问基础设施代码。所以这一切都工作正常,直到我今天早上升级到 Beta8。

由于托管模型从 IIS 更改为 Kestrel,我必须重构 global.json 和 project.json 文件,如下所示

global.json

{
  "projects": [ "Source/Projects","Source/Bootstrapper" ],
  "sdk": {
        "architecture": "x64",
        "runtime": "clr",
        "version": "1.0.0-beta8"
    }
}

project.json

{ 
  "dependencies": {
    "Microsoft.AspNet.IISPlatformHandler": "1.0.0-beta8",
    "Microsoft.AspNet.Server.Kestrel": "1.0.0-beta8",
    "....",
    "....",
},

 "commands": {
    "web": "Microsoft.AspNet.Server.Kestrel"   
    } 
}

进行上述更改后,无论我使用 dnx 命令还是直接通过 Visual Studio 运行它,我都开始收到以下错误

Internal Server Error System.InvalidOperationException A type named 'StartupDevelopment' or 'Startup' could not be found in assembly 'EcommerceMvcApp'. at Microsoft.AspNet.Hosting.Startup.StartupLoader.FindStartupType(String startupAssemblyName, IList diagnosticMessages) at Microsoft.AspNet.Hosting.Internal.HostingEngine.EnsureStartup() at Microsoft.AspNet.Hosting.Internal.HostingEngine.EnsureApplicationServices() at Microsoft.AspNet.Hosting.Internal.HostingEngine.BuildApplication()

事实证明,我必须按照解释指定配置文件或 Web 命令的内联参数 here 。按照建议后,我尝试运行该应用程序,这次我开始收到以下错误

System.IO.FileNotFoundException Could not load file or assembly 'Bootstrapper' or one of its dependencies. The system cannot find the file specified. at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) at System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) at System.Reflection.Assembly.Load(AssemblyName assemblyRef) at Microsoft.AspNet.Hosting.Startup.StartupLoader.FindStartupType(String startupAssemblyName, IList diagnosticMessages) at Microsoft.AspNet.Hosting.Internal.HostingEngine.EnsureStartup() at Microsoft.AspNet.Hosting.Internal.HostingEngine.EnsureApplicationServices() at Microsoft.AspNet.Hosting.Internal.HostingEngine.BuildApplication()

solution要求我在 MVC 项目中添加对 Bootstrapper 项目的引用,并且它可以工作。然而,它一开始就违背了拥有单独的 Bootstrapper 程序集的目的。

问题是,为什么它无法像 Beta7 中那样使用 global.json 中“项目”下指定的源找到 Bootstrapper 程序集,或者新的托管模型是否忽略了 global.json?有没有办法指定启动程序集的位置?

更新1

只是想强调一下,在 Beta7 中,它还可以对 Microsoft.AspNet.Server.WebListener 和 Microsoft.AspNet.Server.Kestrel 使用“dnx 命令”。

"commands": {
        "kestrel": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:5004 --config wwwroot/Microsoft.AspNet.Hosting.ini",
        "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5004 --config wwwroot/Microsoft.AspNet.Hosting.ini"
    }

但是,Beta8 中的两台服务器的 dnx 命令(使用 Microsoft.AspNet.Hosting.json 文件)均失败。如果有人想知道这与 Beta7 中的 IIS Helios 组件有关,事实并非如此。我很困惑为什么程序集查找在 Beta8 中停止工作

更新2

这是我尝试使用 IISExpress 在 Beta8 中运行时得到的堆栈跟踪。看起来它正在尝试在 dnx bin 文件夹中查找程序集。

System.IO.FileNotFoundException: Could not load file or assembly 'Bootstrapper' or one of its dependencies. The system cannot find the file specified. File name: 'Bootstrapper' at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) at System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) at System.Reflection.Assembly.Load(AssemblyName assemblyRef) at Microsoft.AspNet.Hosting.Startup.StartupLoader.FindStartupType(String startupAssemblyName, IList`1 diagnosticMessages) at Microsoft.AspNet.Hosting.Internal.HostingEngine.EnsureStartup() at Microsoft.AspNet.Hosting.Internal.HostingEngine.EnsureApplicationServices() at Microsoft.AspNet.Hosting.Internal.HostingEngine.BuildApplication()

=== Pre-bind state information === LOG: DisplayName = Bootstrapper (Partial) WRN: Partial binding information was supplied for an assembly: WRN: Assembly Name: Bootstrapper | Domain ID: 1 WRN: A partial bind occurs when only part of the assembly display name is provided. WRN: This might result in the binder loading an incorrect assembly. WRN: It is recommended to provide a fully specified textual identity for the assembly, WRN: that consists of the simple name, version, culture, and public key token. WRN: See whitepaper http://go.microsoft.com/fwlink/?LinkId=109270 for more information and common solutions to this issue. LOG: Appbase = file:///C:/Users/sshassan/.dnx/runtimes/dnx-clr-win-x86.1.0.0-beta8/bin/ LOG: Initial PrivatePath = NULL Calling assembly : (Unknown). === LOG: This bind starts in default load context. LOG: No application configuration file found. LOG: Using host configuration file: LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config. LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind). LOG: Attempting download of new URL file:///C:/Users/sshassan/.dnx/runtimes/dnx-clr-win-x86.1.0.0-beta8/bin/Bootstrapper.DLL. LOG: Attempting download of new URL file:///C:/Users/sshassan/.dnx/runtimes/dnx-clr-win-x86.1.0.0-beta8/bin/Bootstrapper/Bootstrapper.DLL. LOG: Attempting download of new URL file:///C:/Users/sshassan/.dnx/runtimes/dnx-clr-win-x86.1.0.0-beta8/bin/Bootstrapper.EXE. LOG: Attempting download of new URL file:///C:/Users/sshassan/.dnx/runtimes/dnx-clr-win-x86.1.0.0-beta8/bin/Bootstrapper/Bootstrapper.EXE.

也许,如果我运行 dnu 发布并将其托管在 IIS 下,它就会工作,但这意味着我每次进行更改时都必须发布它

最佳答案

我也遇到过类似的问题。看起来我们不想从 UI 层到基础设施层进行引用(我们非常严格),甚至不想进行依赖关系解析。

也许可以通过使用后期绑定(bind)(我刚刚听说过它),但我认为你应该阅读this article 。它基本上表示组合根不可重用,每个应用程序都应该有一个(即,一个用于 UI.Web,另一个用于 UI.Console,等等)。

这也回答了我关于 UI.Web 中具有 DI 解析的问题,但需要另一个 UI,比如说控制台(答案:最好在控制台中进行另一个 DI 解析,并且它会有自己的与控制台应用程序实际工作方式相关的分辨率依赖性)。

我希望能给您一个很好的观点来澄清这个问题。

关于asp.net-core - Beta8 中的 Asp.Net 5 MVC 6 Startup.cs 装配解耦,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33240413/

相关文章:

c# - 需要从 ASP.NET Core 动态在 Azure DNS 中创建子域

c# - MVC6 - 如果(复选框勾选)则删除线

c# - Entity Framework Core 在保存时不验证数据?

c# - 将带有asp.net core的文件作为字节数组上传到数据库中

c# - 在 Startup.cs 的 Configure 中获取域名或主机名和端口

c# - 如何从 UseStatusCodePagesWithReExecute 中排除某些路由?

authentication - 在asp.net core 3.1中注册基于租户的认证方案

model-view-controller - Dialogflow Webhook C# 集成

asp.net - "No files matched the search pattern"在 tfs 构建中

c# - 将强类型配置设置直接访问到 ASP.NET 5 (vNext) 中的类库中?