0

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:

  1. Is there a way to deserialize the given string and send over using to the BusinessLayer without string processing it?
  2. 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.

4
  • 1
    Have you tried JsonConvert.DeserializeObject<List<my_error_object>>(string_from_stored_proc);? Commented Feb 28, 2017 at 20:53
  • 2
    It's looking for a list/array type because your SQL string has [ and ] around its contents. Remove those, then deserialize. Commented Feb 28, 2017 at 20:57
  • @Equalsk - Thanks a bunch. It did the trick. I somehow ignored that it was returning a list even when the return variable set in the Stored Procedure is a varchar (string in C# model). Commented Mar 1, 2017 at 0:44
  • However, I'm still stuck with return Ok(object) instead of being able to send a clean error string using BadRequest(string_from_stored_proc) and deserialize it in the BusinessLayer. I have updated the question with the output. Thanks again. @MikeMcCaughan - Though your answer works, it is not something I want to do in first place since it involves manual string processing. Commented Mar 1, 2017 at 0:50

1 Answer 1

2

I was stuck with a similar thing. To get the output from your DL, you can return as below:

FROM DL (Called/Second) API

return Content(<HttpStatusCode>, "Custom Error Message Here");

For example:

Return Content(System.Net.HttpStatusCode.BadRequest, e.Message.ToString());

now in BL (First/Calling) API, if the StatusCode is not Success then read the response result. Like this:

if(!response.IsSuccessStatusCode)
{
    var errorOutput = response.Content.ReadAsStringAsync().Result;
    //Now send this errorOutput from this API to the client. Return an HTTPResult or another Content from here. Upto you!
}
return Ok(); //If response.statuscode is Success
Sign up to request clarification or add additional context in comments.

1 Comment

that's helpful. passing Content is better as it supports custom error/message along with the Status Code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.