.NET Core 控制台如何嵌入运行 Web API网站?

news/2024/5/10 0:53:58/文章来源:https://blog.csdn.net/farway000/article/details/127081509
【导读】我们知道在.NET Framework中可以嵌入运行Web APi,那么在.NET Core(.NET 6+称之为.NET)中如何内嵌运行Web Api呢,在实际项目中这种场景非常常见,那么我们本节以.NET 6.0作为演示示例一起来瞅瞅。

内嵌运行.NET Core Web APi

接下来我们通过控制台作为主程序来启动Web APi,首先我们创建名为EmbedWebApi的控制台程序,然后创建Embed.WebApi类库运行Web APi,我们在此Web APi中创建如下接口,并实现相关方法来运行Web APi

public class InitTest : IInitTest
{public void Init(){var builder = WebApplication.CreateBuilder();builder.Services.AddControllers();var app = builder.Build();app.UseRouting();app.UseEndpoints(endpoints => {endpoints.MapDefaultControllerRoute();});app.Run();}
}public interface IInitTest
{void Init();
}

通过写接口并在对应方法中运行Web APi主要是达到在控制中调用该接口进行模拟实现,这里需要注意一点的是,因为我们创建的Web APi是类库,要想使用Web里面的Api等等,直接在项目文件中添加如下一行以表明我们要引用框架,这样一来框架里面所包含的APi等等版本都一致统一,而不是通过NuGet一一下载,这是错误的做法

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

接下来我们在该类库中按照规范创建Controllers文件夹,并创建测试控制器,如下

using Microsoft.AspNetCore.Mvc;namespace Embed.WebApi.Controllers
{[ApiController][Route("api/[controller]/[action]")]public class TestController : ControllerBase{[HttpGet]public IActionResult Test(){return Ok("Hello World");}}
}

最后我们在控制台程序中注册上述接口并调用初始化方法,如下:

internal class Program
{static void Main(string[] args){var services = new ServiceCollection();services.AddTransient<IInitTest, InitTest>();var serviceProvider = services.BuildServiceProvider();var initTest = serviceProvider.GetRequiredService<IInitTest>();initTest.Init();Console.Read();}
}

2c0b90b83d9e2e7c9c6355f0495dbf6e.png

芜湖,我们通过Postman模拟调用测试接口,结果惊呆了,404了~~~

01e5b86ba374442e7ddfe298f4246ac1.png

当我们将类库中的控制器移动到控制台中,此时请求测试接口并成功返回对世界的问候,这是什么原因呢?不难猜测可知,WebAPi控制器的激活以作为入口的主程序集进行查找激活。

虽然这样看似解决了问题,假设调用嵌入运行的主程序是底层已经封装好的基础设施,那么岂不是遭到了代码入侵,所以我们就想在运行的Web APi类库里面去激活,此时我们想到将类库作为Web APi应用程序一部分应用手动加载并激活,在初始化方法里面修改为如下即可请求测试接口成功

public class InitTest : IInitTest
{private static readonly string AssemblyName = typeof(InitTest).Assembly.GetName().Name;public void Init(){var builder = WebApplication.CreateBuilder();builder.Services.AddControllers().AddApplicationPart(Assembly.Load(new AssemblyName(AssemblyName)));var app = builder.Build();app.UseRouting();app.UseEndpoints(endpoints => {endpoints.MapDefaultControllerRoute();});app.Run();}
}

上述直接在运行Web APi类库中添加控制器激活,这种场景完全限定于底层主入口已封装好,所以只能采用这种方式,若是主入口我们自己可控制,当然还有另外一种方式,来,我们瞧瞧截取的关键性源码

