【WebApi】C#创建WebApi学习

1、创建WebApi项目

Prgram.cs代码保留如下

cs 复制代码
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

var app = builder.Build();

// Configure the HTTP request pipeline.

app.UseHttpsRedirection();

app.Run();

2、Minmal APIs最小API使用

Prgram.cs中进行最小API使用

cs 复制代码
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

var app = builder.Build();

// Configure the HTTP request pipeline.

app.UseHttpsRedirection();

//获取所有衬衫数据列表
app.MapGet("/shirts", () =>
{
    return "获取所有衬衫数据列表";
});

//获取指定ID的衬衫数据
app.MapGet("/shirts/{id}", (int id) =>
{
    return $"获取ID为 {id} 的衬衫数据";
});

//创建一件新的衬衫
app.MapPost("/shirts", () =>
{
    return "创建一件新的衬衫";
});

//更新指定ID的衬衫数据
app.MapPut("/shirts/{id}", (int id) =>
{
    return $"更新ID为 {id} 的衬衫数据";
});

//删除指定ID的衬衫数据
app.MapDelete("/shirts/{id}", (int id) =>
{
    return $"删除ID为 {id} 的衬衫数据";
});

app.Run();

3、ASP.NET Core中间件管道

app中的Use开头的方法都是中间件组件使用方法

4、Web API控制器实现Web API

方法1:将路由写在方法前面并指定操作动词

cs 复制代码
using Microsoft.AspNetCore.Mvc;

namespace WebApiTest.Controllers
{
    [ApiController]
    public class ShirtsController : ControllerBase
    {
        //获取所有衬衫数据列表
        [HttpGet]
        [Route("api/shirts")]
        public string GetShirts()
        {
            return "获取所有衬衫数据列表";
        }

        //获取指定ID的衬衫数据
        [HttpGet]
        [Route("api/shirts/{id}")]
        public string GetShirtById(int id)
        {
            return $"获取ID为 {id} 的衬衫数据";
        }

        //创建一件新的衬衫
        [HttpPost]
        [Route("api/shirts")]
        public string CreateShirt()
        {
            return "创建一件新的衬衫";
        }

        //更新指定ID的衬衫数据
        [HttpPut]
        [Route("api/shirts/{id}")]
        public string UpdateShirt(int id)
        {
            return $"更新ID为 {id} 的衬衫数据";
        }

        //删除指定ID的衬衫数据
        [HttpDelete]
        [Route("api/shirts/{id}")]
        public string DeleteShirt(int id)
        {
            return $"删除ID为 {id} 的衬衫数据";
        }
    }
}

方法2:将路由写在类前面,再在方法前面指定操作动词

cs 复制代码
using Microsoft.AspNetCore.Mvc;

namespace WebApiTest.Controllers
{
    [ApiController]
    [Route("/api/[controller]")]
    public class ShirtsController : ControllerBase
    {
        //获取所有衬衫数据列表
        [HttpGet]
        public string GetShirts()
        {
            return "获取所有衬衫数据列表";
        }

        //获取指定ID的衬衫数据
        [HttpGet("{id}")]
        public string GetShirtById(int id)
        {
            return $"获取ID为 {id} 的衬衫数据";
        }

        //创建一件新的衬衫
        [HttpPost]
        public string CreateShirt()
        {
            return "创建一件新的衬衫";
        }

        //更新指定ID的衬衫数据
        [HttpPut("{id}")]
        public string UpdateShirt(int id)
        {
            return $"更新ID为 {id} 的衬衫数据";
        }

        //删除指定ID的衬衫数据
        [HttpDelete("{id}")]
        public string DeleteShirt(int id)
        {
            return $"删除ID为 {id} 的衬衫数据";
        }
    }
}

5、基于控制器的Web API的路由

使用注解[Route("/shirts")]设置Web API的URL,可以在方法前使用,也可以在类前使用

方法前

类前

6、模型绑定,将Http请求中的数据映射到操作方法的参数

6.1 从路由绑定,在路由Route("/shirts/{id}")或在操作动词HttpGet("{id}")设置,在方法参数前设置[FromRoute]也可以省略

cs 复制代码
        [HttpGet("{id}")]
        public string GetShirtById([FromRoute]int id)
        {
            return $"获取ID为 {id} 的衬衫数据";
        }

6.2 从查询字符串中绑定,方法参数前使用注解[FromQuery]

http://localhost:5186/api/shirts/1?color=红色

cs 复制代码
        [HttpGet("{id}")]
        public string GetShirtById([FromRoute]int id, [FromQuery]string color)
        {
            return $"获取ID为 {id} 的衬衫数据";
        }

6.3 从请求头Header中绑定,方法参数前使用注解[FromHeader]

cs 复制代码
        [HttpGet("{id}")]
        public string GetShirtById([FromRoute]int id, [FromQuery]string color, [FromHeader]int size)
        {
            return $"获取ID为 {id} 的衬衫数据,衬衫颜色为{color},大小为{size}";
        }

6.4 从请求体Body JSON格式中绑定,方法参数前使用注解[FromBody]

cs 复制代码
        [HttpPost]
        public string CreateShirt([FromBody]Shirt shirt)
        {
            return $"创建一件新的衬衫,{shirt.Id}, {shirt.Name}, {shirt.Color}, {shirt.Gender}, {shirt.Price}";
        }

6.5 从请求体Body 表单中绑定,方法参数前使用注解[FromForm]

cs 复制代码
        [HttpPost]
        public string CreateShirt([FromForm]Shirt shirt)
        {
            return $"创建一件新的衬衫,{shirt.Id}, {shirt.Name}, {shirt.Color}, {shirt.Gender}, {shirt.Price}";
        }

