【问题标题】:ASP.NET Core OData Batch works for get but not update (PATCH)ASP.NET Core OData Batch 适用于获取但不适用于更新 (PATCH)
【发布时间】:2023-01-29 21:02:50
【问题描述】:

使用 .NET Core 3.1 和 Microsoft.AspNetCore.OData 8.0.4。

我已经在我的 API 上设置了批处理,如果批处理中的所有请求都是 GET,它就会工作。

但是,如果我进行任何更新,它就会失败并出现我无法弄清楚的错误。

直接更新成功:

curl --location --request PATCH 'https://localhost:44390/api/odata/TradeTypeSpread(8432C89B-6D71-48B2-9F40-0000190AD326)' \
--header 'ApiAccessKey: xxxx' \
--header 'Content-Type: application/json' \
--data-raw '{
    "Id":"8432C89B-6D71-48B2-9F40-0000190AD326",
    "Spread": 3.0
}'
200 OK
{
    "error": null,
    "isSucceeded": true,
    "id": null
}

批量更新失败:

curl --location --request POST 'https://localhost:44390/api/Odata/$batch' \
--header 'ApiAccessKey: xxx' \
--header 'Content-Type: application/json' \
--data-raw '{
    "requests": [
        {
            "id": "1",
            "method": "PATCH",
            "url": "/api/odata/TradeTypeSpread(8432C89B-6D71-48B2-9F40-0000190AD326)",
            "body": {
                "Id": "8432C89B-6D71-48B2-9F40-0000190AD326",
                "Spread": 3.0
            }
        }
    ]
}'
{
    "responses": [
        {
            "id": "1",
            "status": 400,
            "headers": {
                "content-type": "application/json; odata.metadata=minimal; odata.streaming=true",
                "odata-version": "4.0"
            },
            "body": {
                "error": {
                    "code": "",
                    "message": "The input was not valid.",
                    "details": [
                        {
                            "code": "",
                            "message": "The input was not valid."
                        }
                    ]
                }
            }
        }
    ]
}

谁能看到我在第二个样本中做错了什么?

启动代码:

        public IServiceProvider ConfigureServices(IServiceCollection services)
        {

            var defaultODataBatchHandler = new DefaultODataBatchHandler();
            defaultODataBatchHandler.MessageQuotas.MaxNestingDepth = 2;
            defaultODataBatchHandler.MessageQuotas.MaxOperationsPerChangeset = 100;


            services
                .AddControllersWithViews(options =>
                {
                    options.Filters.Add(typeof(HttpGlobalExceptionFilter));
                    options.Filters.Add(typeof(ValidateModelStateAttribute));
                })
                .AddNewtonsoftJson(options => options.SerializerSettings.UseDefaultSettings(nullValueHandling: Newtonsoft.Json.NullValueHandling.Include))
                .AddOData(opt => opt.AddRouteComponents(
                                    "api/odata",
                                     new ModuleOdataEntityDataModel().GetEntityDataModel(),
                                     defaultODataBatchHandler)
                                    .Select().Filter().Count().OrderBy().Expand().SetMaxTop(Convert.ToInt32(Configuration["OdataMaxPageSize"])))
                .ConfigureApiBehaviorOptions(options =>
                {
                    options.SuppressModelStateInvalidFilter = true;
                });

控制器代码


 public class TradeTypeSpreadController : ODataController
    {


        [EnableQuery]
        public async Task<IQueryable<TradeTypeSpreadDto>> Get()
        {
            ...
        }

        

        public async Task<IActionResult> Patch(Guid key, Delta<TradeTypeSpreadDto> detalTradeSpreadDto)
        {
            ...
        }


    }

谢谢 山姆

【问题讨论】:

  • 您可以关注这篇文章:learn.microsoft.com/en-us/odata/webapiauth/getting-started,还有您的控制器API代码是什么样的?
  • 嗨 Chaodeng, 是的,我遵循了类似的东西。我没有放置启动代码的原因是所有单独的 Get 和 Update 逻辑都有效。只有批量更新有问题。但是现在让我在上面添加相关代码。
  • 完成,添加了缺少的代码。
  • 对我来说,我不得不在 Guid 周围使用单引号钥匙在 URL 中,但使用该设置它就可以正常工作。

标签: asp.net-core .net-core odata


【解决方案1】:

ASP Net Core 中 OData 的工作批处理更新可能如下所示:

    [AcceptVerbs("PATCH", "MERGE")]
    public async Task<IActionResult> Patch(
        [FromODataUri] string key,
        Delta<MyModel> patch)
    {
            var model = patch.GetInstance();
            await _repository.Update(model);

            // IQueryable
            var res = _repository.GetAll().SingleOrDefault(x => x.Id == key); 

            return Updated(res);
    }

并且它希望“获得单身”也可用:

    [EnableQuery]
    public IActionResult Get(
        [FromODataUri] string key)
    {
        var dataset = _salesAreaBandsRepository.GetAll();

        return Ok(dataset.SingleOrDefault(x => x.Id == key));
    }

当然,如果您使用复合键或其他字段作为键,则必须调整 GetEdmModel():

private static IEdmModel GetEdmModel()
{
    ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
    var entitySet1 = builder.EntitySet<MyModel>("MyModel");
    entitySet1.EntityType.HasKey(entity => entity.OtherKey);
    return builder.GetEdmModel();
}

你有:

app.UseODataBatching();

有时候还需要改AddRouteComponents

AddRouteComponents("odata", GetEdmModel(),
                    new DefaultODataBatchHandler())

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-26
    • 2019-08-31
    • 1970-01-01
    • 1970-01-01
    • 2012-09-14
    • 2020-05-26
    相关资源
    最近更新 更多