首页 > 其他分享 >WebApi使用 (.Net Framework版)

WebApi使用 (.Net Framework版)

时间:2025-01-01 14:41:19浏览次数:5  
标签:WebApi HTTP return string Get Framework IHttpActionResult Net public

1 创建

使用.Net做web后端,推荐使用.Net Core,微软在此基础上做了很多适配,包括内置Swagger,可以直接启动等等。而.Net Framework版,需要手动配置很多内容。

如果需要调用的项目是基于.Net Framework,那么web项目也应基于.Net Framework开发。或者其他原因不得不使用.Net Framework开发web项目,可以参考本文。

打开VS,在搜索栏输入“ASP.NET Web”,选择.Net Framework版,注意,这里要创建的是空白API项目,在前后端分离的项目中只作为后端接口,而不是MVC(模型-视图-控制器)

填写项目名,选择位置,选择需要的框架

创建一个空白项目,勾选“Web API”,取消勾选“HTTPS配置”

添加完成后,会创建以下目录结构:

  • “App_Data”目录用于方式一些资源文件;
  • “App_Start”目录下用于放置一些配置资源,默认已有一个配置类“WebApiConfig”,内容如下:
public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}
- config.MapHttpAttributeRoutes();表示启用了属性路由,允许在控制器和操作方法上直接使用特性(如 `[Route]`)来定义路由规则。
- 下半部分表示定义默认路由规则。
  • “Controllers”目录下放置对外接口;
  • “Models”目录下放置后端接口的内部逻辑,比如要接入数据库的操作等等。这些目录作为一个规范,如果违反这个规范随意放置,也可以正常运行,只不过看着比较杂乱。

2 测试

项目创建完成后,并没有提供任何对外接口,添加一个测试接口。选中“Controllers”目录=>右键=>添加=>Web API控制器类

填写名称,建议名称为“xxxController”(xxx为需要写的名称),此名称会被上文提到的“默认路由规则”匹配,将“xxx”作为api的一部分。

类创建完成后,会自动生成示例程序,包含Get, Post, Put, Delete请求

public class TestController : ApiController
{
    // GET api/<controller>
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }

    // GET api/<controller>/5
    public string Get(int id)
    {
        return "value";
    }

    // POST api/<controller>
    public void Post([FromBody] string value)
    {
    }

    // PUT api/<controller>/5
    public void Put(int id, [FromBody] string value)
    {
    }

    // DELETE api/<controller>/5
    public void Delete(int id)
    {
    }
}

启动项目,基于.Net Framework的web项目需要借助于服务启动,vs调试默认使用IIS服务。

启动完成后,没有配置默认的访问地址就会显示如下界面。

测试Api访问。

3 配置属性路由规则

上文提到,配置类“WebApiConfig”中配置了默认路由规则,启用了属性路由。属性路由就是使用特性标记路由,使用属性路由代替了默认路由。

示例如下:

[RoutePrefix("api/TestABC")]
public class TestController : ApiController
{
    [HttpGet]
    [Route("GetValue")]
    // GET api/<controller>
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }
}

启动,测试访问,可以看到,路由规则已经由默认路由规则变为了属性路由规则。

4 配置Swagger

4.1 基本配置

在NuGet中下载安装“Swashbuckle”

安装完成后,在“App_Start”目录下会自动生成“SwaggerConfig”配置类。可以修改需要显示的内容,下图这个语句包含两条信息,“版本”和“Title”。

在项目属性中,勾选生成“XML文档文件”,本质上是Swagger将此xml转换为Swagger格式的内容。

安装完之后,再访问本地URL,可能会报一个错,这里不要慌,一般是安装的“Swashbuckle”包依赖的内容与现有安装的包不相符,在NuGet包管理器中全部更到最新即可。

启动后在原有url后加入/swagger即可访问文档。

展开后,可以点击“Try it out”按钮进行测试。

请求与相应如下:

测试Post,字符串一定要带""

程序中获取到浏览器发送的内容。

4.2 为程序添加注释

上文提到,勾选了生成“XML文档文件”,此xml是将写的注释记录下来。

比如为Get请求添加注释。

/// <summary>
/// 测试请求
/// </summary>
/// <returns>返回示例数据</returns>
public IEnumerable<string> Get()
{
    return new string[] { "value1", "value2" };
}

然后在SwaggerConfig配置类中添加一条配置。