7、数据注解模型验证

8、ValidationAtteibute模型验证,继承ValidationAttribute

创建脚本Shirt_EnsureCorrectSizingAttribute.cs

cs 复制代码
using System.ComponentModel.DataAnnotations;
using WebApiDemo.Models;

namespace WebApiTest.Models.Validations
{
    public class Shirt_EnsureCorrectSizingAttribute : ValidationAttribute
    {
        protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)
        {
            var shirt = validationContext.ObjectInstance as Shirt;
            if(shirt != null && !string.IsNullOrEmpty(shirt.Gender))
            {
                if(shirt.Gender.Equals("men", StringComparison.OrdinalIgnoreCase) && shirt.Size < 8)
                {
                    return new ValidationResult("男性衬衫的尺码必须大于或等于8。");
                }
                else if (shirt.Gender.Equals("women", StringComparison.OrdinalIgnoreCase) && shirt.Size < 6)
                {
                    return new ValidationResult("女性衬衫的尺码必须大于或等于6。");
                }
            }

            return ValidationResult.Success;
        }
    }
}

在属性前添加注解

9、Web API返回类型

返回类型使用IActionResult

正确返回使用 Ok(返回数据)

未找到使用 NotFound()

错误响应使用 BadRequest()

cs 复制代码
        [HttpGet("{id}")]
        public IActionResult GetShirtById([FromRoute]int id, [FromQuery]string color, [FromHeader]int size)
        {
            if(id <= 0)
            {
                //错误响应
                return BadRequest();
            }
            else if(id > 10)
            {
                //未找到
                return NotFound();
            }

            //正确响应
            return Ok($"获取ID为 {id} 的衬衫数据,衬衫颜色为{color},大小为{size}");
        }

10、操作过滤器进行模型验证,继承ActionFilterAttribute

用户输入传递的id可能不符合规范,可以通过操作过滤器进行模型验证对id进行验证

创建脚本Shirt_ValidateShirtIdFilterAttribute

cs 复制代码
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace WebApiTest.Filters.ActionFilters
{
    public class Shirt_ValidateShirtIdFilterAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            base.OnActionExecuting(context);

            var id = context.ActionArguments["id"] as int?;
            if (id.HasValue)
            {
                if(id.Value <= 0)
                {
                    context.ModelState.AddModelError("Id", "衬衫ID必须大于0。");
                    var problemDetails = new Microsoft.AspNetCore.Mvc.ValidationProblemDetails(context.ModelState)
                    {
                        Status = 400,
                        Title = "请求参数错误",
                    };
                    context.Result = new BadRequestObjectResult(problemDetails);
                }
            }
        }
    }
}

需要使用验证的方法前添加注解

11、异常过滤器实现异常处理

更新衬衫之前可能其他请求把该衬衫已经删掉,更新时可能会报错,模拟该情景

创建脚本Shirt_HandleUpdateExceptionFilterAttribute

cs 复制代码
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace WebApiTest.Filters.ExceptionFilters
{
    public class Shirt_HandleUpdateExceptionFilterAttribute : ExceptionFilterAttribute
    {
        public int?[] shirtsId = new int?[] { 1, 2, 3, 4, 5 };

        public override void OnException(ExceptionContext context)
        {
            base.OnException(context);

            //判断衬衫ID是否存在 暂时假设shirtsId为数据库中已有的衬衫ID列表
            var strShirtId = context.RouteData.Values["id"] as string;
            if (int.TryParse(strShirtId, out int shirtId))
            {
                if (shirtsId.FirstOrDefault(x => x == shirtId) == null)
                {
                    context.ModelState.AddModelError("Id", $"衬衫已经不存在");
                    var problemDetails = new ValidationProblemDetails(context.ModelState)
                    {
                        Status = StatusCodes.Status404NotFound,
                    };
                    context.Result = new NotFoundObjectResult(problemDetails);
                }
            }
        }
    }
}

在需要异常处理的方法前使用

12、Web API操作数据库

案例使用SqlServer数据库

12.1 安装需要使用的包

12.2 创建数据库上下文

12.3 执行数据库迁移

12.4 使用EF Core实现Get端点

12.5 使用EF Core实现Get by Id端点

12.6 使用EF Core实现Post端点

12.7 使用EF Core实现Put端点

12.8 使用EF Core实现Delete端点

相关推荐
似水明俊德3 小时前
02-C#.Net-反射-面试题
开发语言·面试·职场和发展·c#·.net
阿蒙Amon4 小时前
C#常用类库-详解SerialPort
开发语言·c#
似水明俊德6 小时前
02-C#.Net-反射-学习笔记
开发语言·笔记·学习·c#·.net
.NET修仙日记11 小时前
Acme.ReturnOh:让.NET API返回值处理更优雅,统一响应格式一步到位
c#·.net·webapi
阿蒙Amon13 小时前
C#常用类库-详解YamlDotNet
开发语言·c#
Sunsets_Red15 小时前
乘法逆元的 exgcd 求法
c++·学习·数学·算法·c#·密码学·信息学竞赛
唐青枫16 小时前
深入理解 C#.NET TaskScheduler:为什么大量使用 Work-Stealing
c#·.net
人工智能AI技术16 小时前
Claude 3.7 企业版私有化部署技术验证:与 .NET 实战方案
人工智能·c#
呆子也有梦17 小时前
思考篇:积分是存成道具还是直接存数值?——ET/Skynet 框架下,从架构权衡到代码实现全解析
游戏·架构·c#·lua
我是唐青枫17 小时前
深入理解 C#.NET Task.Run:调度原理、线程池机制与性能优化
性能优化·c#·.net