xamarin 通过json字符串POST向webapi c#发送嵌套数据

b4qexyjb  于 2022-12-07  发布在  C#
关注(0)|答案(2)|浏览(292)

Im having an issue passing a nested list from my app to a web api. Im not seeing anything in my logs, but I keep receiving the following response in Postman:

{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-7d20c10b0a8b389f3ab9b13253d89356-96635c33db3d6d02-00",
"errors": {
    "$": [
        "The JSON value could not be converted to System.String. Path: $ | LineNumber: 0 | BytePositionInLine: 1."
    ],
    "RawJson": [
        "The RawJson field is required."
    ]
}

}
When I input this JSON string in to the body/raw data with type set as JSON:

{
"RawJson": {
    "ParkSys_ID": 3,
    "Route_ID": 1,
    "TrailName": "test",
    "GPXData": [
        {
            "Timestamp": "2022-10-07T13:38:19.877+00:00",
            "Latitude": 41.5263926,
            "Longitude": -81.6508186,
            "Altitude": 153.39999389648438,
            "Accuracy": 20,
            "VerticalAccuracy": 1.5861159563064575,
            "Speed": null,
            "Course": null,
            "IsFromMockProvider": false,
            "AltitudeReferenceSystem": 2
        },
        {
            "Timestamp": "2022-10-07T13:38:21.379+00:00",
            "Latitude": 41.5263905,
            "Longitude": -81.6508169,
            "Altitude": 153.39999389648438,
            "Accuracy": 13.423999786376953,
            "VerticalAccuracy": 1.2535593509674072,
            "Speed": null,
            "Course": null,
            "IsFromMockProvider": false,
            "AltitudeReferenceSystem": 2
        },
        {
            "Timestamp": "2022-10-07T13:38:22.921+00:00",
            "Latitude": 41.5263924,
            "Longitude": -81.6508156,
            "Altitude": 153.39999389648438,
            "Accuracy": 13.423999786376953,
            "VerticalAccuracy": 1.3553755283355713,
            "Speed": null,
            "Course": null,
            "IsFromMockProvider": false,
            "AltitudeReferenceSystem": 2
        },
        {
            "Timestamp": "2022-10-07T13:38:24.479+00:00",
            "Latitude": 41.5263905,
            "Longitude": -81.6508186,
            "Altitude": 153.39999389648438,
            "Accuracy": 13.538000106811523,
            "VerticalAccuracy": 1.3423168659210205,
            "Speed": null,
            "Course": null,
            "IsFromMockProvider": false,
            "AltitudeReferenceSystem": 2
        },
        {
            "Timestamp": "2022-10-07T13:38:25.992+00:00",
            "Latitude": 41.5263919,
            "Longitude": -81.6508162,
            "Altitude": 153.39999389648438,
            "Accuracy": 14.10200023651123,
            "VerticalAccuracy": 1.526308298110962,
            "Speed": null,
            "Course": null,
            "IsFromMockProvider": false,
            "AltitudeReferenceSystem": 2
        }
    ]
}

}
This is my class that should be handling this, and I'm not sure why its not seeing the RawJson nested in the json

public class ActivitySubmissionService : IActivitySubmission
{
    [JsonProperty("ParkSys_ID")]
    public int ParkSys_ID { get; set; }
    [JsonProperty("Route_ID")]
    public int Route_ID { get; set; }
    [JsonProperty("TrailName")]
    public string TrailName { get; set; }
    [JsonProperty("GPXData")]
    public object GPXData { get; set; }

    private readonly GPSAPIContext gpsapiContext;
    public ActivitySubmissionService(GPSAPIContext gpsapiContext)
    {
        this.gpsapiContext = gpsapiContext;
    }

