-1

I am using Json.NET to deserialize a list that contains a list my class is as follows. However, I am getting an exception saying Illegal character now I presume it will be because I need data around something if so can someone help me, please.

public class DeliverysItems
{
    [Key]
    public int id { get; set; }
    public string OrderNumber { get; set; }
    public string CustomerName { get; set; }
    public int DeliveryDriverId { get; set; }
    public decimal OrderTotal { get; set; }
    public string TelephoneNumber { get; set; }
    public string EmailAddress { get; set; }        
    public int hasBeenDelivered { get; set; }
    public List<DeliverItemLines> DeliveryLines { get; set; }
}

public class DeliverItemLines
{
    [Key]
    public int id { get; set; }
    public string ItemNumber { get; set; }
    public string StockCode { get; set; }
    public string StockDescription { get; set; }

    public bool isDamaged { get; set; }

    public bool isMissing { get; set; }

    public int Status  { get; set; }
    public decimal Qty { get; set; }
    public decimal Price { get; set; }
}

Here you will see is an example of the data returned from the web api 2 created in .net c# with dapper.

[{"id":1,"OrderNumber":null,"CustomerName":null,"DeliveryDriverId":1,"OrderTotal":100.00,"TelephoneNumber":"2393029023","EmailAddress":"test@test.com","hasBeenDelivered":0,"DeliveryLines":[{"id":1,"ItemNumber":null,"StockCode":"ST233202","StockDescription":"MopBoxes","isDamaged":false,"isMissing":false,"Status":0,"Qty":0.0,"Price":23.00},{"id":2,"ItemNumber":null,"StockCode":"ST232032","StockDescription":"WashingUpLiqud","isDamaged":false,"isMissing":false,"Status":0,"Qty":0.0,"Price":24.99}]}]

This is the function I use to retrieve the said above in my app.

private HttpClient _client;
public async Task<String> GetDeliverysFromAPi()
{
    var content = "";
    _client = new HttpClient();

    var uri = new Uri("http://192.168.31.65:81/api/Deliverys/"); // Your url is here

    try
    {
        var response = await _client.GetAsync(uri);
        if (response.IsSuccessStatusCode)
        {
            content = await response.Content.ReadAsStringAsync();
        }
    }
    catch (Exception ex)
    {

    }

    return content;
}

As you can see however I am getting the below error when I debug it I am using json.net by the way.

This is how I am encoding the above using dapper.net

public IHttpActionResult Get()
{
    string retJson;
    string constring = ConfigurationManager.AppSettings["DeliveryGocs"].ToString();

    string sql = "SELECT TOP 10 * FROM Deliverys AS A INNER JOIN DeliveryLines AS B ON A.id = B.DeliveryId;";

    using (var connection = new SqlConnection(constring))
    {
        var orderDictionary = new Dictionary<int, DeliverysItems>();

        var list = connection.Query<DeliverysItems, DeliverItemLines, DeliverysItems>(
            sql,
            (order, orderDetail) =>
            {
                DeliverysItems orderEntry;

                if (!orderDictionary.TryGetValue(order.id, out orderEntry))
                {
                    orderEntry = order;
                    orderEntry.DeliveryLines = new List<DeliverItemLines>();
                    orderDictionary.Add(orderEntry.id, orderEntry);
                }

                orderEntry.DeliveryLines.Add(orderDetail);
                return orderEntry;
            })
        .Distinct()
        .ToList();

        retJson = JsonConvert.SerializeObject(list);
        var response = this.Request.CreateResponse(HttpStatusCode.OK);
        response.Content = new StringContent(retJson, Encoding.UTF8, "application/json");

        return ResponseMessage(response);
    }
}

The Exception that is caused is as follows.

{Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: S. Path '', line 0, position 0. at Newtonsoft.Json.JsonTextReader.ParseValue () [0x002ac] in //Src/Newtonsoft.Json/JsonTextReader.cs:1776 at Newtonsoft.Json.JsonTextReader.Read () [0x0004c] in //Src/Newtonsoft.Json/JsonTextReader.cs:419 at Newtonsoft.Json.JsonReader.ReadAndMoveToContent () [0x00000] in //Src/Newtonsoft.Json/JsonReader.cs:1238 at Newtonsoft.Json.JsonReader.ReadForType (Newtonsoft.Json.Serialization.JsonContract contract, System.Boolean hasConverter) [0x0004a] in //Src/Newtonsoft.Json/JsonReader.cs:1195
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType, System.Boolean checkAdditionalContent) [0x000db] in //Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs:196 at Newtonsoft.Json.JsonSerializer.DeserializeInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType) [0x00046] in //Src/Newtonsoft.Json/JsonSerializer.cs:907 at Newtonsoft.Json.JsonSerializer.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType) [0x00000] in //Src/Newtonsoft.Json/JsonSerializer.cs:886 at Newtonsoft.Json.JsonConvert.DeserializeObject (System.String value, System.Type type, Newtonsoft.Json.JsonSerializerSettings settings) [0x0002d] in //Src/Newtonsoft.Json/JsonConvert.cs:830 at Newtonsoft.Json.JsonConvert.DeserializeObject[T] (System.String value, Newtonsoft.Json.JsonSerializerSettings settings) [0x00000] in //Src/Newtonsoft.Json/JsonConvert.cs:786 at Newtonsoft.Json.JsonConvert.DeserializeObject[T] (System.String value) [0x00000] in //Src/Newtonsoft.Json/JsonConvert.cs:719 at App1.Views.DeliveryPage.OnAppearing () [0x00015] in D:\Projects\Mobile\New folder\App1\App1\App1\Views\DeliveryPage.xaml.cs:95 }

Line 95 is the line where I am doing the deserlization to the list object. The to string is being used to ensure an object does not get returned.

This is how I am calling my deserlization method.

string content = GetDeliverysFromAPi(); //Sends a GET request to the specified Uri and returns the response body as a string in an asynchronous operation
List<DeliverysItems> _deliveryItems =JsonConvert.DeserializeObject<List<DeliverysItems>>(content); //Deserializes or converts JSON String into a collection of Post

The below answer marked was indeed correct I was able to get the data by adjusting my method as per below.

public DeliveryDataStore()
{

        Task<string> callTask = Task.Run(() => GetDeliverysFromAPi());
        // Wait for it to finish
        callTask.Wait();
        // Get the result
        string content = callTask.Result;

        //Sends a GET request to the specified Uri and returns the response body as a string in an asynchronous operation
         deliverysItems = JsonConvert.DeserializeObject<List<DeliverysItems>>(content); //Deserializes or converts JSON String into a collection of Post


 }
dbc
  • 104,963
  • 20
  • 228
  • 340
c-sharp-and-swiftui-devni
  • 3,743
  • 4
  • 39
  • 100

1 Answers1

1

The problem is that your method GetDeliverysFromAPi() returns a Task<String>:

public async Task<String> GetDeliverysFromAPi() { /* Contents omitted */ }

But in the original version of the calling code you are attempting to get the returned string by simply calling Task<TResult>.ToString().

string content = GetDeliverysFromAPi().ToString();

However, Task<TResult> does not override ToString() so this simply returns the full type name "System.Threading.Tasks.Task`1[System.String]" (demo fiddle #1 here).

Instead, use Task<TResult>.Result to get the result:

string content = GetDeliverysFromAPi().Result;

Note the Remarks for Result from the docs:

Accessing the property's get accessor blocks the calling thread until the asynchronous operation is complete; it is equivalent to calling the Wait method.

Once the result of an operation is available, it is stored and is returned immediately on subsequent calls to the Result property.

Working demo fiddle #2 here.

Incidentally, in your edited question you do

string content = GetDeliverysFromAPi(); //Sends a GET request to the specified Uri and returns the response body as a string in an asynchronous operation

This won't even compile, so is likely a typo in the question; see demo fiddle #3 here.

dbc
  • 104,963
  • 20
  • 228
  • 340
  • Thank you for your help I hope the minus vote goes away, It was indeed the issue please see my edit above I wrapped it up in a task run method and worked a treat thanks – c-sharp-and-swiftui-devni Apr 14 '19 at 16:48
  • @rogue39nin - the vote wasn't from me. But in your most recent edit you're now wrapping `GetDeliverysFromAPi` in another task: `Task.Run(() => GetDeliverysFromAPi());` I'm not sure what you will get wrapping a task in another task, but it doesn't seem necessary. – dbc Apr 14 '19 at 17:01
  • i thought it was becasue i cant seem to mark the class as async – c-sharp-and-swiftui-devni Apr 14 '19 at 17:04
  • Classes aren't async, methods are async. See [How and when to use ‘async’ and ‘await’](https://stackoverflow.com/q/14455293). – dbc Apr 14 '19 at 17:08