ASP.NET 核心中的 FromBody API returns 空

FromBody in ASP.NET Core API returns null

我在 Azure Service Fabric 中创建了一个有状态的 ASP.NET 核心服务,其中包含 10 个分区,其中 API 作为项目模板和 ASP.NET 核心 3.0。我正在尝试通过 JSON 中的 Postman 将 class SupplierMaterialMaintenance 的对象发送到我的有状态服务,如下图所示:-

这是我要发送的 JSON 文件。

{
    "SupplierMaterialAssociationGuid": "6ef61a2b-963e-4993-ac73-5e07f707c2e2",
    "MinimumOrderQuantity": 1,
    "UnitOfMeasurementGuid": "771d4f76-9321-442f-b2c2-9f75b1a7cda8",
    "ConversionFactor": 2,
    "POPrice": 123.00000,
    "OrderLeadTime": 10,
    "IssueMinimumLot": 0,
    "ContainerQuantity": 10,
    "InnerContainerQuantity": 1,
    "NoOfInnerContainers": 10,
    "SupplierMaterialNumber": null,
    "SupplierMaterialName": null,
    "POPriceExcludingMetal": 123.00000,
    "InitialVolumeQuantity": 1,
    "ReplacementMaterialNumber": "",
    "MetalWeight": 0.0,
    "MetalRate": 0.0,
    "StandardBoxLength": 0.0,
    "StandardBoxHeight": 0.0,
    "StandardBoxWidth": 0.0,
    "StandardPackFactor": 10,
    "FullBoxWeight": 0.0,
    "TariffCodeGuid": "00000000-0000-0000-0000-000000000000",
    "CountryRegionsAssociationGuid": "00000000-0000-0000-0000-000000000000",
    "ExpiryDate": "0001-01-01T00:00:00",
    "IsActive": true,
    "MatSuppMainSupplier": false,
    "EUPreferentialOriginStatusCode": null,
    "Id": "ead6cbc7-baff-430d-b83b-4914a916aabd",
    "Name": null,
    "CreatedDate": "2019-07-09T01:53:49.659194",
    "ModifiedDate": "2019-07-09T01:53:49.659194",
    "CreatedBy": "13beef85-3939-4998-b912-22d8df2cd966",
    "ModifiedBy": "13beef85-3939-4998-b912-22d8df2cd966",
    "IsRowChecked": false,
    "Version": null,
    "CrudOperationType": 0,
    "Error": null
}

这是我的控制器:-

using Microsoft.AspNetCore.Mvc;
using Microsoft.ServiceFabric.Data;
using Microsoft.ServiceFabric.Data.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MyStatefulService.Models;
using System.Net.Http;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;

namespace MyStatefulService.Controllers
{
    [Produces("application/json")]
    [Route("api/[controller]")]
    [ApiController]
    public class DefaultController : Controller
    {
        private readonly IReliableStateManager reliableStateManager;

        public DefaultController(IReliableStateManager reliableStateManager)
        {
            this.reliableStateManager = reliableStateManager;
        }

        // GET api/Default
        [HttpGet]
        public async Task<IActionResult> Get()
        {
            CancellationToken ct = new CancellationToken();

            IReliableDictionary<Guid, SupplierMaterialMaintenance> myDictionary = await this.reliableStateManager.GetOrAddAsync<IReliableDictionary<Guid, SupplierMaterialMaintenance>>("dictionary");

            using (ITransaction tx = this.reliableStateManager.CreateTransaction())
            {
                Microsoft.ServiceFabric.Data.IAsyncEnumerable<KeyValuePair<Guid, SupplierMaterialMaintenance>> list = await myDictionary.CreateEnumerableAsync(tx);

                Microsoft.ServiceFabric.Data.IAsyncEnumerator<KeyValuePair<Guid, SupplierMaterialMaintenance>> enumerator = list.GetAsyncEnumerator();

                List<KeyValuePair<Guid, SupplierMaterialMaintenance>> result = new List<KeyValuePair<Guid, SupplierMaterialMaintenance>>();

                while (await enumerator.MoveNextAsync(ct))
                {
                    result.Add(enumerator.Current);
                }

                return this.Json(result);
            }
        }