    //
    // this is sent JSON string
    public async Task<object> SubmitNewActivity(string RawJsonString)
    {
        var StringConvert = JsonConvert.DeserializeObject<List<ActivitySubmissionService>>(RawJsonString);
        int Park_ID = StringConvert.Select(x => x.ParkSys_ID).FirstOrDefault();
        int Route_ID = StringConvert.Select(x => x.Route_ID).FirstOrDefault();
        string Trail_Name = StringConvert.Select(x => x.TrailName).FirstOrDefault();
        object GPXData = StringConvert.Select(x => x.GPXData).ToList();

        return GPXData;
    }
}
sbtkgmzw

sbtkgmzw1#

好的,ASP.net不支持text/plain内容类型。解决方法是自己读取主体。要使其工作,action方法不能声明任何参数。

[HttpPost]
    public async Task<IActionResult> ProcessJsonString()
    {
        using StreamReader sr = new StreamReader(Request.Body, System.Text.Encoding.UTF8);
        string body = await sr.ReadToEndAsync();
        // Now you can do whatever you need with the string, like parsing to JSON, although it is a weird approach.
        return Ok(GetMyDataFromTheString(body));
    }
juud5qan

juud5qan2#

所以我花了一段时间来研究这个问题...结果至少是一个模糊的东西,然后是我的一个错误。
我没有

<Nullable>disable</Nullable>

导致错误的csproj文件中的安装

"RawJson": [
    "The RawJson field is required."
]

而且,我将[FromBody]数据传递给SubmitNewActivity(string RawJsonString) {}的方式完全错误,我需要在 Package 器中传递它(我甚至没有考虑过),JSON中的嵌套元素也需要一个 Package 器类。
另一个让我感到困惑的问题是,当将[FormBody]数据传递给方法时,如果通过 Package 器传递它,它会自动反序列化数据。因此,出现以下错误:

"$": [
    "The JSON value could not be converted to System.String. Path: $ | LineNumber: 0 | BytePositionInLine: 1."
],

是一个副产品

var StringConvert = JsonConvert.DeserializeObject<List<ActivitySubmissionService>>(RawJsonString);

最后,我得到了以下代码:

public class GPXDataWrapper
{
    public DateTime Timestamp { get; set; }
    public decimal Latitude { get; set; }
    public decimal Longitude { get; set; }
    public decimal Altitude { get; set; }
    public decimal Accuracy { get; set; }
    public decimal VerticalAccuracy { get; set; }
    public string Speed { get; set; }
    public string Course { get; set; }
    public bool IsFromMockProvider { get; set; }
    public decimal AltitudeReferenceSystem { get; set; }
}
public class ActivitySubmissionWrapper
{
    [JsonProperty("ParkSys_ID")]
    public int ParkSys_ID { get; set; }
    [JsonProperty("Route_ID")]
    public int Route_ID { get; set; }
    [JsonProperty("TrailName")]
    public string TrailName { get; set; }
    [JsonProperty("GPXData")]
    public List<GPXDataWrapper> GPXData { get; set; } = new List<GPXDataWrapper>();
}

public async Task<string> SubmitNewActivity(ActivitySubmissionWrapper RawJsonString)
    {
        int Park_ID = RawJsonString.ParkSys_ID;
        int Route_ID = RawJsonString.Route_ID;
        string Trail_Name = RawJsonString.TrailName;
        List<GPXDataWrapper> GPXData = RawJsonString.GPXData;
        decimal Trail_Lat = GPXData[0].Latitude;
        decimal Trail_Lon = GPXData[0].Longitude;
        
        //
        // start the insert by creating the trailhead
        GPXTrailHead TrailHead_Insert = new GPXTrailHead();
        TrailHead_Insert.TrailHead_Name = Trail_Name;
        TrailHead_Insert.TrailHead_Lat = Trail_Lat;
        TrailHead_Insert.TrailHead_Lon = Trail_Lon;
        gpsapiContext.TrailHead.Add(TrailHead_Insert);
        return "test: " + Park_ID+" , "+Route_ID+" ,"+Trail_Name+" , "+GPXData;
    }

相关问题