c.IncludeXmlComments(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "bin\\TestWebApi.xml"));

再次访问,可以看到,有了注释的内容。

4.3 汉化处理

安装“Swagger.Net.UI”

安装完成后,在“App_Start”目录下新增了一个SwaggerNet类

打开SwaggerNet类,注释掉这两行(这里我没做深究,参考的几篇文章都说注释掉这两行,可能后续运行有报错)

创建一个“SwaggerControllerDescProvider”类,用于对swagger文档中的内容进行汉化处理。

/// <summary>
/// swagger显示控制器的描述
/// </summary>
public class SwaggerControllerDescProvider : ISwaggerProvider
{
    private readonly ISwaggerProvider _swaggerProvider;
    private static ConcurrentDictionary<string, SwaggerDocument> _cache = new ConcurrentDictionary<string, SwaggerDocument>();
    private readonly string _xml;
    /// <summary>
    /// 
    /// </summary>
    /// <param name="swaggerProvider"></param>
    /// <param name="xml">xml文档路径</param>
    public SwaggerControllerDescProvider(ISwaggerProvider swaggerProvider, string xml)
    {
        _swaggerProvider = swaggerProvider;
        _xml = xml;
    }

    public SwaggerDocument GetSwagger(string rootUrl, string apiVersion)
    {
        var cacheKey = string.Format("{0}_{1}", rootUrl, apiVersion);
        SwaggerDocument srcDoc = null;
        //只读取一次
        if (!_cache.TryGetValue(cacheKey, out srcDoc))
        {
            srcDoc = _swaggerProvider.GetSwagger(rootUrl, apiVersion);

            srcDoc.vendorExtensions = new Dictionary<string, object> { { "ControllerDesc", GetControllerDesc() } };
            _cache.TryAdd(cacheKey, srcDoc);
        }
        return srcDoc;
    }

    /// <summary>
    /// 从API文档中读取控制器描述
    /// </summary>
    /// <returns>所有控制器描述</returns>
    public ConcurrentDictionary<string, string> GetControllerDesc()
    {
        string xmlpath = _xml;
        ConcurrentDictionary<string, string> controllerDescDict = new ConcurrentDictionary<string, string>();
        if (File.Exists(xmlpath))
        {
            XmlDocument xmldoc = new XmlDocument();
            xmldoc.Load(xmlpath);
            string type = string.Empty, path = string.Empty, controllerName = string.Empty;

            string[] arrPath;
            int length = -1, cCount = "Controller".Length;
            XmlNode summaryNode = null;
            foreach (XmlNode node in xmldoc.SelectNodes("//member"))
            {
                type = node.Attributes["name"].Value;
                if (type.StartsWith("T:"))
                {
                    //控制器
                    arrPath = type.Split('.');
                    length = arrPath.Length;
                    controllerName = arrPath[length - 1];
                    if (controllerName.EndsWith("Controller"))
                    {
                        //获取控制器注释
                        summaryNode = node.SelectSingleNode("summary");
                        string key = controllerName.Remove(controllerName.Length - cCount, cCount);
                        if (summaryNode != null && !string.IsNullOrEmpty(summaryNode.InnerText) && !controllerDescDict.ContainsKey(key))
                        {
                            controllerDescDict.TryAdd(key, summaryNode.InnerText.Trim());
                        }
                    }
                }
            }
        }
        return controllerDescDict;
    }
}

在SwaggerUI文件夹中,创建一个swagger_lang.js的js,用于对swagger进行汉化处理(注:这个文件必须添加,否则汉化将失败)

swagger_lang.js 文件中的js内容如下。在最后几行有“公司名称”和对应的Url,可以自行更改,这里我写了百度的链接作为测试。

