【WebApi】C#创建WebApi学习

1、创建WebApi项目

Prgram.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使用

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:将路由写在方法前面并指定操作动词

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:将路由写在类前面,再在方法前面指定操作动词

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]也可以省略

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

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

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

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

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

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

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

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

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

 [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

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()

 [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

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

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 下载安装Sql Server Developer Edition和SQL Server Management Studio

Sql Server Developer Edition

SQL Server Management Studio

打开SQL Server Management Studio连接本地数据库

12.2 安装需要使用的包

  • EntityFrameworkCore
  • EntityFrameworkCore.Design
  • EntityFrameworkCore.Tools
  • EntityFrameworkCore.SqlServer

1)打开 管理NuGet程序包

2)搜索安装指定的包

3)双击查看是否安装成功

12.3 创建数据库上下文

1)创建脚本ApplicationDbContext

using Microsoft.EntityFrameworkCore; using WebApiDemo.Models; namespace WebApiTest.Data { public class ApplicationDbContext : DbContext { public DbSet<Shirt> Shirts { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); //数据播种 modelBuilder.Entity<Shirt>().HasData( new Shirt { Id = 1, Name = "衬衫1", Color = "red", Gender = "men", Size = 10, Price = 100 }, new Shirt { Id = 2, Name = "衬衫2", Color = "blue", Gender = "men", Size = 12, Price = 140 }, new Shirt { Id = 3, Name = "衬衫3", Color = "黑色", Gender = "wemen", Size = 11, Price = 132 }, new Shirt { Id = 4, Name = "衬衫4", Color = "白色", Gender = "wemen", Size = 7, Price = 151 } ); } } } 

12.4 执行数据库迁移

1)添加连接字符串

2)获取连接字符串,视图->服务器资源管理器->数据连接

//需要将master替换为需要创建的数据库名称 Data Source=(local);Initial Catalog=master;Integrated Security=True;Trust Server Certificate=True

3)数据库上下文中创建构造函数指定连接数据库位置

using Microsoft.EntityFrameworkCore; using WebApiDemo.Models; namespace WebApiTest.Data { public class ApplicationDbContext : DbContext { public ApplicationDbContext(DbContextOptions options) : base(options) { } public DbSet<Shirt> Shirts { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); //数据播种 modelBuilder.Entity<Shirt>().HasData( new Shirt { Id = 1, Name = "衬衫1", Color = "red", Gender = "men", Size = 10, Price = 100 }, new Shirt { Id = 2, Name = "衬衫2", Color = "blue", Gender = "men", Size = 12, Price = 140 }, new Shirt { Id = 3, Name = "衬衫3", Color = "黑色", Gender = "wemen", Size = 11, Price = 132 }, new Shirt { Id = 4, Name = "衬衫4", Color = "白色", Gender = "wemen", Size = 7, Price = 151 } ); } } }

4)在Progam.cs添加运行EntityFrameworkCore所需的服务

builder.Services.AddDbContext<ApplicationDbContext>(options => { options.UseSqlServer(builder.Configuration.GetConnectionString("ShirtStoreManagement")); });

5)创建迁移代码并进行迁移

控制台运行命令Add-Migration Init(Init可以替换为该次进行操作说明)

运行成功会创建在迁移文件夹下创建迁移代码

在控制台运行迁移代码,Update-Database Init(Init为迁移代码名称,不指定会执行最新的代码)

执行成功可以在查看数据库创建成功

12.5 使用EF Core实现Get端点

在ShirtsController构造函数中依赖注入Db上下文

 //获取所有衬衫数据列表 [HttpGet] public IActionResult GetShirts() { return Ok(db.Shirts.ToList()); }

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

修改Shirt_ValidateShirtIdFilterAttribute,实现验证ID在数据库是否存在

using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using WebApiTest.Data; namespace WebApiTest.Filters.ActionFilters { public class Shirt_ValidateShirtIdFilterAttribute : ActionFilterAttribute { private readonly ApplicationDbContext db; public Shirt_ValidateShirtIdFilterAttribute(ApplicationDbContext db) { this.db = db; } 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 ValidationProblemDetails(context.ModelState) { Status = 400, Title = "请求参数错误", }; context.Result = new BadRequestObjectResult(problemDetails); } else { var shirt = db.Shirts.Find(id.Value); if(shirt == null) { context.ModelState.AddModelError("Id", $"ID为{id.Value}的衬衫在数据库不存在"); var problemDetails = new ValidationProblemDetails(context.ModelState) { Status = 400, Title = "衬衫ID不存在", }; context.Result = new NotFoundObjectResult(problemDetails); } else { context.HttpContext.Items["shirt"] = shirt; } } } } } } 

在操作过滤器中查询数据库存在ID衬衫在context.HttpContext.Items中进行存在,然后在控制器中获取,避免重复进行数据库查询减少性能开销

