406(NotAcceptable)来自EntitySetController中的PATCH请求的响应.网站API 2.

本文关键字:请求 响应 网站 API PATCH 中的 NotAcceptable 来自 EntitySetController | 更新日期: 2023-09-27 17:59:03

我非常困惑,希望有人能澄清。升级到Web API的最新版本后(从Microsoft.AspNet.WebApi.xx5.0.0。到Microsoft.AspNet.WebApi.xxx5.1.2)OData的EntitySetController停止处理PATCH谓词,而是返回406(不可接受)代码。

实现没有改变:

public class ODataAnnouncementController : EntitySetController<TEntity, TKey> where TEntity : class
{
    (...)
    protected override Announcement PatchEntity(Guid key, Delta<Announcement> patch)
    {
        var announcement = getEntityByKeyOrThrowException(key);
        patch.Patch(announcement);
        AnnouncementManager.Instance.Save(announcement, true);
        return announcement;
    }
}

请求也没有改变:

接受:application/json

内容类型:application/json;charset=utf-8

补丁:http://{url}/odatea/Announcement(guid'62E34FB3-A37E-413F-9843-642D95BA580A')

{"描述":"单元测试的修补描述"}

方法内部的断点没有被击中,就好像"Delta<Announce>>补丁"从未被反序列化一样。它真正到达方法内部断点的唯一条件是,请求BODY为空,导致补丁对象为空。

所有其他动词(GET、POST、PUT、DELETE)都可以正常工作。

这以前也行得通。有人知道Web API 2.1在PATCH方面有任何突破性的变化吗?否则我该如何进行故障排除?

非常感谢

票据

更新

以下是C#模型:

[Serializable]
[DataContract]
public class Announcement
{                       
    private Guid _announcementID;
    private string _description;
    private bool _isPrivate;
    private DateTime _createdTime;
    private Nullable<Guid> _membershipID;
    [DataMember]
    public Guid AnnouncementID
    {
        get { return this._announcementID; }
        set { this._announcementID = value; }
    }
    [DataMember]
    public string Description
    {
        get { return this._description; }
        set { this._description = value; }
    }       
    [DataMember]
    public bool IsPrivate
    {
        get { return this._isPrivate; }
        set { this._isPrivate = value; }
    }
    [DataMember]
    public DateTime CreatedTime
    {
        get { return this._createdTime; }
        set { this._createdTime = value; }
    }
    [DataMember]
    public Nullable<Guid> MembershipID
    {
        get { return this._membershipID; }
        set { this._membershipID = value; }
    }
}

我使用显式数据模型:

var routingConventions = ODataRoutingConventions.CreateDefault();
config.Routes.MapODataRoute(
            routeName: "ODataRoute",
            routePrefix: "odata",
            model: BuildExplicitODataModel(),
            pathHandler: new DefaultODataPathHandler(),
            routingConventions: routingConventions  
        );
public static IEdmModel BuildExplicitODataModel()
{
ODataModelBuilder modelBuilder = new ODataModelBuilder();
var announcementSet = buildAnnouncementModel(modelBuilder);
return modelBuilder.GetEdmModel();
}
private static EntitySetConfiguration<Announcement> buildAnnouncementModel(ODataModelBuilder modelBuilder)
{
        var announcementSet = modelBuilder.EntitySet<Announcement>("Announcement");
        announcementSet.HasEditLink(
            entityContext => entityContext.Url.ODataLink(
                new EntitySetPathSegment(entityContext.EntitySet.Name),
                new KeyValuePathSegment(ODataUriUtils.ConvertToUriLiteral(entityContext.EntityInstance.AnnouncementID, ODataVersion.V3))),
            followsConventions: true);
        announcementSet.HasIdLink(
            entityContext => entityContext.Url.ODataLink(
                new EntitySetPathSegment(entityContext.EntitySet.Name),
                new KeyValuePathSegment(ODataUriUtils.ConvertToUriLiteral(entityContext.EntityInstance.AnnouncementID, ODataVersion.V3))),
                followsConventions: true);
        var announcement = announcementSet.EntityType;
        announcement.HasKey(p => p.AnnouncementID);
        announcement.Property(p => p.Description);
        announcement.Property(p => p.IsPrivate);
        announcement.Property(p => p.CreatedTime);
        announcement.Property(p => p.MembershipID);
        return announcementSet;
}

这是请求有效载荷:

补丁http://{url}/odatea/Announcement(guid'62E34FB3-A37E-413F-9843-642D95BA580A')
接受:application/json
内容类型:application/json;charset=utf-8

身体:

{"描述":"单元测试的修补描述"}

406(NotAcceptable)来自EntitySetController中的PATCH请求的响应.网站API 2.

在我检查了最新的文件EntityRoutingConvention.cs之后,我发现actionName只能是Patch或PatchAnnouncement。

永远不会调用PatchEntity。

可以尝试使用Patch或PatchAnnouncement重命名该方法吗?


更新

然而,它在我的repo项目中运行良好。你能将你的参考版本WebApiConfig.cs、AnnouncementsController.cs和请求与我的进行比较吗。

我注意到了一些不同:

  1. 控制器名称为ODataAnnouncementController,您是否在模型生成器中使用"ODataAnnotation"作为实体集名称
  2. 在您的PATCH请求中,为什么要使用"公告"而不是"公告"

参考

Microsoft.AspNet.WebApi 5.1.2targetFramework="net45"

WebApiConfig.cs

using System.Web.Http;
using System.Web.Http.OData.Builder;
using ReproPatchNotWork.Models;
namespace ReproPatchNotWork
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.MapHttpAttributeRoutes();
            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
            builder.EntitySet<Announcement>("Announcements");
            config.Routes.MapODataRoute("odata", "odata", builder.GetEdmModel());
        }
    }
}

公告Controller.cs

using System;
using System.Web.Http.OData;
namespace ReproPatchNotWork.Models
{
    public class AnnouncementsController : EntitySetController<Announcement, Guid>
    {
        protected override Announcement PatchEntity(Guid key, Delta<Announcement> patch)
        {
            Announcement announcement = new Announcement();
            patch.Patch(announcement);
            return announcement;
        }
    }
}

请求

PATCH http://{url}/odatea/Announcements(guid'62E34FB3-A37E-413F-9843-642D95BA580A')

接受:application/json

内容类型:application/json;charset=utf-8

正文:{"描述":"单元测试的补丁描述"}