/// <summary>
/// 中文转换
/// </summary>
var SwaggerTranslator = (function () {
    //定时执行检测是否转换成中文,最多执行500次  即500*50/1000=25s
    var iexcute = 0,
        //中文语言包
        _words = {
            "Warning: Deprecated": "警告:已过时",
            "Implementation Notes": "实现备注",
            "Response Class": "响应类",
            "Status": "状态",
            "Parameters": "参数",
            "Parameter": "参数",
            "Value": "值",
            "Description": "描述",
            "Parameter Type": "参数类型",
            "Data Type": "数据类型",
            "Response Messages": "响应消息",
            "HTTP Status Code": "HTTP状态码",
            "Reason": "原因",
            "Response Model": "响应模型",
            "Request URL": "请求URL",
            "Response Body": "响应体",
            "Response Code": "响应码",
            "Response Headers": "响应头",
            "Hide Response": "隐藏响应",
            "Headers": "头",
            "Try it out!": "试一下!",
            "Show/Hide": "显示/隐藏",
            "List Operations": "显示操作",
            "Expand Operations": "展开操作",
            "Raw": "原始",
            "can't parse JSON.  Raw result": "无法解析JSON. 原始结果",
            "Model Schema": "模型架构",
            "Model": "模型",
            "apply": "应用",
            "Username": "用户名",
            "Password": "密码",
            "Terms of service": "服务条款",
            "Created by": "创建者",
            "See more at": "查看更多:",
            "Contact the developer": "联系开发者",
            "api version": "api版本",
            "Response Content Type": "响应Content Type",
            "fetching resource": "正在获取资源",
            "fetching resource list": "正在获取资源列表",
            "Explore": "浏览",
            "Show Swagger Petstore Example Apis": "显示 Swagger Petstore 示例 Apis",
            "Can't read from server.  It may not have the appropriate access-control-origin settings.": "无法从服务器读取。可能没有正确设置access-control-origin。",
            "Please specify the protocol for": "请指定协议:",
            "Can't read swagger JSON from": "无法读取swagger JSON于",
            "Finished Loading Resource Information. Rendering Swagger UI": "已加载资源信息。正在渲染Swagger UI",
            "Unable to read api": "无法读取api",
            "from path": "从路径",
            "Click to set as parameter value": "点击设置参数",
            "server returned": "服务器返回"
        },
 
        //定时执行转换
        _translator2Cn = function () {
            if ($("#resources_container .resource").length > 0) {
                _tryTranslate();
            }
 
            if ($("#explore").text() == "Explore" && iexcute < 500) {
                iexcute++;
                setTimeout(_translator2Cn, 50);
            }
        },
 
        //设置控制器注释
        _setControllerSummary = function () {
            $.ajax({
                type: "get",
                async: true,
                url: $("#input_baseUrl").val(),
                dataType: "json",
                success: function (data) {
                    var summaryDict = data.ControllerDesc;
                    var id, controllerName, strSummary;
                    $("#resources_container .resource").each(function (i, item) {
                        id = $(item).attr("id");
                        if (id) {
                            controllerName = id.substring(9);
                            strSummary = summaryDict[controllerName];
                            if (strSummary) {
                                var option = $(item).children(".heading").children(".options");
                                if ($(option).children(".controller-summary").length > 0) {
                                    $(option).children(".controller-summary").remove();
                                }
                                $(option).prepend('<li class="controller-summary" title="' + strSummary + '">' + strSummary + '</li>');
                            }
                        }
                    });
                }
            });
        },
 
        //尝试将英文转换成中文
        _tryTranslate = function () {
            $('[data-sw-translate]').each(function () {
                $(this).html(_getLangDesc($(this).html()));
                $(this).val(_getLangDesc($(this).val()));
                $(this).attr('title', _getLangDesc($(this).attr('title')));
            });
        },
        _getLangDesc = function (word) {
            return _words[$.trim(word)] !== undefined ? _words[$.trim(word)] : word;
        };
 
    return {
        Translator: function () {
            $("#logo").html("公司名称").attr("href", "https://www.baidu.com");
            $('body').append('<style type="text/css">.controller-summary{color:#10a54a !important;word-break:keep-all;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:250px;text-align:right;cursor:default;} </style>');
            //设置控制器描述
            _setControllerSummary();
            _translator2Cn();
        },
        translate: function () {
            this.Translator();
        }
    }
})();
//执行转换
SwaggerTranslator.Translator();

新增的swagger_lang.js文件需要修改文件属性,将文件生成操作修改为“嵌入的资源”。

将创建的swagger_lang.js在SwaggerConfig文件中进行引用。注意文件的路径。

c.InjectJavaScript(thisAssembly, "TestWebApi.SwaggerUI.swagger_lang.js");  //引用中文包

汉化结果:

5 包装返回结果

5.1 IHttpActionResult接口

默认生成的测试程序,请求到的数据都直接返回的数据内容。

public IEnumerable<string> Get()
{
    return new string[] { "value1", "value2" };
}