控制器查询代码

 //获取指定ID的衬衫数据 [HttpGet("{id}")] [TypeFilter(typeof(Shirt_ValidateShirtIdFilterAttribute))] public IActionResult GetShirtById([FromRoute]int id) { //正确响应 return Ok(HttpContext.Items["shirt"]); }

12.7 使用EF Core实现Post端点

 //创建一件新的衬衫 [HttpPost] public IActionResult CreateShirt([FromBody]Shirt shirt) { this.db.Shirts.Add(shirt); this.db.SaveChanges(); return CreatedAtAction(nameof(GetShirtById), new { id = shirt.Id}, shirt); }

12.8 使用EF Core实现Put端点

修改代码Shirt_HandleUpdateExceptionFilterAttribute,实现验证当前ID数据是否还存在,可能存在当前操作之前数据被删除的可能

using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using WebApiTest.Data; namespace WebApiTest.Filters.ExceptionFilters { public class Shirt_HandleUpdateExceptionFilterAttribute : ExceptionFilterAttribute { private readonly ApplicationDbContext db; public Shirt_HandleUpdateExceptionFilterAttribute(ApplicationDbContext db) { this.db = db; } 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 (this.db.Shirts.FirstOrDefault(x => x.Id == shirtId) == null) { context.ModelState.AddModelError("Id", $"衬衫已经在数据库不存在,可能在此之前被删除了"); var problemDetails = new ValidationProblemDetails(context.ModelState) { Status = StatusCodes.Status404NotFound, }; context.Result = new NotFoundObjectResult(problemDetails); } } } } } 

控制器更新代码

 //更新指定ID的衬衫数据 [HttpPut("{id}")] [TypeFilter(typeof(Shirt_ValidateShirtIdFilterAttribute))] [TypeFilter(typeof(Shirt_HandleUpdateExceptionFilterAttribute))] public IActionResult UpdateShirt(int id, [FromBody]Shirt shirt) { var shirtToUpdate = HttpContext.Items["shirt"] as Shirt; shirtToUpdate.Name = shirt.Name; shirtToUpdate.Size = shirt.Size; shirtToUpdate.Color = shirt.Color; shirtToUpdate.Gender = shirt.Gender; shirtToUpdate.Price = shirt.Price; this.db.SaveChanges(); return Ok($"ID为{id}衬衫更新成功"); }

12.9 使用EF Core实现Delete端点

 //删除指定ID的衬衫数据 [HttpDelete("{id}")] [TypeFilter(typeof(Shirt_ValidateShirtIdFilterAttribute))] public IActionResult DeleteShirt(int id) { var shirtToDelete = HttpContext.Items["shirt"] as Shirt; this.db.Shirts.Remove(shirtToDelete); this.db.SaveChanges(); return Ok(shirtToDelete); }

13、Web Api安全机制,使用JWT生成令牌和验证令牌

1)创建应用程序信息类,Application.cs

namespace WebApiDemo.Authority { public class Application { public int ApplicationId { get; set; } public string? ApplicationName { get; set; } public string? ClientId { get; set; } public string? Secret { get; set; } public string? Scopes { get; set; } } } 

2)创建应用内容存储,AppPepository.cs,替代已存储数据库的应用程序注册信息

namespace WebApiDemo.Authority { public static class AppPepository { private static List<Application> _applications = new List<Application> { new Application { ApplicationId = 1, ApplicationName = "MVCWebApp", ClientId = "53D3C1E6-4587-4AD5-8C6E-A8E4BD59940E", Secret = "0673FC70-0514-4011-B4A3-DF9BC03201BC", Scopes = "read,write,delete" } }; public static Application? GetApplicationByClientId(string clientId) { return _applications.FirstOrDefault(app => app.ClientId == clientId); } } } 

3)创建应用凭证类,AppCredential.cs,用于接受认证请求参数

namespace WebApiDemo.Authority { public class AppCredential { public string? ClientId { get; set; } = string.Empty; public string? Secret { get; set; } = string.Empty; } } 

4)创建应用认证控制器接口,AuthorityController.cs

using Microsoft.AspNetCore.Mvc; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; using System.Text; using WebApiDemo.Authority; namespace WebApiDemo.Controllers { [ApiController] public class AuthorityController : ControllerBase { private readonly IConfiguration configuration; public AuthorityController(IConfiguration configuration) { this.configuration = configuration; } [HttpPost("auth")] public IActionResult Authenticate([FromBody] AppCredential credential) { if (Authenticator.Authenticate(credential.ClientId, credential.Secret)) { var expiresAt = DateTime.UtcNow.AddMinutes(10); return Ok(new { access_token = Authenticator.CreateToken(credential.ClientId, expiresAt, configuration["SecurityKey"] ?? string.Empty), expores_at = expiresAt }); } else { ModelState.AddModelError("Unanthorized", "未被授权"); var problemDetails = new ValidationProblemDetails(ModelState) { Status = StatusCodes.Status401Unauthorized, }; return new UnauthorizedObjectResult(problemDetails); } } } } 

