0

Thanks for your help, I am writing a web API (using dotnet core 3) that accepts network errors report :

{
    "sampling_fraction": 1.0,
    "server_ip": "192.0.2.1",
    "protocol": "http/1.1",
    "method": "GET",
    "request_headers": {
      "If-None-Match": ["01234abcd"]
    },
    "response_headers": {
      "ETag": ["01234abcd"]
    },
    "status_code": 304,
     "type": "ok"
}

And trying to get request_headers and response_headers as collections of strings with values coming from HeaderNames class. Roughly

class Data
{    ...
      public string Method {get;set;}
      public List<string> RequestHeaders {get;set;}
      public List<string> ResponseHeaders {get;set;}
}

So far I have created a Model Class to Cast it:

public class ErrorBody
    {
        public double Sampling_Fraction { get; set; }
        public string Server_Ip { get; set; }
        public string Protocol { get; set; }
        public string Method { get; set; }
        public HttpRequestHeader Request_Headers { get; set; }
        public HttpResponseHeaders Response_Headers { get; set; }
        public int Status_Code { get; set; }
        public string Type { get; set; }
    }

From Json I am trying to cast "Request_Headers" and "Response_Headers" as a collection of Headers, like:

    public HttpRequestHeader Request_Headers { get; set; }
    public HttpResponseHeaders Response_Headers { get; set; }

unsing System.Net

But the casting fails with error:

 "errors": {
        "$.body.request_headers": [
            "The JSON value could not be converted to System.Net.HttpRequestHeader. Path: $.body.request_headers | LineNumber: 9 | BytePositionInLine: 24."
        ]
    }

My method looks like:

[HttpPost]
public IActionResult CreateReport(ErrorDto error)
{             
   Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(error));
   return Ok();
}

I am trying to cast both objects into a collection of HeaderName

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
foo-baar
  • 1,076
  • 3
  • 17
  • 42
  • Please edit your post to include the code you have tried that is raising the exception. – John Wu Dec 03 '19 at 22:40
  • There is no real [MCVE] and it is very unclear what you actually want to achieve... In particular how do you expect some object with properties get converted to an enum? – Alexei Levenkov Dec 03 '19 at 22:45
  • @JohnWu Please see if it's explanatory now. Thanks – foo-baar Dec 04 '19 at 00:33
  • @AlexeiLevenkov Please see if it's explanatory now. Thanks – foo-baar Dec 04 '19 at 00:33
  • I don't see any explanation on what do you want to see as result of converting something like `{ "If-None-Match": ["01234abcd"] }` into enum value of type `HttpRequestHeader`. – Alexei Levenkov Dec 04 '19 at 00:37
  • @AlexeiLevenkov I am trying to cast both objects into a collection of HeaderName https://learn.microsoft.com/en-us/dotnet/api/microsoft.net.http.headers.headernames?view=aspnetcore-3.0 – foo-baar Dec 04 '19 at 00:46
  • Does this answer your question? [Deserialize Dictionary](https://stackoverflow.com/questions/10585500/) – Dour High Arch Dec 04 '19 at 00:49
  • https://stackoverflow.com/questions/1207731/how-can-i-deserialize-json-to-a-simple-dictionarystring-string-in-asp-net is probably better duplicate as it shows sample for {"n":v, "n1":v1,...} format... – Alexei Levenkov Dec 04 '19 at 00:58
  • I've edited post so it aligns what your comments say... Please review.. – Alexei Levenkov Dec 04 '19 at 01:26

2 Answers2

1

This error is occurring because, as it states, it cannot deserialize the object to type System.Net.HttpRequestHeader. For one, System.Net.HttpRequestHeader is an enum. For two, the key If-None-Match has hyphens, and that can't be deserialized to a C# property because property names don't have hyphens. You would probably want to use a custom type instead.

However, I recommend using a Dictionary because, otherwise, your custom type would have to have a property for every possible header value. So change your Request_Headers and Response_Headers objects to type Dictionary<string, List<string>> and I think that'll take care of it.

Matt U
  • 4,970
  • 9
  • 28
  • 1
    Thank you @AlexeiLevenkov. I realized after reading your comment that the header values are arrays in the JSON. I updated my answer. – Matt U Dec 04 '19 at 01:09
  • `List` indeed... array probably would not worked. Consider adding dictionary -> `Lsit` (were strings are from HeaderName) conversion to completely answer OP's question... – Alexei Levenkov Dec 04 '19 at 01:19
0

If you were able to change data types on your header collections then you could do deserialise them as Dictionaries:

public class ErrorBody
{
    public double Sampling_Fraction { get; set; }
    public string Server_Ip { get; set; }
    public string Protocol { get; set; }
    public string Method { get; set; }
    public Dictionary<string, List<string>> Request_Headers { get; set; }  // change type here
    public Dictionary<string, List<string>> Response_Headers { get; set; } // change type here
    public int Status_Code { get; set; }
    public string Type { get; set; }
}
void Main()
{
    var str = "{\"sampling_fraction\":1,\"server_ip\":\"192.0.2.1\",\"protocol\":\"http\\/1.1\",\"method\":\"GET\",\"request_headers\":{\"If-None-Match\":[\"01234abcd\"]},\"response_headers\":{\"ETag\":[\"01234abcd\"]},\"status_code\":304,\"type\":\"ok\"}";
    JsonConvert.DeserializeObject<ErrorBody>(str); // this gave me deserialised object
}
timur
  • 14,239
  • 2
  • 11
  • 32