// GET api/<controller>/5
public string Get(int id)
{
    return "value";
}

如果需要自主决定状态码或者返回错误结果内容时携带异常信息等,可以使用C#提供的IHttpActionResult接口。

public IHttpActionResult Get()
{
    return Ok(new string[] { "value1", "value2" });
}

其中Ok()是ASP.NET Web API 提供了一些常用的IHttpActionResult实现,代表200状态码,只使用Ok(),与不使用IHttpActionResult接口并无明显的区别。

5.2 其它方法

除了常见的 Ok 方法外,ASP.NET Web API 还提供了多个 IHttpActionResult 的实现类或方法,用于构建特定的 HTTP 响应。以下是常用的 IHttpActionResult 实现及其对应的用途:

5.2.1 Ok

  • 返回 HTTP 状态码:200 OK
  • 用法
    • 用于返回一个成功的响应,并可以附带一个对象作为响应体。
public IHttpActionResult Get()
{
    var data = new { Id = 1, Name = "Example" };
    return Ok(data);
}

5.2.2 BadRequest

  • 返回 HTTP 状态码:400 Bad Request
  • 用法
    • 用于表示客户端发送的请求无效,例如参数验证失败或格式错误。
public IHttpActionResult Post(string value)
{
    if (string.IsNullOrEmpty(value))
    {
        return BadRequest("Value cannot be null or empty.");
    }
    return Ok();
}

5.2.3 Unauthorized

  • 返回 HTTP 状态码:401 Unauthorized
  • 用法
    • 用于指示需要身份验证或身份验证失败。
public IHttpActionResult Get()
{
    if (!User.Identity.IsAuthenticated)
    {
        return Unauthorized();
    }
    return Ok();
}

5.2.4 NotFound

  • 返回 HTTP 状态码:404 Not Found
  • 用法
    • 用于表示所请求的资源不存在。
public IHttpActionResult Get(int id)
{
    var item = _repository.GetItem(id);
    if (item == null)
    {
        return NotFound();
    }
    return Ok(item);
}

5.2.5 Conflict

  • 返回 HTTP 状态码:409 Conflict
  • 用法
    • 用于表示请求无法完成,因为发生了冲突(例如重复数据或违反约束)。
public IHttpActionResult Post(Item item)
{
    if (_repository.Contains(item.Id))
    {
        return Conflict();
    }
    _repository.Add(item);
    return Ok();
}

5.2.6 Created / CreatedAtRoute

  • 返回 HTTP 状态码:201 Created
  • 用法
    • 用于表示资源已成功创建,并可以附带新资源的 URI。
public IHttpActionResult Post(Item item)
{
    _repository.Add(item);
    return Created(new Uri(Request.RequestUri + "/" + item.Id), item);
}

// 或者使用 CreatedAtRoute 指定路由名称
public IHttpActionResult Post(Item item)
{
    _repository.Add(item);
    return CreatedAtRoute("DefaultApi", new { id = item.Id }, item);
}

5.2.7 NoContent

  • 返回 HTTP 状态码:204 No Content
  • 用法
    • 用于表示请求已成功处理,但不需要返回响应体内容(例如更新操作)。
public IHttpActionResult Put(int id, Item item)
{
    if (!_repository.Update(id, item))
    {
        return NotFound();
    }
    return StatusCode(HttpStatusCode.NoContent); // 或者直接 NoContent()
}

5.2.8 Redirect / RedirectToRoute

  • 返回 HTTP 状态码:302 Found 或其他重定向状态码
  • 用法
    • 用于表示需要重定向到另一个 URI。
public IHttpActionResult Get()
{
    return Redirect("https://www.example.com");
}

// 使用特定路由
public IHttpActionResult Get()
{
    return RedirectToRoute("DefaultApi", new { id = 1 });
}

5.2.9 InternalServerError

  • 返回 HTTP 状态码:500 Internal Server Error
  • 用法
    • 用于表示服务器内部发生错误。
public IHttpActionResult Get()
{
    try
    {
        // 处理逻辑
    }
    catch (Exception ex)
    {
        return InternalServerError(ex);
    }
}

5.2.10 ResponseMessage

  • 返回自定义的 HTTP 响应消息
  • 用法
    • 用于完全自定义 HTTP 响应,灵活构建响应消息。
public IHttpActionResult Get()
{
    var response = Request.CreateResponse(HttpStatusCode.OK, "Custom Message");
    return ResponseMessage(response);
}

