Search code examples
c#asp.netasync-awaitjson-deserialization

Async JSON deserialisation in ASP.NET


I have a small MVC 5 application that calls a web service, and receives a JSON response. I deserialise the response into my own type and it gets passed on to the view and data is displayed by razor.

The controller handler:

    public async Task<ActionResult> Search(string q)
    {
        var vm = new SearchResultViewModel(await _searchService.GetDataAsync(q));
        return View(vm);
    }

The search service method:

    public async Task<ISearchResult> GetDataAsync(string q)
    {
        var fullRequest = new UriBuilder(RequestUri) {Query = "q=" + q};

        var result = await _client.GetAsync(fullRequest.ToString()).ConfigureAwait(false);

        if (result.IsSuccessStatusCode)
        {
            var jsonResponse = await result.Content.ReadAsStringAsync().ConfigureAwait(false);

            // How should I call this?
            return JsonConvert.DeserializeObject<SearchResult>(jsonResponse);
        }
        return new SearchResult
    }

My question: How should I call JsonConvert.DeserializeObject? It's an inherently CPU bound operation, so is it ok to call synchronously (and block the thread) since I can't return until it's done anyway? If there's a problem with deserialisation, a cancellation token couldn't be used.

If I should call asynchronously, should I use Task.Factory.StartNew() as suggested by intellisense, as a replacement for the deprecated JsonConvert.DeserializeObjectAsync()? This Channel 9 video suggests (at 58mins) that this isn't such a good idea. Perhaps another option, such as Task.Run()? Possibly a bad idea since it might cause SyncContext issues?

Any pointers gratefully received!


Solution

  • Your code is good as is. DeserializeObject will run inside a thread-pool thread since you are using ConfigureAwait(false).

    Your overall method (GetDataAsync) would still be asynchronous since it will return to the caller on the first await.