深入浅出Dotnet Core的项目结构变化

有时候,越是基础的东西,越是有人不明白。

前几天Review一个项目的代码,发现非常基础的内容,也会有人理解出错。

今天,就着这个点,写一下Dotnet Core的主要类型的项目结构,以及之间的转换和演化。

一、最基础的应用Console

控制台应用,是Dotnet Core乃至前边的Dotnet Framework中,最基础的项目。

我们来创建一个Console项目看一下:

% dotnet new console -o demo

创建完成后,打开工程。工程里只有一个文件Program.cs,里面只有一个方法Main

namespace demo
{class Program{static void Main(string[] args){Console.WriteLine("Hello World!");}}
}

在Dotnet Core所有类型的项目中,Program.cs都是最开始的入口,main方法,也是最开始的入口方法。

这个工程中,还有一个文件也需要了解一下,demo.csproj,这是这个项目的定义文件:

<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net5.0</TargetFramework></PropertyGroup></Project>

这里面,OutputType告诉编辑器这个工程编译后可以直接执行,TargetFramework定义运行的框架。

注意,这个框架字串有个对照表:net5.0对应的是.Net 5.0;如果你想用Dotnet Core 3.1,对应的字符串是netcoreapp3.1,而不是net3.1。准确的说,3.1是.Net Core 3.1,而5.0是.Net 5.0。不用太纠结,微软的命名规则而已。

这就是控制台应用Console的初始状态。

下面,我们看看这个工程如何转变为Web应用。

二、转为Web应用

第一件事,我们需要改动demo.csproj项目定义文件。

Web应用跑在WebHost上面,而不是从直接执行。所以,我们需要把OutputType项去掉。

另外,SDK也需要改一下。Console我们用的是Microsoft.NET.Sdk,Web应用要改成Microsoft.NET.Sdk.Web

<Project Sdk="Microsoft.NET.Sdk.Web"><PropertyGroup><TargetFramework>net5.0</TargetFramework></PropertyGroup></Project>

改完保存。

这时候,应该可以注意到,项目的发生了变化:

  • 依赖的框架从Microsoft.NETCore.App变成了两个,多了一个Microsoft.AspNetCore.App,表明现在这是一个Asp.net Core的应用;

  • 项目中自动生成了一个目录Properties,下面多了一个文件launchSettings.json。这个文件大家应该很熟悉,就不解释了。

这时候,应用已经从Console转为了Web应用。

Asp.Net Core框架提供了Host供Web加载。我们需要做的,是把Host构建器加到程序中。通常,我们需要两个构建器:

  • 通用主机 Generic host builder

  • Web主机 Web host builder 

1. 配置通用主机

通用主机在Microsoft.Extensions.Hosting.Host中,主要给Web应用提供以下功能:

  • 依赖注入

  • 日志

  • 配置 IConfiguration

  • IHostedService实现

加入通用主机很简单,就一个方法CreateDefaultBuilder

class Program
{static void Main(string[] args){Host.CreateDefaultBuilder(args).Build().Run();}
}

2. 配置Web主机

Web主机才是真正与Web相关的内容,主要实现:

  • Http支持

  • 设置Kestrol服务器为Web服务器

  • 添加IIS支持

加入Web主机,也是一个方法ConfigureWebHostDefaults

class Program
{static void Main(string[] args){Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>{}).Build().Run();}
}

这个方法用来添加Http请求管道并注入我们需要的服务。而注入我们需要的服务,就是我们最常见的Startup.cs的内容。

下面,我们先创建Startup.cs

namespace demo
{public class Startup{}
}

在前边ConfigureWebHostDefaults中,加入Startup,并补齐代码:

class Program
{static void Main(string[] args){Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>{webBuilder.UseStartup<Startup>();}).Build().Run();}
}

这就是Program.cs中的完整代码了。整理一下,就是我们常见的样子:

public class Program
{public static void Main(string[] args){CreateHostBuilder(args).Build().Run();}public static IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>{webBuilder.UseStartup<Startup>();});
}

不过,到这儿还不能正常运行,因为Startup.cs现在还是空的。

3. 补齐Startup类

Startup类在Asp.net Core应用中有着重要的作用。这个类用于:

  • 使用DI容器注入服务

  • 设置Http Request管道以插入中间件

下面我们补齐所需的方法:

namespace demo
{public class Startup{public void ConfigureServices(IServiceCollection services){}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){}}
}

运行,到这儿,Web应用已经可以正常启动了。

4. 给应用添加路由

Web应用启动了,但里面什么也没有,是空的。

要访问Web应用中的任何资源,需要配置路由。这儿的路由,基本上就是传入Http请求与资源之间的映射。

我们可以用下面的中间件来启动路由:

  • UseRouting

  • UseEndpoints

加一下试试:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{app.UseRouting();app.UseEndpoints(endpoint => {endpoint.MapGet("/", async context =>{await context.Response.WriteAsync("Hello from Demo");});});
}

这次运行,浏览器中就看到正确的输出了。