5.2.11 StatusCode

  • 返回任意 HTTP 状态码
  • 用法
    • 用于返回特定的 HTTP 状态码,而不需要返回额外的内容。
public IHttpActionResult Delete(int id)
{
    _repository.Remove(id);
    return StatusCode(HttpStatusCode.NoContent); // 返回 204 No Content
}

5.2.12 Json

  • 返回 JSON 格式的响应
  • 用法
    • 用于直接返回 JSON 数据,而不依赖模型绑定。
public IHttpActionResult Get()
{
    var data = new { Id = 1, Name = "Example" };
    return Json(data);
}

5.2.13 ExceptionResult

  • 返回异常结果
  • 用法
    • 用于返回一个表示异常的响应。
public IHttpActionResult Get()
{
    try
    {
        throw new InvalidOperationException("An unexpected error occurred.");
    }
    catch (Exception ex)
    {
        return InternalServerError(ex); // 适用于返回异常信息的场景
    }
}

5.2.14 NotImplemented

  • 返回 HTTP 状态码:501 Not Implemented
  • 用法
    • 用于表示服务端还未实现某个功能。
public IHttpActionResult Get()
{
    return StatusCode(HttpStatusCode.NotImplemented);
}

5.2.15 总结

以下是常见的 IHttpActionResult 方法及其对应的 HTTP 状态码:

方法 HTTP 状态码 描述
Ok 200 OK 请求成功并返回数据。
BadRequest 400 Bad Request 客户端请求无效。
Unauthorized 401 Unauthorized 表示未通过身份验证。
NotFound 404 Not Found 资源不存在。
Conflict 409 Conflict 请求冲突(如违反约束)。
Created 201 Created 成功创建资源,并返回资源 URI。
NoContent 204 No Content 请求成功,但没有返回内容。
Redirect 302 Found 重定向到另一个 URI。
InternalServerError 500 Internal Server Error 服务器内部错误。
ResponseMessage 自定义状态码 返回自定义的 HTTP 响应消息。
StatusCode 任意状态码 返回指定的 HTTP 状态码。
Json 任意状态码 返回 JSON 响应内容。

通过这些方法,开发者可以灵活地编写符合 HTTP 规范的响应,满足各种 RESTful API 的需求。

6 标明返回类型

书接第五部分,返回类型如果使用IHttpActionResult接口,Swagger文档中无法解析出响应的具体内容,如下图所示。

如果希望显示响应内容,可以使用特性标明。

[SwaggerResponse(200, "Success", typeof(string[]))]
public IHttpActionResult Get()
{
    return Ok(new string[] { "value1", "value2" });
}

有关这方面的扩展内容很多,感兴趣可以自行查阅。

7 一键启动

在项目的Web.config文件同目录下创建一个.bat文件

.bat文件的内容如下,相关信息修改为适合本项目的内容。这里有一点,正常来说应该先启动IIS Express,再执行“浏览器访问URL”,但是启动IIS Express这个行为会阻塞到当前语句,不再往下执行,所以这里将“浏览器访问URL”语句提前,浏览器会等待IIS Express启动后访问成功。

@echo off
:: 设置IIS Express的路径(通常位于Program Files中,如果安装在其他位置,请调整路径)
set IIS_EXPRESS_PATH="C:\Program Files\IIS Express\iisexpress.exe"

:: 项目的物理路径,这条语句不需要修改,意为访问bat文件所在目录
cd /d "%~dp0"

:: Web项目的端口
set PORT=63027

:: 项目的启动URL(如果需要)
set URL=http://localhost:%PORT%/swagger/ui/index#/

:: 打开默认浏览器访问URL(可选)
start %URL%

:: 启动IIS Express
%IIS_EXPRESS_PATH% /path:"%cd%" /port:%PORT%

pause

双击该bat文件即可将项目内容自动配置到IIS服务中。

8 打包

选择“发布”。

发布位置选择“文件夹”。

点击“发布”。

生成的内容如下:

将“配置Swagger”中生成的xml文件拷到bin目录下,这是Swagger文档的基础,发布操作不会自动复制该文件,需要手动复制。然后将“一键启动”生成的.bat文件复制到Web.config文件同目录下,双击即可打开。

9 参考

.net framework中webapi使用swagger进行接口文档展示

ASP.NET WebApi项目框架搭建(一):创建项目