        // PUT api/Default/name
        [HttpPost]
        public async Task<IActionResult> Post([FromBody] SupplierMaterialMaintenance obj)
        {
            SupplierMaterialMaintenance obj1 = new SupplierMaterialMaintenance();
            if (ModelState.IsValid)
            {
                obj1 = obj;
            }
            IReliableDictionary<Guid, SupplierMaterialMaintenance> myDictionary = await this.reliableStateManager.GetOrAddAsync<IReliableDictionary<Guid, SupplierMaterialMaintenance>>("dictionary");

            using (ITransaction tx = this.reliableStateManager.CreateTransaction())
            {
                await myDictionary.AddOrUpdateAsync(tx, obj1.SupplierMaterialAssociationGuid, obj1, (key, oldvalue) => obj1);
                await tx.CommitAsync();
            }

            return new OkResult();
        }
    }
}

这是 class SupplierMaterialMaintenance :-

public class SupplierMaterialMaintenance : IComparable<SupplierMaterialMaintenance>, IEquatable<SupplierMaterialMaintenance>
    {

        public Guid SupplierMaterialAssociationGuid;
        public int MinimumOrderQuantity;
        public Guid UnitOfMeasurementGuid;
        public int ConversionFactor;
        public decimal POPrice;
        public int OrderLeadTime;
        public int IssueMinimumLot;
        public int ContainerQuantity;
        public int InnerContainerQuantity;
        public int NoOfInnerContainers;
        public string SupplierMaterialNumber;
        public string SupplierMaterialName;
        public decimal POPriceExcludingMetal;
        public int InitialVolumeQuantity;
        public string ReplacementMaterialNumber;
        public decimal MetalWeight;
        public decimal MetalRate;
        public decimal StandardBoxLength;
        public decimal StandardBoxHeight;
        public decimal StandardBoxWidth;
        public int StandardPackFactor;
        public decimal FullBoxWeight;
        public Guid TariffCodeGuid;
        public Guid CountryRegionsAssociationGuid;
        public DateTime ExpiryDate;
        public bool IsActive;
        public bool MatSuppMainSupplier;
        public string EUPreferentialOriginStatusCode;
        public Guid Id;
        public string Name;
        public string CreatedDate;
        public string ModifiedDate;
        public Guid CreatedBy;
        public Guid ModifiedBy;
        public bool IsRowChecked;
        public string Version;
        public int CrudOperationType;
        public string Error;

        public int CompareTo(SupplierMaterialMaintenance obj)
        {
            if (obj != null)
            {
                SupplierMaterialMaintenance otherObj = obj as SupplierMaterialMaintenance;

                if (otherObj != null)
                {
                    return otherObj.SupplierMaterialAssociationGuid.CompareTo(this.SupplierMaterialAssociationGuid);
                }
                else
                {
                    throw new ArgumentException("Object is not a SupplierMaterialMaintenance");
                }
            }
            return 1;
        }

        public bool Equals(SupplierMaterialMaintenance obj)
        {
            if (obj == null) return false;

            return obj.SupplierMaterialAssociationGuid.Equals(this.SupplierMaterialAssociationGuid);
        }
    }

每当我在 Postman 中点击发送按钮时,我总是会得到一个 class X 的对象,并使用默认值进行初始化,如下所示:-

我在 Whosebug 上搜索了很多问题,但没有成功。我在这里做错了什么?

您需要将 SupplierMaterialMaintenance class 中的所有 fields 更改为 properties gettersetter

public class SupplierMaterialMaintenance : IComparable<SupplierMaterialMaintenance>, IEquatable<SupplierMaterialMaintenance>
{
    public Guid SupplierMaterialAssociationGuid { get; set; }
    public int MinimumOrderQuantity { get; set; }
    public Guid UnitOfMeasurementGuid { get; set; }
    public int ConversionFactor { get; set; }
    //goes like this...

您可以在 .net-core

中查看有关模型绑定的 Microsoft Documentation

既然是ASP.NET Core 3.0:你还在用NewtonSoft,Json,还是换成System.Text.Json了?

ASP.NET 核心默认在 Json 端使用 camelCase 与 Json 序列化。因此,您尝试 post 的数据应该类似于

{

    "supplierMaterialAssociationGuid": "6ef61a2b-963e-4993-ac73-5e07f707c2e2",
    "minimumOrderQuantity": 1,
    "unitOfMeasurementGuid": "771d4f76-9321-442f-b2c2-9f75b1a7cda8",
    "conversionFactor": 2,

    ...

}

取自此 NewtonSoft.Json Serialization Guide, using Fields should work just fine if you're working with NewtonSoft.Json and are manually (de)serializing. For model binding, you need to use properties as explained in the .

By default a type's properties are serialized in opt-out mode. What that means is that all public fields and properties with getters are automatically serialized to JSON, and fields and properties that shouldn't be serialized are opted-out by placing JsonIgnoreAttribute on them.