我们可以用MapGet映射更多资源:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{app.UseRouting();app.UseEndpoints(endpoint =>{endpoint.MapGet("/", async context =>{await context.Response.WriteAsync("Hello from Demo");});endpoint.MapGet("/test", async context =>{await context.Response.WriteAsync("Hello from Demo.Test");});endpoint.MapGet("/about", async context =>{await context.Response.WriteAsync("Hello from Demo.About");});});
}

到这儿,我们成功地把Console应用转为了Web应用。

三、延伸内容

上面完成的Web应用,算是Web应用中的基础。基于这个内容,我们还可以扩展到别的项目结构。

1. 改为MVC应用

需要在ConfigureServices中注入AddControllersWithViews,并在Configure中添加MapDefaultControllerRoute

public class Startup
{public void ConfigureServices(IServiceCollection services){services.AddControllersWithViews();}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){app.UseRouting();app.UseEndpoints(endpoint =>{endpoint.MapDefaultControllerRoute();});}
}

2. 改为WebAPI应用

需要注入AddControllersMapControllers

public class Startup
{public void ConfigureServices(IServiceCollection services){services.AddControllers();}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){app.UseRouting();app.UseEndpoints(endpoint =>{endpoint.MapControllers();});}
}

3. 改为Razor应用

需要注入AddRazorPagesMapRazorPages

public class Startup
{public void ConfigureServices(IServiceCollection services){services.AddRazorPages();}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){app.UseRouting();app.UseEndpoints(endpoint =>{endpoint.MapRazorPages();});}
}

四、总结

看下来,其实过程很简单。通过这种方式,能更进一步理解Dotnet Core的项目结构以及应用的运行过程。

希望对大家能有所帮助。

本文的配套代码在:https://github.com/humornif/Demo-Code/tree/master/0038/demo

喜欢就来个三连,让更多人因你而受益

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/305696.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

群策群力:破机房征求灵丹妙药

我校有一年代久远之计算机教室&#xff0c;现已经迈入日落西山之境。特征求灵丹妙药&#xff0c;不求妙手回春&#xff0c;只愿其能为我校的信息技术教育事业再尽最后一把微力&#xff0c;也为我校即将面临无地授课的教师提供继续上岗的救命稻草一枝。具体情况说明&#xff1a;…

使用 C# 9 的records作为强类型ID - 路由和查询参数

上一篇文章&#xff0c;我介绍了使用 C# 9 的record类型作为强类型id&#xff0c;非常简洁public record ProductId(int Value);但是在强类型id真正可用之前&#xff0c;还有一些问题需要解决&#xff0c;比如&#xff0c;ASP.NET Core并不知道如何在路由参数或查询字符串参数中…

linux sudo 必须属于用户ID0,sudo:/usr/bin/sudo 务必属于用户 ID 0(的用户)并且设置 setuid 位...

今天手抖本来要修改/usr/bin/下面的一个文件属性为 user:user&#xff0c;执行chown -R /usr/bin/的时候&#xff0c;再按tab之前直接敲了回车&#xff1b;结果导致执行sudo命令时出现错误提示&#xff1a;“sudo&#xff1a;/usr/bin/sudo 必须属于用户 ID 0(的用户)并且设置…

企业形象广告的几个突破要点

企业形象广告的使用不能简单的说好与不好&#xff0c;特定的企业&#xff0c;特定的行业&#xff0c;有不同的功能和效果&#xff0c;一般大众化消费品较为适宜&#xff0c;但也要注意&#xff1a; 1、 如果一个企业的产品处于一个完全成熟的品牌阶段&#xff0c;不易投入大量的…

公司高层要我转Java 我直接邮件回怼...

2020年艰难而短暂&#xff0c;而互联网的历史车轮还是轰隆隆一路向前&#xff0c;服务网格/云原生/Serverless架构&#xff0c;各种新架构大行其道。重新审视当下主流的编程语言&#xff0c;天下第一的Java已老&#xff0c;下行多年的.NET却浴火重生&#xff0c;焕发生机&#…

linux如何实现网络高级编程,嵌入式Linux网络编程之:网络高级编程-嵌入式系统-与非网...

10.3 网络高级编程在实际情况中&#xff0c;人们往往遇到多个客户端连接服务器端的情况。由于之前介绍的如connet()、recv()和send()等都是阻塞性函数&#xff0c;如果资源没有准备好&#xff0c;则调用该函数的进程将进入睡眠状态&#xff0c;这样就无法处理I/O多路复用的情况…

.NET斗鱼直播弹幕客户端(2021)

.NET斗鱼直播弹幕客户端(2021)离之前更新的两篇《.NET斗鱼直播弹幕客户端》已经有一段时间&#xff0c;近期有许多客户向我反馈刚好有这方面的需求&#xff0c;但之前的代码不能用了——但网上许多流传的Node.js、Python脚本却可以用&#xff0c;这岂能忍&#xff1f;&#xff…

McAfee推免费版SiteAdvisor安全上网工具

McAfee近期宣布推出完全免费版McAfee SiteAdvisor上网工具。McAfee SiteAdvisor是业界第一款Web安全工具&#xff0c;能够主动地提醒用户在浏览、搜索和即时通信或收发电子邮件时所遇到的危险站点&#xff0c;避免遭到网络钓鱼、间谍软件等恶意程序的***。 McAfee SiteAdvisor是…

