DotNet 5.0 Core MVC - 与 JsonPatchDocument 一起使用 - PATCH 不工作 - 404 未找到

DotNet 5.0 Core MVC - using with JsonPatchDocument - PATCH not working - 404 not found

我使用的是新发布的Dotnet 5.0项目(MVC项目):

dotnet new mvc

.csproj 文件内部:<TargetFramework>net5.0</TargetFramework>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="5.0.0"/>
    <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.0"/>
  </ItemGroup>

我尝试使用教程进行测试,但没有用。 ASP Net Core API - Partial Update using HTTP Patch

// Startup.cs  
    // Added .AddNewtonsoftJson() extension method from NewtonsoftJsonMvcBuilderExtensions

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews().AddNewtonsoftJson();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env){
            // .... truncated ....
            
            // Add custom route for /api

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");

                endpoints.MapControllerRoute(
                    name: "api",
                    pattern: "api/{controller=VideoGame}/{action=Index}/{id?}");

            });

        }
// VideoGame.cs
public partial class VideoGame
{
    public virtual int Id { get; set; }
 
    public virtual string Title { get; set; }
 
    public virtual string Publisher { get; set; }
 
    public virtual DateTime? ReleaseDate { get; set; }
 
    public VideoGame(int id, string title, string publisher, DateTime? releaseDate)
    {
        Id = id;
        Title = title;
        Publisher = publisher;
        ReleaseDate = releaseDate;
    }
}

** 如前所述,模板不起作用,因此我添加了一些额外的控制器操作 [HttpGet] Index()[HttpGet] Patch():** 和 离开 [HttpPatch] Patch()方法不变,与教程相同

// VideoGameController.cs
using Test_JSON_Patch.Classes;
using System.Linq;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.JsonPatch;

// Removed this route - because it didn't work at all (even without adding a custom route) 
// [Route("api/video-game")]
// So current resolves to https://localhost/api/VideoGame/Index
public class VideoGameController : Controller
{
    IList<VideoGame> VideoGames { get; set; }
 
    public VideoGameController()
    {
        VideoGames = new List<VideoGame>();
 
        VideoGames.Add(new VideoGame(1, "Call of Duty: Warzone", "Activision", new System.DateTime(2020, 3, 10)));
        VideoGames.Add(new VideoGame(2, "Friday the 13th: The Game", "Gun Media", new System.DateTime(2017, 5, 26)));
        VideoGames.Add(new VideoGame(3, "DOOM Eternal", "Bethesda", new System.DateTime(2020, 3, 20)));
    }
 
    [HttpGet]
    public IActionResult Index(){
        return View();
    }

    [HttpGet]
    public IActionResult Patch(){
        // Just using View from home page to confirm Patch GET
        ViewBag.DataTest = "Patch Home Page";
        return View("Index");
    }
    
    [HttpPatch("{id:int}")]
    public IActionResult Patch(int id, [FromBody] JsonPatchDocument<VideoGame> patchEntity)
    {
        var entity = VideoGames.FirstOrDefault(videoGame => videoGame.Id == id);
 
        if (entity == null)
        {
            return NotFound();
        }
 
        patchEntity.ApplyTo(entity, ModelState); // Must have Microsoft.AspNetCore.Mvc.NewtonsoftJson installed
        
        return Ok(entity);
    } 
}

使用以下 JSON 示例进行测试:(使用 POSTMAN 中的 PATCH 方法)

// PATCH method using POSTMAN and raw body: - tried |BOTH| array and single object syntax
https://localhost:5001/api/VideoGame/Patch/id/2
[
    {
        "value": "Friday the 13th",
        "path": "/title",
        "op": "replace"
    }
]

这个returns 404 Not Found ....

关于路径的注释 https://localhost:5001/api/VideoGame/...:

我错过了什么?或者我不能在同一个项目中使用 'MVC actions' 和 'Patch API actions' 吗?

我设法使用 PATCH 更新解决了问题,我确实可以在同一个项目中使用它,我正在使用 Dotnet MVC 项目

我的问题中链接的教程不适用于当前版本的 Dotnet Core 3x 或新的 Dotnet 5.0,但它只需要稍作更新。

我的问题几乎所有内容都是正确的,经过不同的测试后有一些细微的变化。

所需件数:

使用 Nuget 等添加这两个库:

  • Microsoft.AspNetCore.Mvc.NewtonsoftJson

  • Microsoft.AspNetCore.JsonPatch

  • .proj/解决方案文件

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="5.0.0"/>
    <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.0"/>
  </ItemGroup>
  • Startup.cs
    • 不要为api添加新的.MapControllerRoute()路由路径,这似乎不起作用正确使用 JsonPatch

    • 确保Microsoft.Extensions.DependencyInjection被引用,静态classNewtonsoftJsonMvcBuilderExtensions

    • 添加AddNewtonsoftJson()到服务:(IMvcBuilder扩展)

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews().AddNewtonsoftJson();
        }
  • 你的控制器:

注意教程路线和最终成功的路线之间的区别。 ApiController 属性是可选的。

using Microsoft.AspNetCore.JsonPatch;

namespace X{
    [ApiController]
    [Route("api/[controller]/[action]")]
    public class VideoGameController : Controller

        [HttpPatch("{id:int}")]
        public IActionResult Patch(int id, [FromBody] JsonPatchDocument<VideoGame> patchEntity)
        {
            var entity = VideoGames.FirstOrDefault(videoGame => videoGame.Id == id);
    
            if (entity == null)
            {
                return NotFound();
            }
    
            patchEntity.ApplyTo(entity, ModelState); // Must have Microsoft.AspNetCore.Mvc.NewtonsoftJson installed
            
            return Ok(entity);
        }
}

疑难解答

首先:不要为 api 添加新的 .MapControllerRoute() 路由路径,这似乎无法与 JsonPatch 一起正常工作

Error 405 Method Not allowed.

  • 确保您的路由与控制器中的路由完全一致,Startup.cs 中的路由似乎不适用于 JsonPatch。
  • 还要确保您将JSON作为内容类型

Error 415 "Unsupported Media Type"

  • 您的内容类型未设置为 JSON。

The patchEntity collection is empty, but the response is 200 success (appears that is working, but no patch happened on object.

  • 我发现如果不添加AddNewtonsoftJson()扩展方法,集合会为空,请求成功但没有更新。