I hope it is something very simple and must be a common scenario for other devs.
I'm sending an OUT variable from SQL which contains the error details. In my DataLayer API, I check it in VS Debugger and that's how it appears:
var string_from_stored_proc = "[{\"errornumber\":2627,\"errormessage\":\"Violation of UNIQUE KEY constraint 'KEY_Subject'. Cannot insert duplicate key in object 'edu.Subject'. The duplicate key value is (MATS10, 2).\",\"errorstate\":1,\"errorseverity\":14,\"errorline\":36,\"errroprocedure\":\"SPCreateSubject\",\"xactstate\":1}]"
I understand that VS debugger adds the escape () to the string. When I try to deserialize this string using:
JsonConvert.DeserializeObject<my_error_object>(string_from_stored_proc);
I get this error:
{"Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'BaaS.DTO.SQLErrorHandler' because the type requires a JSON object (e.g. {\"name\":\"value\"}) to deserialize correctly.\r\nTo fix this error either change the JSON to a JSON object (e.g. {\"name\":\"value\"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.\r\nPath '', line 1, position 1."}
json2csharp.com fails to convert this JSON. If I remove all backslashes, it does the job. Below is the my_error_object (or converted by json2sharp) Class:
public class my_error_object
{
public int errornumber { get; set; }
public string errormessage { get; set; }
public int errorstate { get; set; }
public int errorseverity { get; set; }
public int errorline { get; set; }
public string errroprocedure { get; set; }
public int xactstate { get; set; }
}
I tried to process the string_from_stored_proc and remove all backslashes but I can't remove the escape chars (which I think is the expected behavior). With those slashes, I'm unable to get the string deserialized.
Workaround:
If I use var outputJson = Newtonsoft.Json.Linq.JToken.Parse(string_from_stored_proc); , it gives an output the below output:
{[
{
"errornumber": 2627,
"errormessage": "Violation of UNIQUE KEY constraint 'KEY_Subject'. Cannot insert duplicate key in object 'edu.Subject'. The duplicate key value is (MATS10, 2).",
"errorstate": 1,
"errorseverity": 14,
"errorline": 36,
"errroprocedure": "SPCreateSubject",
"xactstate": 1
}
]}
Upon removing starting and trailing braces, am able to deserialize using NewtonSoft.
However, when I send it from the DataLayer using BadRequest(deserialized_string_from_stored_proc)
and retrieve it in the BusinessLayer using
var output = await response.Content.ReadAsAsync<SQLErrorHandler>();
The output variable again has a lot of extra chars which I then need to process again. The only way which works for me is to send the deserialized object using HttpResults.OK(object) and the read it in my BusinessLayer. Which I don't want to do since it is not the correct return type in case of error.
Am I doing it right? I have two questions:
- Is there a way to deserialize the given string and send over using to the BusinessLayer without string processing it?
- If first is not possible, could I simply pass the string to the BusinessLayer and deserialize it there (preferred way)?
I'm happy to provide more info or code snippet to reproduce the error.
EDIT: per @Equalsk's suggestion, I have been able to deserialize it properly. however, it's in the Datalayer at the moment. Here is the output:
var equalskObj = JsonConvert.DeserializeObject<List<SQLErrorHandler>>(outputFromSP.Value.ToString());
return Ok(equalskObj);
However, I'm still not able to do the preferred way (#2). If I send the string to the BusinessLayer using return BadRequest(string_from_stored_proc) it sends
"{\r\n \"message\": \"[{\\"errornumber\\":2627,\\"errormessage\\":\\"Violation of UNIQUE KEY constraint 'KEY_Subject'. Cannot insert duplicate key in object 'edu.Subject'. The duplicate key value is (MATS10, 2).\\",\\"errorstate\\":1,\\"errorseverity\\":14,\\"errorline\\":36,\\"errroprocedure\\":\\"SPCreateSubject\\",\\"xactstate\\":1}]\"\r\n}"
Where I still have to process it. Is there a cleaner way of sending it over and then to convert as suggested? I think I should post a simplified question for this since these are separate issues. I'm really interested to see what's the best approach to do it.
JsonConvert.DeserializeObject<List<my_error_object>>(string_from_stored_proc);?[and]around its contents. Remove those, then deserialize.