9050 端口 linux 进程,windows和linux查看端口占用情况

一、Windows平台在windows命令行窗口下执行&#xff1a;1.查看所有的端口占用情况C:\>netstat -ano协议 本地地址 外部地址 状态 PIDTCP 127.0.0.1:1434 0.0.0.0:0 LISTENING 3236TC…

Exceptionless服务端本地化部署

背景分布式异常日志收集框架Exceptionless是开源的工具&#xff0c;根据官方给出的说明&#xff1a;Exceptionless提供两种使用方式&#xff0c;一种是官网创建账号,需要付费&#xff0c;免费版有限制&#xff1b;一种是自己搭建本地项目&#xff0c;无任何限制。准备安装包准备…

微软所谓的无人工介入的自动的机器翻译系统

近日在微软网站上查找资料,发现一个资料里有如下的声明性描述:注意&#xff1a;这篇文章是由无人工介入的自动的机器翻译系统翻译完成。这些文章是微软为不懂英语的用户提供的, 以使他们能够理解这些文章的内容。微软不保证机器翻译的正确度&#xff0c;也不对由于内容的误译或…

ABP vnext模块化架构的最佳实践的实现

在上一篇文章《手把手教你用Abp vnext构建API接口服务》中&#xff0c;我们用ABP vnext实现了WebAPI接口服务&#xff0c;但是并非ABP模块化架构的最佳实践。我本身也在学习ABP&#xff0c;我认为ABP新手应该从最佳实践开始学习&#xff0c;可以少走很多弯路&#xff0c;所以写…

WebCast学习链接

全部下载列表1. C#面向对象设计模式纵横谈系列课程 讲师&#xff1a;李建忠 上海祝成信息科技有限公司 高级培训讲师 MSDN特邀讲师2. ASP.NET AJAX深入浅出系列课程 讲师: 老赵 课程(1)&#xff1a;ASP.NET AJAX 概述 课程(2)&#xff1a;UpdatePanel的使用(…

linux删除第二次出现的字符,linux下 怎样删除文件名中包含特殊字符的文件

目录中无意间出现了 -- 这个文件[rootdev tmp]# ls-- 00 01 02 03 04 05 06 07 08 09[rootdev tmp]# lltotal 0-rw-r--r-- 1 root root 0 Oct 23 15:31 ---rw-r--r-- 1 root root 0 Oct 23 15:37 00-rw-r--r-- 1 root root 0 Oct 23 15:37 01-rw-r--r-- 1 root root 0 Oct 23 1…

全球知名跨境电商,.Net软件工程师招聘,约么?

公司&#xff1a;际客国际电子商务有限公司&#xff0c;网址&#xff1a;http://geekbuy.cn/工作地点&#xff1a;深圳市龙岗区五和大道南雅宝路1号星河WORLD B座岗位职责&#xff1a;中级开发工程师。薪资待遇&#xff1a;10K-20K&#xff0c;具体面议。 职位要求&#x…

被关起来日子的流水帐

2007年3月19日 老上号经过3个半小时的颠簸&#xff0c;在晚上7&#xff1a;30到达了哈尔滨&#xff0c;还是住在黑龙江大学旁边的学府宾馆&#xff0c;由于是在学校的边上&#xff0c;相对来说比较安全&#xff0c;宾馆的条件已经不如以前了&#xff0c;稍微显得有点陈旧&#…

krc 编辑 linux,Linux网络编程

6 berkeley - 145 -struct in_addr {unsigned long s_addr;};ina struct sockaddr_instruct in_addrina.sin_addr.s_addr 4 IP4 IP #defines6.5.21IP2h to nto Network Short Hosts H-to-n-s htons()68000n h to s l IPstolh() Short to Long Host?l htons() “Host to Networ…

iphone查看删除的短信_手机资讯:iPhone手机可以批量删除短信吗如何操作

如今使用IT数码设备的小伙伴们是越来越多了&#xff0c;那么IT数码设备当中是有很多知识的&#xff0c;这些知识很多小伙伴一般都是不知道的&#xff0c;就好比最近就有很多小伙伴们想要知道iPhone手机可以批量删除短信吗如何操作&#xff0c;那么既然现在大家对于iPhone手机可…

如何在 C# 8 中使用 模式匹配

模式匹配 是在 C# 7 中引入的一个非常????的特性&#xff0c;你可以在任何类型上使用 模式匹配&#xff0c;甚至是自定义类型&#xff0c;而且在 C# 8 中得到了增强&#xff0c;引入了大量的新模式类型&#xff0c;这篇文章就来讨论如何在 C# 8 中使用模式匹配。C# 8 中的表…

linux下找不到libc 库,Linux-覆盖libc open()库函数

我在库&中有glibc提供的相同的覆盖open().我首先在库中设置了LD_PRELOAD,因此当进程调用open()时,将调用库中定义的open.问题&#xff1a;-glibc中还有其他几个函数,一旦示例为getpt(),就会调用open(),当getpt()调用open()时,将调用glibc中定义的open(),我将如何使getpt ()…