2

I have been struggling to get some code working on a new machine.. I thought I finally had it working but now when I run it the code hangs at the point of trying to create the table storage (or in actual fact get a reference to it, as it does already exist)... I know about having to make sure it's async all the way through and this code was working... I've now changed it to try and improve it and get it working on this machine, but something is not right... So in the constructor of the Repo I do this....

public LdsRepo() 
    {

        if (!GetTableRef("licensedatesummary").Result)
        {
            throw new Exception("It broke!");
        }
    }

and my GetTableReference Method (on the base class) is like this...

protected async Task<bool>  GetTableRef(string tableRef)
    {
        try
        {
            if (string.IsNullOrEmpty(StorageAccountName) || string.IsNullOrEmpty(AuthKey))
            {
                throw new ArgumentNullException(nameof(tableRef),
                    "storageaccountname or authk are not set in the config");
            }
            if (_tableClient == null)
                _tableClient =
                    new CloudStorageAccount(new StorageCredentials(StorageAccountName, AuthKey), true)
                        .CreateCloudTableClient();
            if (_table == null)
            {
                // Create the CloudTable object that represents the referenced table.
                _table = _tableClient.GetTableReference(tableRef);
                var x =  _table.CreateIfNotExistsAsync();
                return await x;
            }
            return true;
        }
        catch (Exception ex)
        {
            Trace.WriteLine(ex.Message);
            Trace.WriteLine(ex.ToString());
            return false;
        }
    }

and if it helps... this is my packages config...

<packages>
<package id="Microsoft.Azure.KeyVault.Core" version="1.0.0" targetFramework="net452" />
<package id="Microsoft.Data.Edm" version="5.7.0" targetFramework="net452" />
<package id="Microsoft.Data.OData" version="5.7.0" targetFramework="net452" />
<package id="Microsoft.Data.Services.Client" version="5.7.0" targetFramework="net452" />
<package id="Microsoft.Web.WebJobs.Publish" version="1.0.11" targetFramework="net452" />
<package id="Microsoft.WindowsAzure.ConfigurationManager" version="3.2.1" targetFramework="net452" />
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net452" />
<package id="System.Spatial" version="5.7.0" targetFramework="net452" />
<package id="WindowsAzure.Storage" version="7.0.0" targetFramework="net452" /> </packages>

And finally my actual WebApi controller....

[EnableCors(origins: "*", headers: "*", methods: "*")]
[RoutePrefix("api")]
public class LinkDataController : ApiController
{
    private readonly IFloatingObjectRecordRepo _repo;
    public LinkDataController()
    {
        _repo = new FloatingObjectRecordRepo();
    }
    [HttpGet, Route("linkdata/{id}")]
    public async Task<IHttpActionResult> Get(string id)
    {
        try
        {
            if (string.IsNullOrEmpty(id))
            {
                return BadRequest();
            }
            var retStr = await  _repo.SearchById(id);
            if (retStr == "Not found")
                return new IsoncOkResult<KeyValuePair<string, string>>(
                    new KeyValuePair<string, string>(id, retStr), this);
            var g = Guid.NewGuid();
            var f = await _repo.Add(new FlorData
            {
                CreatedBy = "Ais Integration Search",
                Mmsi = id,
                CreatedOn = DateTime.Now,
                GeneratedId = g,
                RowKey = g.ToString()
            });
            retStr = f.GeneratedId.ToString();
            return new IsoncOkResult<KeyValuePair<string, string>>(new KeyValuePair<string, string>(id, retStr), this);
        }
        catch (Exception ex)
        {
            Trace.TraceError($"Error Searching / Creating AIS Link Data: {ex}");
            return BadRequest(ex.ToString());
        }
    }
   }

I have searched on here quite extensively but every time it has been where someone hasn't followed the async chain all the way through, which I think I am doing?

dreadeddev
  • 238
  • 5
  • 14

1 Answers1

5

When using

if (!GetTableRef("licensedatesummary").Result)

You are missing the point of "Async all the way", see This question for a difference between await Task and Task.Result.

There are several options in order to solve this, here are just two:

  1. You can change the "GetTableRef" to be synchronous(if this is the only usage you have for this method, than this should be a decent option since no benefit of using async method only in blocking context) by using the CreateIfNotExists() method instead of CreateIfNotExistsAsync().
  2. See How to call async method in constructor which explains some techniques for such scenario
Community
  • 1
  • 1
Kobynet
  • 912
  • 11
  • 23
  • Thanks, and yes, you're absolutely has got to be synch, as you can't do anything else until you actually have a reference to, or have created the table, therefore this shouldn't be asynch at all. – dreadeddev May 03 '16 at 14:47