Reputation: 555
Below I have pasted some code. On the first line of the body I call an awaitable call Task<IEnumerable<SkuGcn>> GetSkuGcnList();
On the last line, in the mapPromise.GetAwaiter()
it throws when getting the result with this exception:
An exception of type 'System.IO.FileNotFoundException' occurred in System.Private.CoreLib.ni.dll but was not handled in user code
Additional information: Could not load file or assembly 'System.Runtime.Serialization.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.
I know my service that the GetSkuGcnList()
call is calling to, is being called, because I can set a break point and I break at it when the call is made. Then the service seems to return.
This code worked just fine with ASP.NET 5 RC1 but now not so good in ASP.Net Core 1.0 Release.
Any help will be greatly appreciated!
public ProductItemsCacheStore(IItemsProductCacheRepository itemsRepo, IProductAvailabilityPricing proxyGoliathApi,
IProductItemListRepo itemsListsRepo, IItemPricesCacheRepo itemPricesRepo)
{
var mapPromise = proxyGoliathApi.GetSkuGcnList();
_items = itemsRepo.GetAllProductOrderListForCache();
_itemsLists = itemsListsRepo.GetItemListsForCache();
_priceZones = itemPricesRepo.GetAllPriceZonesAndItemPrices();
MergeProductsWithGcn(_items, mapPromise.GetAwaiter().GetResult());
}
My project.json looks like this:
{
"version": "1.0.0-alpha.1",
"description": "AvailabilityPricingClient Class Library",
"authors": [ "irving.lennert" ],
"packOptions": {
"tags": [ "" ],
"projectUrl": "",
"licenseUrl": ""
},
"tooling": {
"defaultNamespace": "AvailabilityPricingClient"
},
"dependencies": {
"Microsoft.NETCore.App": {
"version": "1.0.0",
"type": "platform"
},
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
"Microsoft.Extensions.Configuration.Json": "1.0.0",
"Microsoft.Extensions.Logging": "1.0.0",
"Microsoft.Extensions.Logging.Console": "1.0.0",
"Microsoft.Extensions.Logging.Debug": "1.0.0",
"Microsoft.AspNet.WebApi.Client": "5.2.3"
},
"frameworks": {
"netcoreapp1.0": {
"imports": [
"dotnet5.6",
"portable-net45+win8"
]
}
}
}
The implementation of GetSkuGcnList()
is this:
public async Task<IEnumerable<SkuGcn>> GetSkuGcnList()
{
HttpResponseMessage response = _client.GetAsync("/api/skuGcnList").Result;
if (response.IsSuccessStatusCode)
{
var skuGcns = await response.Content.ReadAsAsync<IEnumerable<SkuGcn>>();
return skuGcns;
}
return null;
}
Upvotes: 2
Views: 1200
Reputation: 555
I have determined that the assembly that I am calling on is not working correctly for ASP.Net Core release. If you look in the above project.json it is this line:
"Microsoft.AspNet.WebApi.Client": "5.2.3"
I have changed that line to this line:
"System.Net.Http": "4.1.0"
This assembly does not expose the same API so I had to change my implementation code to:
public async Task<IEnumerable<SkuGcn>> GetSkuGcnList()
{
HttpResponseMessage response = _client.GetAsync("/api/skuGcnList").Result;
if (response.IsSuccessStatusCode)
{
var skuGcns = await response.Content.ReadAsStringAsync()
.ContinueWith<IEnumerable<SkuGcn>>(getTask =>
{
return JsonConvert.DeserializeObject<IEnumerable<SkuGcn>>(getTask.Result);
});
return skuGcns;
}
return null;
}
This solution is working well. It is important to note I was also having the same problem with post and they are a little more complicated so I'll provide another call I make that is a post for anyone interested.
public async Task<IEnumerable<Availablity>> GetAvailabilityBySkuList(IEnumerable<string> skuList)
{
var output = JsonConvert.SerializeObject(skuList);
HttpContent contentPost = new StringContent(output, System.Text.Encoding.UTF8, "application/json");
HttpResponseMessage response = _client.PostAsync("/api/availabilityBySkuList", contentPost).Result;
if (response.IsSuccessStatusCode)
{
var avail = await response.Content.ReadAsStringAsync()
.ContinueWith<IEnumerable<Availablity>>(postTask =>
{
return JsonConvert.DeserializeObject<IEnumerable<Availablity>>(postTask.Result);
});
return avail;
}
return null;
}
Thanks to all that contributed!
Upvotes: 4
Reputation: 53710
As @DaniDev mentioned in the comments, mixing synchronous and asynchronous code is not recommended. The canonical article on this topic is Stephen Cleary's Don't Block on Async Code.
It's a little tricky to make your code async, because you are calling async operations in the constructor and constructors can't be async.
One way to restructure your code would be to split up the constructor (dependency injection) and the initialization (async calls) code:
public class ProductItemsCacheStore
{
private readonly IItemsProductCacheRepository _itemsProductCacheRepo;
private readonly IProductAvailabilityPricing _productAvailabilityPricing;
private readonly IProductItemListRepo _productItemListRepo;
private readonly IItemsPricesCacheRepo _itemsPricesCacheRepo;
private bool _initialized = false;
public ProductItemsCacheStore(
IItemsProductCacheRepository itemsRepo,
IProductAvailabilityPricing proxyGoliathApi,
IProductItemListRepo itemsListsRepo,
IItemPricesCacheRepo itemPricesRepo)
{
_itemsProductCacheRepo = itemsRepo;
_productAvailabilityPricing = proxyGoliathApi;
_productItemListRepo = itemsListsRepo;
_itemsPricesCacheRepo = itemsPricesRepo
}
public async Task Initialize()
{
// Could possibly move these to the constructor as well
var _items = itemsRepo.GetAllProductOrderListForCache();
var _itemsLists = itemsListsRepo.GetItemListsForCache();
var _priceZones = itemPricesRepo.GetAllPriceZonesAndItemPrices();
MergeProductsWithGcn(_items, await _productAvailabilityPricing.GetSkuGcnList());
_initialized = true;
}
}
Your consuming code (wherever you were building a new ProductItemsCacheStore(...)
before) now looks like:
var productItemsCacheStore = new ProductItemsCacheStore(/* dependencies */);
await productItemsCacheStore.Initialize();
Of course, this means that your consuming code also has to be async. It's async all the way up.
Upvotes: 1