WebApi 接口返回值类型详解 ( 转 )

如果觉得文章还不错的话,请给一个大大的赞吧,感谢支持!

标签:WebApi,HTTP,return,string,Get,Framework,IHttpActionResult,Net,public
From: https://www.cnblogs.com/cunzai/p/18645924

相关文章

  • VSCODE报错:运行命令 remote-explorer.refresh 错误: Client network socket disconnec
    VSCODE报错:运行命令remote-explorer.refresh错误:ClientnetworksocketdisconnectedbeforesecureTLSconnectionwasestablished。这可能是由提交remote-explorer.refresh的扩展引起的。相关:https://blog.csdn.net/qq_44106037/article/details/139124149解决......
  • .NET 9 New features-JSON序列化
    .NET9已经发布有一段时间了,近期整理一下.NET9的新特性,今天重点分享.NET9JSON序列化方面的改进。先引用官方的说明:在 System.Text.Json 中,.NET9提供了用于序列化JSON的新选项和新的单一实例,可以更轻松地使用Web默认值进行序列化。举个实际的例子,缩进选项JsonSer......
  • .NET Core技术研究-HttpContext访问的正确方式
    将ASP.NET升级到ASP.NETCore之后,相信大家都会遇到HttpContext.Current无法使用的问题。这也是我们迁移ASP.NETCore必须解决的问题。先列一下使用HttpContext的具体场景:1.在Controller层访问HttpContext2.在中间件中使用HttpContext3.在数据访问层使用HttpContext4.在后......
  • ASP.NET Core技术研究-探秘依赖注入框架
    ASP.NETCore在底层内置了一个依赖注入框架,通过依赖注入的方式注册服务、提供服务。依赖注入不仅服务于ASP.NETCore自身,同时也是应用程序的服务提供者。毫不夸张的说,ASP.NETCore通过依赖注入实现了各种服务对象的注册和创建,同时也实现了面向抽象的编程模式和编程体验,提升了应用......
  • Kubernetes 资源管理
    Kubernetes资源管理本节先讲解Pod的两个重要参数:CPURequest与MemoryRequest。在大多数情况下,我们在定义Pod时并没有定义这两个参数,此时Kubernetes会认为该Pod所需的资源很少,并可以将其调度到任何可用的Node上。这样一来,当集群中的计算资源不很充足时,如果集群中的Pod负载突然加......
  • 【论文阅读笔记】IceNet算法与代码 | 低照度图像增强 | IEEE | 2021.12.25
    目录1导言2相关工作A传统方法B基于CNN的方法C交互方式3算法A交互对比度增强1)Gammaestimation2)颜色恢复3)个性化初始ηB损失函数1)交互式亮度控制损失2)熵损失3)平滑损失4)总损失C 实现细节4实验5IceNet环境配置和运行1下载代码2运行3训......
  • chrome浏览器network如何查看上一个页面的请求
    前言大家好,我是小徐啊。chrome浏览器是我们在JAVA开发中常用的浏览器,其中的console和network等,都是我们常用的功能。network中,是可以看到每次的请求的,包括请求的参数和返回的数据。但有时候,页面上请求之后,会有跳转的请求,导致看不到上一个页面的请求。其实,我们可以设置的,那么,该如......
  • .NET Core 注入依赖
    .NETCore是一个现代化的、跨平台的框架,提供了构建高性能和可扩展应用程序的工具。依赖注入(DependencyInjection,DI)和中间件(Middleware)是.NETCore框架中两个核心的概念,它们在应用程序的架构中扮演着关键的角色。本文将详细探讨这两个概念,并展示如何在.NETCore应用程序中有......
  • .net6 WebApi 使用特性实现自动依赖注入
    首先搞三个特性类///<summary>///作用域///</summary>[AttributeUsage(AttributeTargets.Class)]publicclassDiScopedAttribute:Attribute{}///<summary>///单例///</summary>[AttributeUsage(AttributeTargets.Class)]publicclassDiSing......
  • Kubernetes iptables与IPVS 负载均衡模式对比
    Kubernetes可以使用iptables或IPVS作为其服务负载均衡模式。两者有各自的特点和适用场景。以下是对它们的比较和选择建议:1.iptables模式特点基于规则匹配:iptables是基于链表结构的包过滤和NAT实现方式。每个请求都会逐条匹配规则,直到找到匹配项。易用性:适合......