首页 > 解决方案 > 带有正确 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 包:

解决方案资源管理器:

在此处输入图像描述

.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
}

如果有人能帮我解决这个问题,我自己(我敢肯定互联网上的大部分人)会感谢你的。

标签: c#.net-core

解决方案


这已经获得了实体:

if (_repository.GetPersonById(person.id) == null) { ... }

所以你需要得到这个结果:

var personDB = _repository.GetPersonById(person.id);

然后检查变量是否为null

if(personDB != null) { ... }

然后,您将需要personDB使用人员(来自 PUT 参数)值更改属性值。


推荐阅读