/// <summary>
/// Populates the given <paramref name="feature"/> using the list of
/// <see cref="IApplicationFeatureProvider{TFeature}"/>s configured on the
/// <see cref="ApplicationPartManager"/>.
/// </summary>
/// <typeparam name="TFeature">The type of the feature.</typeparam>
/// <param name="feature">The feature instance to populate.</param>
public void PopulateFeature<TFeature>(TFeature feature)
{if (feature == null){throw new ArgumentNullException(nameof(feature));}foreach (var provider in FeatureProviders.OfType<IApplicationFeatureProvider<TFeature>>()){provider.PopulateFeature(ApplicationParts, feature);}
}internal void PopulateDefaultParts(string entryAssemblyName)
{var assemblies = GetApplicationPartAssemblies(entryAssemblyName);var seenAssemblies = new HashSet<Assembly>();foreach (var assembly in assemblies){if (!seenAssemblies.Add(assembly)){// "assemblies" may contain duplicate values, but we want unique ApplicationPart instances.// Note that we prefer using a HashSet over Distinct since the latter isn't// guaranteed to preserve the original ordering.continue;}var partFactory = ApplicationPartFactory.GetApplicationPartFactory(assembly);foreach (var applicationPart in partFactory.GetApplicationParts(assembly)){ApplicationParts.Add(applicationPart);}}
}private static IEnumerable<Assembly> GetApplicationPartAssemblies(string entryAssemblyName)
{var entryAssembly = Assembly.Load(new AssemblyName(entryAssemblyName));// Use ApplicationPartAttribute to get the closure of direct or transitive dependencies// that reference MVC.var assembliesFromAttributes = entryAssembly.GetCustomAttributes<ApplicationPartAttribute>().Select(name => Assembly.Load(name.AssemblyName)).OrderBy(assembly => assembly.FullName, StringComparer.Ordinal).SelectMany(GetAssemblyClosure);// The SDK will not include the entry assembly as an application part. We'll explicitly list it// and have it appear before all other assemblies \ ApplicationParts.return GetAssemblyClosure(entryAssembly).Concat(assembliesFromAttributes);
}private static IEnumerable<Assembly> GetAssemblyClosure(Assembly assembly)
{yield return assembly;var relatedAssemblies = RelatedAssemblyAttribute.GetRelatedAssemblies(assembly, throwOnError: false).OrderBy(assembly => assembly.FullName, StringComparer.Ordinal);foreach (var relatedAssembly in relatedAssemblies){yield return relatedAssembly;}
}

从上述源码可知,通过主入口程序集还会加载引用的程序集去查找并激活相关特性(比如控制器),当然前提是实现ApplicationPartAttribute特性,此特性必须在主入口程序集里定义,定义在程序集上

所以我们只需一行代码即可搞定,我们在控制台主入口命名空间顶部添加特性,引入Web APi类库程序集作为应用程序的一部分,如下:

[assembly: ApplicationPart("Embed.WebApi")]
那么接下来问题又来了,要是需要运行多个Web APi我们又当如何呢?按照上述方式一一添加未尝不可,我们也可以通过MSBuild任务来进行构建将相关特性自动添加到主入口程序集描述信息里面去,例如:
<ItemGroup><AssemblyAttribute Include="Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartAttribute"><_Parameter1>Embed.WebApi</_Parameter1></AssemblyAttribute>
</ItemGroup>

有的童鞋就问了,这不写死了么,那还不如通过添加特性的方式去处理,请注意这里只是使用示例

实际情况下,我们可将多个Web APi放在同一解决方案下,然后在此解决方案下创建可构建任务的.targets文件,并在主项目文件里引入,将程序集名称作为变量引入,剩下事情自行统一处理,若不清楚怎么搞,就在代码中使用特性方式也未尝不可,例如如下:

<ItemGroup><AssemblyAttribute Include="Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartAttribute"><_Parameter1>$(AssemblyName)</_Parameter1></AssemblyAttribute>
</ItemGroup>

本节我们重点讨论如何内嵌运行.NET Core Web APi类库,同时介绍了两种激活比如控制器特性方案, 希望对您有所帮助,谢谢,我们下节再会

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

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

相关文章

【问题解决】Chrome浏览器:该网站使用HSTS。网络错误...此页面稍后可能会工作之解决方法

【问题解决】Chrome浏览器&#xff1a;该网站使用HSTS。网络错误…此页面稍后可能会工作之解决方法 原文地址&#xff1a; https://blog.csdn.net/weixin_43486390/article/details/96860374 这里我偷懒了&#xff0c;直接把别人解决过的方法直接搬过来了&#xff0c;不过&…

源码托管网站推荐——OKSvn

在团队开发时&#xff0c;没使用SVN或者其他版本控制工具必将带来很多不必要的麻烦。在本机搭建SVN的方法虽然可行&#xff0c;但你不能保证你的电脑一直处于运行状态&#xff0c;显然是很不方便的。 我们知道&#xff0c;新浪、谷歌都有项目托管&#xff0c;由于网速不给力&am…

建站手册-网站构建:万维网联盟(World Wide Web Consortium)

ylbtech-建站手册-网站构建&#xff1a;万维网联盟&#xff08;World Wide Web Consortium&#xff09;1.返回顶部 1、http://www.w3school.com.cn/site/site_w3c.asp2、2.返回顶部1、万维网联盟&#xff08;W3C&#xff09;创立了 WWW 标准。 W3C 的使命是通过发展规范、指导方…

数据分析案例(5)利用MYSQL+Python对某网站的用户数进行分析

数据与代码链接&#xff1a; https://pan.baidu.com/s/1vF3hzzI83tDDVl-kM03shQ 提取码&#xff1a;0202 user.sql文件大家自行导入mysql数据库中&#xff0c;我是放在了test01数据库中 数据由于是存储在MYsql数据库的&#xff0c;因此我们需要利用Python连接mysql数据库&…

discuz html5 手机,Discuz正式推出移动端社区建站工具Discuz Q

从黯然离场到二次上线&#xff0c;Discuz近期正式上线移动端社区建站软件Discuz Q&#xff0c;鼎力支持站长专属私域流量经营!了解到&#xff0c;Discuz! Q简单讲就是一套手机端的社区建站软件&#xff0c;核心就是帮助站长经营移动端私域流量&#xff0c;快速内容变现 &#x…

微信网站防屏蔽防红的措施以及微信域名检测API等工具的技术原理

为什么关心这种技术&#xff1f;因为我经常听到身边搞微商、搞微信项目的朋友都在叫苦连天&#xff0c;由于微信域名屏蔽、微信域名被拦截、弄得他们尸横遍野&#xff0c;损失的连过年回家的路费都没了&#xff0c;曾经的叱咤风云一下变成了今日的倒亏损。腾讯对微信中推广活动…

数字藏品交易平台开发 数字藏品交易网站开发

“数字藏品是运用电子信息技术促进文化艺术&#xff0c;尤其是传统式文化创意产业概率界限的移位&#xff0c;是推动文化创意产业使用价值和价值活起來的媒介。"12月21日&#xff0c;河北省博物院副院长赵志良在“用数赋智推动中华文化艺术创造力转换、创新能力发展趋势&q…

区块链nft网站开发 NFT数字藏品网站开发

虽然NFT自从2017年以来一直存在&#xff0c;NFT他们最初被用于加密社区内的边缘例&#xff08;收集加密猫&#xff09;。然而四年了&#xff0c;我们见证了艺术家&#xff0c;设计师&#xff0c;游戏开发者&#xff0c;音乐家和作家对这项技术的采用&#xff0c;在DEFI出现之前…

java中添加音乐_[Java教程]如何在网站中添加音乐

[Java教程]如何在网站中添加音乐0 2014-10-19 17:00:42来源&#xff1a;http://www.ido321.com/1042.html发现有很多的个人博客中添加了背景音乐&#xff0c;以增强用户体验。LZ搜集到了两种在网站中添加音乐的方式。一、豆瓣的FM这个非常简单&#xff0c;一段代码就可以实现。…

藏头诗php网站源码,四、中英翻译、歌词、藏头诗、智能聊天

中英翻译、歌词、藏头诗、智能聊天此章接口都来源于:http://api.ajaxsns.com/ ,感谢作者的无私奉献。先看效果图代码如下:1、共同方法private function _ajaxsns_comm($msg){$paramarray("key" > "free","appid" > "0","ms…

3.在Visual Studio 2017 下创建ASP.NET网站程序

1.文件——新建——项目 2.在新弹出来的窗口上选择Visual C#&#xff0c;然后选择ASP.NET Web 应用程序&#xff08;.NET Framework&#xff09;,然后点击确定 这里要注意下面的名称&#xff0c;位置&#xff0c;方案名称&#xff0c;需要改的就改了吧&#xff0c;新手还是一切…

存储过程可重用的代码块_GitHub推出新功能Actions,直接网站上构建、共享和执行代码...

​【新智元导读】GitHub推出了一个新版本的GitHub Actions测试版&#xff0c;内置了持续集成和交付功能。GitHub表示&#xff0c;它现在拥有4000多万用户。GitHub Actions是一个用于GitHub的因果关系的API&#xff0c;即基于任何事件协调任何工作流&#xff0c;与此同时GitHub负…

网页左侧导航栏点击怎么显示右侧内容_网站导航条应该怎么设计才比较易用

企业在做网站建设的时候需要&#xff0c;导航条是一个关键部分&#xff0c;一个明了易用的网站导航条能让用户在浏览网站的时候快速明确找到自己想要的页面&#xff0c;相当于网站的指路牌&#xff0c;所以导航条需要重点设计。那么如何才能设计出简单易用的网站导航条呢&#…

博文视点大讲堂41期-SEO难点之网站内部链接结构

博文视点大讲堂41期 SEO难点之网站内部链接结构 SEO是什么&#xff1f; 虽然这些年SEO概念普及了&#xff0c;但在很多人眼里&#xff0c;SEO和作弊、欺骗是一回事儿。这是对SEO的极大误解。 SEO是个强有力的工具&#xff0c;能以很合理的方式进行&#xff0c;既照顾到用户需求…

java setaccessible_「accessible」Java反射中的setAccessible()方法是否破坏了类的访问规则 - seo实验室...

accessiblejava反射机制提供的setaccessible()方法可以取消Java的权限控制检查&#xff0c;下面展示了这种方法的使用。package test;import java.lang.reflect.field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;class A {private i…

宝塔Linux301重定向,宝塔面板如何做网站301重定向跳转

网站301重定向对于我们日后做SEO还是挺重要的&#xff0c;它是指是一条对网站浏览器的指令&#xff0c;来显示浏览器被要求显示的不同的URL&#xff0c;当一个网页经历过其URL的最后一次变化以后时使用。一个永久定向是一种服务器端的重定向&#xff0c;能够被搜索引擎蜘蛛适当…

服务器运行堵塞 负载%100,小白站长如何快速了解网站服务器的运行状况

我们的网站服务器预装系统:CentOS Linux 7.6.1810 (Core)。对于小白站长来讲&#xff0c;因为宝塔管理面板是现在非常流行的一款免费的Windows/Linux管理应用&#xff0c;所以服务器安装这个应用&#xff0c;并安装Nginx -Tengine2.2.3运行环境&#xff0c;其可视化操作界面&am…

php课设源代码网站,php精品课程教学网站在线发布系统

功能需求3.3.1 学生部分1&#xff1a;课程展台&#xff1a;为学生提供课程操作平台。1) 课程简介&#xff1a;显示课程的基本情况的介绍&#xff1b;2) 教学大纲&#xff1a;显示课程的教学大纲内容&#xff1b;3) 授课计划&#xff1a;显示课程的授课计划&#xff1b;4) 备课教…

linux保险箱软件,360保险箱的保护功能 - 不怕盗号木马 奇虎360保险箱抢鲜试用(组图)_Linux安全_Linux公社-Linux系统门户网站...

360保险箱的保护功能二、360保险箱的保护功能保护功能是360保险箱的主要功能&#xff0c;在保护功能下共有“安全启动”、“正在保护”、“保护历史”三个标签。在安全启动这一项上&#xff0c;对应的程序类型有“聊天工具”、“网络游戏”、“网络银行”三种类型。其中聊天工具…

论文网站

从cvchina上看到的&#xff0c;转载自demonstrate 的 blog 自己稍作补充。这里搜集了一些常见的和 machine learning 相关的网站&#xff0c;按照 topic 来分。 Active Learning http://active-learning.net/&#xff0c;这里包括了关于Active Learning理论以及应用的一些文章&…