5)设置密钥

6)创建应用认证身份验证逻辑类,Authenticator.cs

using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; using System.Security.Claims; namespace WebApiDemo.Authority { public static class Authenticator { public static bool Authenticate(string clientId, string secret) { var app = AppPepository.GetApplicationByClientId(clientId); if (app == null) return false; return (app.ClientId == clientId && app.Secret == secret); } public static string CreateToken(string clientId, DateTime expiresAt, string strSecretKey) { //安全算法 //签名密钥 //负载(声明) //生成签名 //算法 var signingCredentials = new SigningCredentials( new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(strSecretKey)), SecurityAlgorithms.HmacSha256Signature); //负载(声明) var app = AppPepository.GetApplicationByClientId(clientId); var clamsDictionary = new Dictionary<string, object> { { "AppName", app?.ApplicationName??string.Empty }, //{ "Read", (app?.Scopes??string.Empty).Contains("read") ? "true" : "false" }, //{ "Write", (app?.Scopes??string.Empty).Contains("write") ? "true" : "false" } }; var scopes = app?.Scopes?.Split(',') ?? Array.Empty<string>(); if(scopes.Length > 0) { foreach(var scope in scopes) { clamsDictionary.Add(scope.Trim().ToLower(), "true"); } } var tokenDescriptor = new SecurityTokenDescriptor { SigningCredentials = signingCredentials, Claims = clamsDictionary, Expires = expiresAt, NotBefore = DateTime.UtcNow, }; var tokenHandler = new JsonWebTokenHandler(); return tokenHandler.CreateToken(tokenDescriptor); } public static async Task<IEnumerable<Claim>?> VerifyTokenAsync(string tokenString, string securityKey) { if(string.IsNullOrWhiteSpace(tokenString) || string.IsNullOrWhiteSpace(securityKey)) { return null; } var keyBytes = System.Text.Encoding.UTF8.GetBytes(securityKey); var tokenHandle = new JsonWebTokenHandler(); var validationParameters = new TokenValidationParameters { ValidateIssuer = false, IssuerSigningKey = new SymmetricSecurityKey(keyBytes), ValidateIssuerSigningKey = false, ValidateAudience = false, ValidateLifetime = true, ClockSkew = TimeSpan.Zero }; try { var result = await tokenHandle.ValidateTokenAsync(tokenString, validationParameters); if(result.SecurityToken != null) { var tokenObject = tokenHandle.ReadJsonWebToken(tokenString); return tokenObject.Claims ?? Enumerable.Empty<Claim>(); } else { return null; } } catch (SecurityTokenMalformedException) { return null; } catch (SecurityTokenExpiredException) { return null; } catch (SecurityTokenInvalidSignatureException) { return null; } catch (Exception) { throw; } } } } 

7)通过过滤器方式实现JWT令牌验证

using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using WebApiDemo.Attributes; using WebApiDemo.Authority; namespace WebApiDemo.Filters.AuthFilters { public class JwtTokenAuthFilterAttribute : Attribute, IAsyncAuthorizationFilter { public async Task OnAuthorizationAsync(AuthorizationFilterContext context) { //1. 从请求头中获取授权标识 if (!context.HttpContext.Request.Headers.TryGetValue("Authorization", out var authHeader)) { context.Result = new UnauthorizedResult(); return; } string tokenString = authHeader.ToString(); //2. 去掉Bearer前缀 if (tokenString.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)) { tokenString = tokenString.Substring("Bearer ".Length).Trim(); } else { context.Result = new UnauthorizedResult(); return; } //3. 获取配置和安全密钥 var configuration = context.HttpContext.RequestServices.GetService<IConfiguration>(); var securityKey = configuration?["SecurityKey"] ?? string.Empty; //4. 验证令牌 并且 提取声明 //if(!await Authenticator.VerifyTokenAsync(tokenString, securityKey)) //{ // context.Result = new UnauthorizedResult(); //} var claims = await Authenticator.VerifyTokenAsync(tokenString, securityKey); if (claims == null) { context.Result = new UnauthorizedResult(); // 无效令牌 401 } else { //5. 获取声明需求 var requiredClaism = context.ActionDescriptor.EndpointMetadata .OfType<RequiredClaimAttribute>() .ToList(); if(requiredClaism != null && !requiredClaism.All(rc => claims.Any(c => c.Type.Equals(rc.ClaimType, StringComparison.OrdinalIgnoreCase) && c.Value.Equals(rc.ClaimValue, StringComparison.OrdinalIgnoreCase)))) { context.Result = new StatusCodeResult(403); // 权限不足 403 } } } } } 

8)授权、权限作用域校验类,RequiredClaimAttribute.cs

namespace WebApiDemo.Attributes { [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class,AllowMultiple = true)] public class RequiredClaimAttribute : Attribute { public string ClaimType { get; } public string ClaimValue { get; } public RequiredClaimAttribute(string claimType, string claimValue) { this.ClaimType = claimType; this.ClaimValue = claimValue; } } } 

Read more

GitHub Copilot Workspace 100万Token上下文:大型项目的变革者还是营销噱头?

GitHub Copilot Workspace 100万Token上下文:大型项目的变革者还是营销噱头?

文章目录 * 前言 * 一、技术实现背后的逻辑与价值 * 二、实际使用效果与局限性分析 * 三、行业影响与发展趋势展望 * 总结 前言 大型项目开发者的噩梦被这100万Token破解了。 就在2026年3月22日,Hacker News上一场热议引爆技术圈,GitHub Copilot Workspace推出100万Token上下文支持,声称能彻底解决大型项目开发的痛点。有人称赞这是大型项目的变革者,也有人认为噱头大于实用。 作为每天都在与代码打交道的程序员,我们都知道大型项目开发的痛苦,那些反复切换窗口的时刻,那些因为上下文缺失而导致的错误修改,那些新人需要花费数周才能上手的漫长过程。现在AI技术承诺要改变这一切,但我们需要冷静看待其中的机遇与挑战。 一、技术实现背后的逻辑与价值 GitHub Copilot Workspace是由OpenAI的GPT系列模型提供支持的AI驱动开发环境,核心定位是帮助开发者用自然语言完成代码的规划构建和测试。开源方面,Copilot Extension for VSCode已开源采用MIT许可证,但Workspace核

GitHub Copilot 学生认证详细教程

GitHub Copilot 学生认证详细教程

GitHub Copilot 是 GitHub 提供的 AI 代码助手工具,学生可以通过 GitHub Student Developer Pack(学生开发者包)免费获取 Copilot Pro 版本(通常每月收费 10 美元)。这个过程涉及验证你的学生身份,一旦通过,你可以免费使用 Copilot Pro,直到你的学生身份到期(通常每年需要重新验证)。以下是最详细的教程,基于 GitHub 官方文档和社区指南,涵盖从准备到激活的所有步骤。我会逐步分解,确保每个步骤都清晰、可操作。如果你是第一次申请,预计整个过程可能需要 1-3 天(验证通常在 72 小时内完成)。 第一部分:资格要求和准备工作 在开始前,确保你符合条件。如果不符合,申请会被拒绝。 * 资格标准: * 你必须是当前在读学生,

AI 智能编码工具:重塑开发效率的革命,从 GitHub Copilot 到国产新秀的全面解析

AI 智能编码工具:重塑开发效率的革命,从 GitHub Copilot 到国产新秀的全面解析

目录 引言 一、主流智能编码工具深度测评:从功能到实战 1. GitHub Copilot:AI 编码的 “开山鼻祖” 核心特性与实战代码 优缺点总结 2. Baidu Comate:文心大模型加持的 “国产之光” 核心特性与实战代码 优缺点总结 3. 通义灵码:阿里云的 “企业级编码助手” 核心特性与实战代码 优缺点总结 引言 作为一名拥有 8 年开发经验的程序员,我曾无数次在深夜对着屏幕反复调试重复代码,也因记不清框架语法而频繁切换浏览器查询文档。直到 2021 年 GitHub Copilot 问世,我才第一次感受到:AI 不仅能辅助编码,更能彻底改变开发模式。如今,智能编码工具已从 “尝鲜选项” 变为 “必备工具”,它们像经验丰富的结对编程伙伴,能精准补全代码、生成测试用例、

一篇了解Copilot pro使用的笔记

一篇了解Copilot pro使用的笔记

当前AI 程序员已经默许了,除了使用国内外的那些头部Chat。Agent 模态已经肆意发展,因为随着AI的加成,大家都越来越主动或被动“效率起飞”。下面聊一下Copilot Pro的使用吧。 使用这个也就几个月吧,不谈购买心酸史,已经直接官网10刀了。这次也算开始心疼了,先研究一下这到底怎么用才不暴殄天物也不小才大用吧。哈哈,为了那该死的性价比~ 1.关于copilot pro(个人账号)可供使用的头端模型界面 (手机没拍好) 看起来可用的后端模型挺多的,各家各路,选啥自己整。但却不是按照时间来计算,明显的“流量”限制,就是官网说的访问配额。 x = 相对消耗倍率(Cost / Compute Weight Multiplier),它不是速度,也不是性能评分,而是: “使用该模型一次,相当于基础模型消耗的多少倍额度”。 还有: (1)先说每个模型后面的那个数字0X 0x 不是 免费无限用 而是 不单独计入