c# - 带有正确 HTTP 状态代码的 Web API PUT 返回对象
问题描述
首先,我想说[HttpGet]
,[HttpGet("{id}")]
和[HttpPost]
工作正常。但是,我遇到了一个挑战[HttpPut]
,几乎在我看到的所有地方,解决方案都是在没有状态码的情况下返回。
我正在使用 Visual Studio 2019,项目类型为“ASP.NET Core Web 应用程序”和“API”(ASP.NET Core 3.1)。
我还在同一个 Visual Studio 解决方案中使用类型(C#)“类库(.NET 标准)”的辅助项目。
我正在使用 Postman 来测试 http 请求调用。
需要安装以下(附加)NuGet 包:
- Microsoft.EntityFrameworkCore
- Microsoft.EntityFrameworkCore.InMemory
- System.ComponentModel.Annotations
解决方案资源管理器:
.net 核心包含很多代码,我将在这里全部展示(至于发生了哪些变化)。
项目“CoreStudy.Api”代码:
启动.cs
using CoreStudy.Data.Context;
using CoreStudy.Data.Repository;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace CoreStudy.Api
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddScoped<PeopleRepository>(); // add this line
services.AddDbContext<PersonContext>(opt => opt.UseInMemoryDatabase("PeopleInventory")); // add this line, requires NuGet package "Microsoft.EntityFrameworkCore.InMemory"
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
人控制器.cs
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using CoreStudy.Data.Repository;
using CoreStudy.Data.Models;
using Microsoft.AspNetCore.Http;
namespace CoreStudy.Api.Controllers
{
[Route("people")]
[ApiController]
public class PeopleController : ControllerBase
{
private readonly PeopleRepository _repository;
public PeopleController(PeopleRepository repository)
{
_repository = repository;
}
[HttpGet]
[ProducesResponseType(typeof(List<PersonModel>), StatusCodes.Status200OK)]
public IActionResult GetPeople()
{
return Ok(_repository.GetPeople());
}
[HttpGet("{id}")]
[ProducesResponseType(typeof(PersonModel), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IActionResult GetPersonById(int id)
{
var person = _repository.GetPersonById(id);
if (person == null)
{
return NotFound();
}
return Ok(person);
}
[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> AddPersonAsync([FromBody] PersonModel person)
{
if((_repository.GetPersonById(person.id) != null) || String.IsNullOrWhiteSpace(person.name))
{
return BadRequest();
}
int peopleAdded = await _repository.AddPersonAsync(person);
return CreatedAtAction(nameof(GetPersonById), new { person.id }, person);
}
[HttpPut]
[ProducesResponseType(typeof(PersonModel), StatusCodes.Status202Accepted)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> ChangePersonNameByIdAsync([FromBody] PersonModel person)
{
if (_repository.GetPersonById(person.id) == null)
{
return NotFound();
}
else if (String.IsNullOrWhiteSpace(person.name))
{
return BadRequest();
}
PersonModel updatedPerson = await _repository.ChangePersonNameAsync(person);
return Ok(updatedPerson);
}
}
}
项目“CoreStudy.Data”代码:
PersonContext.cs
using Microsoft.EntityFrameworkCore;
using CoreStudy.Data.Models;
namespace CoreStudy.Data.Context
{
public class PersonContext : DbContext
{
public PersonContext(DbContextOptions<PersonContext> options) : base(options)
{
}
public DbSet<PersonModel> people { get; set; }
}
}
人模型.cs
using System.ComponentModel.DataAnnotations;
namespace CoreStudy.Data.Models
{
public class PersonModel
{
public int id { get; set; }
[Required]
public string name { get; set; }
public string position { get; set; }
public PersonModel() { }
public PersonModel(string name, string position)
{
this.name = name;
this.position = position;
}
public PersonModel(int id, string name, string position)
{
this.id = id;
this.name = name;
this.position = position;
}
}
}
PeopleRepository.cs
using System.Collections.Generic;
using CoreStudy.Data.Models;
using CoreStudy.Data.Context;
using System.Linq;
using System.Threading.Tasks;
namespace CoreStudy.Data.Repository
{
public class PeopleRepository
{
private readonly PersonContext context;
public PeopleRepository(PersonContext context)
{
this.context = context;
if (context.people.Count() == 0)
{
context.people.AddRange(
new PersonModel
{
name = "shaggy",
position = "screwball"
},
new PersonModel
{
name = "scooby",
position = "screwball dog"
},
new PersonModel
{
name = "fred",
position = "leader"
},
new PersonModel
{
name = "velma",
position = "smart one"
},
new PersonModel
{
name = "daphne",
position = "popular one"
});
context.SaveChanges();
}
}
public List<PersonModel> GetPeople()
{
return context.people.ToList();
}
public PersonModel GetPersonById(int id)
{
PersonModel person = context.people.Find(id); // null if not found
return person;
}
public async Task<int> AddPersonAsync(PersonModel person)
{
int rowsAffected = 0;
context.people.Add(person);
rowsAffected = await context.SaveChangesAsync();
return rowsAffected;
}
public async Task<PersonModel> ChangePersonNameAsync(PersonModel person)
{
context.people.Update(person);
await context.SaveChangesAsync();
return GetPersonById(person.id);
}
}
}
尝试使用邮递员发出 PUT 请求时,出现以下错误:
问题出在以下两个片段之一中:
public async Task<PersonModel> ChangePersonNameAsync(PersonModel person)
{
context.people.Update(person); // I thought Update() would be best used here, but not sure
await context.SaveChangesAsync();
return GetPersonById(person.id);
}
[HttpPut]
[ProducesResponseType(typeof(PersonModel), StatusCodes.Status202Accepted)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> ChangePersonNameByIdAsync([FromBody] PersonModel person)
{
if (_repository.GetPersonById(person.id) == null)
{
return NotFound();
}
else if (String.IsNullOrWhiteSpace(person.name))
{
return BadRequest();
}
PersonModel updatedPerson = await _repository.ChangePersonNameAsync(person);
return Ok(updatedPerson); // not sure if I should be using Ok() for a PUT
}
如果有人能帮我解决这个问题,我自己(我敢肯定互联网上的大部分人)会感谢你的。
解决方案
这已经获得了实体:
if (_repository.GetPersonById(person.id) == null) { ... }
所以你需要得到这个结果:
var personDB = _repository.GetPersonById(person.id);
然后检查变量是否为null
if(personDB != null) { ... }
然后,您将需要personDB
使用人员(来自 PUT 参数)值更改属性值。
推荐阅读
- hibernate - Spring-boot,同一对象中的一对多关系(父母和孩子)
- javascript - 通过构建 scss 模块在 webpack 编译中出错
- python - 使用 Python 从多个 CSV/Excel 文件中绘制一个图形
- python - 创建字典以将单词与数字联系起来
- sockets - 如何检查 ssh 隧道是否处于活动状态并已连接?
- r - 减少在闪亮仪表板的标题中添加的选择输入的大小
- arrays - 打字稿中递归函数中嵌套数组的正确类型
- ssl - 如何使用 HTTPS 库在 Node.js 中托管具有有效证书的 HTTPS 服务器
- python - 安装 django-tracking 时遇到问题
- flutter - 比较返回函数的值