Problem occurs only on my client machine. I ran my application on 4 machines without reproduction success.
I would like to ask on advice and help in debug the following exception while using Flurl library:
What may cause this exception to run only on specific machine ?
System.TypeInitializationException: The type initializer for 'Module.Performance.PriceProviders.YahooClientFactory' threw an exception. ---> System.AggregateException: One or more errors occurred. ---> System.NullReferenceException: Object reference not set to an instance of an object.
at Flurl.Http.FlurlClient.ReadResponseCookies(HttpResponseMessage response)
at Flurl.Http.FlurlClient.d__28.MoveNext()
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task1.GetResultCore(Boolean waitCompletionNotification)
at System.Threading.Tasks.Task1.get_Result()
at Module.Performance.PriceProviders.YahooClientFactory..cctor()
--- End of inner exception stack trace ---
at Module.Performance.PriceProviders.YahooClientFactory.get_GetYahooClient()
at Module.Performance.PriceProviders.YahooFlurlClient.d__9.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Module.Performance.PriceProviders.YahooStockPriceProvider.d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Module.Performance.PriceProviders.PriceProviderBase.d__3.MoveNext()
Code beneath the exception looks like:
YahooClientFactory is singletone factor to optimize the request time. Factory is often called by other async task (higher layer)
public static class YahooClientFactory
{
public static IFlurlClient GetYahooClient => YahooClientInstance;
public static string Crumb { get; }
private static readonly IFlurlClient YahooClientInstance;
private const string CookieUrl = "https://finance.yahoo.com";
private static string userAgent = "User-Agent";
private static string headerString =
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36";
private const string CrumbUrl = "https://query1.finance.yahoo.com/v1/test/getcrumb";
private static int MaxRetryCount = 5;
static YahooClientFactory()
{
YahooClientInstance = new FlurlClient()
.WithHeader(userAgent, headerString)
.EnableCookies()
.WithUrl($"{CookieUrl}?{GetRandomString(8)}");
for (int i = 0; i < MaxRetryCount; i++)
{
YahooClientInstance
.GetAsync(CancellationToken.None)
.Result
.EnsureSuccessStatusCode();
if (YahooClientInstance.Cookies?.Count > 0)
{
break;
}
if (i == MaxRetryCount)
{
throw new Exception("Reached maximum number of retries when connecting to yahoo client.");
}
Thread.Sleep(100);
}
Crumb = YahooClientInstance
.WithUrl(CrumbUrl)
.GetAsync(CancellationToken.None)
.ReceiveString()
.Result;
}
public static string GetRandomString(int length)
{
const string Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
return string.Join("", Enumerable.Range(0, length).Select(i => Chars[new Random().Next(Chars.Length)]));
}
}
It looks like you've encountered a known bug where Flurl attempts to read cookies after a failed request without checking for a null response. This is fixed for Flurl.Http 2.0. Please upgrade to the latest prerelease and report back whether that resolves your issue.
Related
I am trying to understand what seems to be wrong from this stack trace. What is "Value" in this context and how does simple Any function throws an exception in this specific case.
Stack Trace:
System.ArgumentNullException: Value cannot be null.
at System.Threading.Monitor.Enter(Object obj)
at System.Net.Http.Headers.HttpHeaders.ParseRawHeaderValues(String name, HeaderStoreItemInfo info, Boolean removeEmptyHeader)
at System.Net.Http.Headers.HttpHeaders.<GetEnumerator>d__20.MoveNext()
at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source, Func`2 predicate)
at PortalCoreV2.Controllers.HomeController.<FacebookShares>d__19.MoveNext() in **********\Controllers\HomeController.cs:line 173
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
........
And here's line 173 of the HomeController:
private static HttpClient facebokPingHttpClient = new HttpClient()
{
Timeout = TimeSpan.FromSeconds(1)
};
[ResponseCache(CacheProfileName = "Default", Order = int.MaxValue)]
public async Task<IActionResult> FacebookShares(string articleIds)
{
if (facebokPingHttpClient.DefaultRequestHeaders.Any(m => m.Key == "user-agent") == false) <--- line 173
facebokPingHttpClient.DefaultRequestHeaders.Add("user-agent", "Mozilla/5.0 (Windows; Windows NT 5.1; rv:1.9.2.4) Gecko/20100611 Firefox/3.6.4");
Following my previous comments...
From further investigation by means of ILSpy, I was unable to find a method that can add a null HeaderStoreItemInfo object.
All candidate places seem to be properly guarded by null checks.
Meanwhile, it seem that the HttpHeaders class is NOT thread-safe, meaning that different threads simultaneously setting properties might corrupt the internal dictionary.
A similar effect might happen when reading while something else is writing.
I suggest adding synchronization locks around both code that is modifying and using the headers.
NOTE:
FacebookShares is both reading and writing headers; is it possible that two threads are running sych method simultaneously?
For example:
private static HttpClient facebokPingHttpClient = new HttpClient()
{
Timeout = TimeSpan.FromSeconds(1)
};
private static readonly object HeadersLock = new object(); // DECLARED LOCK
[ResponseCache(CacheProfileName = "Default", Order = int.MaxValue)]
public async Task<IActionResult> FacebookShares(string articleIds)
{
lock(HeadersLock) // ADDED LOCK
{
if (!facebokPingHttpClient.DefaultRequestHeaders.Any(m => m.Key == "user-agent"))
facebokPingHttpClient.DefaultRequestHeaders.Add("user-agent", "Mozilla/5.0 (Windows; Windows NT 5.1; rv:1.9.2.4) Gecko/20100611 Firefox/3.6.4");
}
}
You have to check your code to add the same exact lock everywhere facebokPingHttpClient.DefaultRequestHeaders could be modified.
I am new to azure. I am trying to create ResourceGroup then trying to deploy a VM. But I am getting exception during accessing resourcegroups.
I am following MSDN example given here: https://learn.microsoft.com/en-us/azure/virtual-machines/windows/csharp-template
I tried different subscription but no luck. Couldn't find any pointers online for this issue or I might have missed. If you could help me please let me know.
Thanks.
//AppId,Key,TenetId are correct
var credentials = SdkContext.AzureCredentialsFactory
.FromServicePrincipal(ApplicationID, Key, TenetID,
new AzureEnvironment()
{
AuthenticationEndpoint = #"https://login.windows.net/",
ManagementEndpoint = #"https://management.core.windows.net/",
ResourceManagerEndpoint = #"https://management.azure.com/",
GraphEndpoint = #"https://graph.windows.net/",
});
var azure = Azure
.Configure()
.WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
.Authenticate(credentials)
.WithSubscription(AzureProperties.SubscriptionId);
var groupName = "MyresourceGroup1";
var location = Region.USWest;
//Exception comes at here.
var resourceGroup = azure.ResourceGroups.Define(groupName)
.WithRegion(location)
.Create();
//Exception details.
System.ArgumentNullException
HResult=0x80004003
Message=Value cannot be null.
Parameter name: value
Source=mscorlib
StackTrace:
at System.String.EndsWith(String value, StringComparison comparisonType)
at Microsoft.Azure.Management.ResourceManager.Fluent.Authentication.AzureCredentials.<ProcessHttpRequestAsync>d__24.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at Microsoft.Azure.Management.ResourceManager.Fluent.ResourceGroupsOperations.<CreateOrUpdateWithHttpMessagesAsync>d__6.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.Management.ResourceManager.Fluent.ResourceGroupImpl.<CreateResourceAsync>d__26.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.Management.ResourceManager.Fluent.Core.ResourceActions.Creatable`4.<Microsoft-Azure-Management-ResourceManager-Fluent-Core-ResourceActions-IResourceCreator<IResourceT>-CreateResourceAsync>d__15.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.Management.ResourceManager.Fluent.Core.DAG.CreatorTaskItem`1.<ExecuteAsync>d__6.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.Management.ResourceManager.Fluent.Core.DAG.TaskGroupBase`1.<ExecuteNodeTaskAsync>d__14.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.Management.ResourceManager.Fluent.Core.Extensions.Synchronize[TResult](Func`1 function)
at Microsoft.Azure.Management.ResourceManager.Fluent.Core.ResourceActions.Creatable`4.Create()
at pvt_CreateVM.AzureVMManager.CreateVM()
at pvt_CreateVM.Program.Main(String[] args)
I think code is currently failing because you haven't set any value for KeyVaultSuffix property for AzureEnvrionment that you have initialized.
It's a guess looking at the error info you have shared but I say this after looking at the relevant source code for Azure Management Libraries for .NET
(on a side note it's awesome that anyone can do that.. here is a link)
public async override Task ProcessHttpRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var adSettings = new ActiveDirectoryServiceSettings
{
AuthenticationEndpoint = new Uri(Environment.AuthenticationEndpoint),
TokenAudience = new Uri(Environment.ManagementEndpoint),
ValidateAuthority = true
};
string url = request.RequestUri.ToString();
if (url.StartsWith(Environment.GraphEndpoint, StringComparison.OrdinalIgnoreCase))
{
adSettings.TokenAudience = new Uri(Environment.GraphEndpoint);
}
string host = request.RequestUri.Host;
// I guess this is where your code is failing currently.
if (host.EndsWith(Environment.KeyVaultSuffix, StringComparison.OrdinalIgnoreCase))
{
How to fix
Unless there is a good reason, I would not initialize AzureEnvironment object and instead use the values already available, as that would make sure all required properties have correct values.
Example: AzureEnvironment.AzureGlobalCloud. Look here for all possible values
Change this code where you initialize AzureEnvironment
var credentials = SdkContext.AzureCredentialsFactory
.FromServicePrincipal(ApplicationID, Key, TenetID,
new AzureEnvironment()
{
AuthenticationEndpoint = #"https://login.windows.net/",
ManagementEndpoint = #"https://management.core.windows.net/",
ResourceManagerEndpoint = #"https://management.azure.com/",
GraphEndpoint = #"https://graph.windows.net/",
});
To this code
var credentials = SdkContext.AzureCredentialsFactory
.FromServicePrincipal(clientId,
clientSecret,
tenantId,
AzureEnvironment.AzureGlobalCloud);
In case you have some reason that none of the available environment values are good enough, then make sure you initialize all required properties for AzureEnvironment
I am trying to get the links from VSO for workitems, and the code seems to work fine when called from a single thread, but throws exceptions when called from a parallel for each loop.
I initalize my vso client object in my class's constructor:
vso = new WorkItemReporting(Config.VSTSAccessToken);
Then later in a method:
Parallel.ForEach(msrcAbBugsToProcess, new ParallelOptions { MaxDegreeOfParallelism = 10 }, bugId =>
{
var workItemLinks = vso.GetWorkItemSourceCodeLinks(bugId);
});
witclient below is a WorkItemTrackingHttpClient which is in a different class (WorkItemReporting) and calls the API. It is this call that fails.
public List<string> GetWorkItemSourceCodeLinks(int bugId)
{
var workItemSourceCodeLinks = new List<string>();
var workItem = _witClient.GetWorkItemAsync(bugId, null, null, WorkItemExpand.Relations).Result;
if (workItem?.Relations != null)
{
var validSourceCodeLinkTypes = new List<string> { "ArtifactLink", "Hyperlink" };
foreach (var relation in workItem.Relations)
{
if (validSourceCodeLinkTypes.Contains(relation.Rel))
{
workItemSourceCodeLinks.Add(relation.Url);
}
}
}
}
This works fine if I don't use the Parallel.ForEach and I get the needed data from the API. When I do, I get this exception 50% of the time:
Object reference not set to an instance of an object.
at System.Security.Cryptography.X509Certificates.X509CertificateCollection.GetHashCode()
at System.Net.HttpWebRequest.GetConnectionGroupLine()
at System.Net.HttpWebRequest.SubmitRequest(ServicePoint servicePoint)
at System.Net.HttpWebRequest.BeginGetResponse(AsyncCallback callback, Object state)
at System.Net.Http.HttpClientHandler.StartGettingResponse(RequestState state)
at System.Net.Http.HttpClientHandler.StartRequest(Object obj)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at Microsoft.VisualStudio.Services.Common.VssHttpMessageHandler.<SendAsync>d__17.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.VisualStudio.Services.Common.VssHttpRetryMessageHandler.<SendAsync>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.VisualStudio.Services.WebApi.VssHttpClientBase.<SendAsync>d__48.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.VisualStudio.Services.WebApi.VssHttpClientBase.<SendAsync>d__45`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.VisualStudio.Services.WebApi.VssHttpClientBase.<SendAsync>d__27`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.VisualStudio.Services.WebApi.VssHttpClientBase.<SendAsync>d__26`1.MoveNext()
Is there something I'm doing wrong?
A solution is to create WorkItemReporting inside Parallel.ForEach:
Parallel.ForEach(msrcAbBugsToProcess, new ParallelOptions { MaxDegreeOfParallelism = 10 }, bugId =>
{
var vso = new WorkItemReporting(Config.VSTSAccessToken);
var workItemLinks = vso.GetWorkItemSourceCodeLinks(bugId);
});
You need to lock access to the external resource by doing something like the following.
As per comment #AlexSikilinda _witClient must not be thread safe.
For what your doing though, just because you can create multiple threads doesn't means you should, i would get timings, on what your doing with and without the parallel processing in your code,
Keep in mind if you use non thread safe external resources, and locks then it maybe just as slow as running in a normal for loop. You need to test both scenario's.
Add an object outside your methods to allow access to the lock object from every thread, this will help manage the access to the non thread safe class.
vso = new WorkItemReporting(Config.VSTSAccessToken);
private readonly object _witLock = new object();
In the following you DON'T want to put the lock around the entire methods contents as i have, otherwise you are definitely wasting your time using the Parallel for this piece of code.
Based on what your doing thought this should stop the exceptions.
You need refactor the code so that only the call to _witClient is within the lock. So just declare the workItem variable outside the lock with it proper type, and then only wrap the call to workItem = _witClient.GetWorkItemAsync(bugId, null, null, WorkItemExpand.Relations).Result; in your lock code.
public List<string> GetWorkItemSourceCodeLinks(int bugId)
{
var workItemSourceCodeLinks = new List<string>();
lock (_witLock)
{
var workItem = _witClient.GetWorkItemAsync(bugId, null, null, WorkItemExpand.Relations).Result;
if (workItem?.Relations != null)
{
var validSourceCodeLinkTypes = new List<string> { "ArtifactLink", "Hyperlink" };
foreach (var relation in workItem.Relations)
{
if (validSourceCodeLinkTypes.Contains(relation.Rel))
{
workItemSourceCodeLinks.Add(relation.Url);
}
}
}
}
}
Good Luck
I'm stressing a service I'm writing that uses a WebSocket taken from AcceptWebSocketAsync. The code I'm using to send messages through the WebSocket is this:
static bool
SendMessage(WebSocket webSocket, WebSocketMessage message, byte[] buffer, CancellationToken cancellationToken)
{
try {
var endOfMessage = false;
do {
using(var timeout = new CancellationTokenSource(webSocketsTimeout))
using(var lcts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeout.Token)) {
var count = message.Content.Read(buffer, 0, buffer.Length);
endOfMessage = count < buffer.Length;
// ReSharper disable once MethodSupportsCancellation
webSocket
.SendAsync(new ArraySegment<byte>(buffer, 0, count), message.Type, endOfMessage, lcts.Token)
.Wait() // SendAsync should be canceled using the Token.
;
}
} while(endOfMessage == false);
return true;
}
catch(Exception e) {
TraceConnectionError(e);
return false;
}
finally {
message.Dispose();
}
}
My problem is that under "stress" (I'm opening and closing 6 connections every 30 seconds until the system fails), I'm getting:
Unhandled Exception: System.AggregateException: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread. ---> System.Net.HttpListenerException: An operation was attempted on a nonexistent network connection
at System.Net.WebSockets.WebSocketHttpListenerDuplexStream.WriteAsyncFast(HttpListenerAsyncEventArgs eventArgs)
at System.Net.WebSockets.WebSocketHttpListenerDuplexStream.<MultipleWriteAsyncCore>d__38.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Net.WebSockets.WebSocketBase.<SendFrameAsync>d__48.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at System.Net.WebSockets.WebSocketBase.WebSocketOperation.<Process>d__19.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Net.WebSockets.WebSocketBase.<SendAsyncCore>d__47.MoveNext()
--- End of inner exception stack trace ---
at System.Threading.Tasks.TaskExceptionHolder.Finalize()
Shouldn't the Wait() I'm using be enough to "observe" the Task exception?
The problem was a race condition in .NET framework code.
I've reported the bug here.
As a workaround, I keep a list of used WebSockets which I regularly check for State != Open and then call this code:
public static class WebSocketXs
{
readonly static Assembly assembly = typeof(WebSocket).Assembly;
readonly static FieldInfo m_InnerStream = assembly.GetType("System.Net.WebSockets.WebSocketBase").GetField(nameof(m_InnerStream), BindingFlags.NonPublic | BindingFlags.Instance);
readonly static FieldInfo m_ReadTaskCompletionSource = assembly.GetType("System.Net.WebSockets.WebSocketHttpListenerDuplexStream").GetField(nameof(m_ReadTaskCompletionSource), BindingFlags.NonPublic | BindingFlags.Instance);
readonly static FieldInfo m_WriteTaskCompletionSource = assembly.GetType("System.Net.WebSockets.WebSocketHttpListenerDuplexStream").GetField(nameof(m_WriteTaskCompletionSource), BindingFlags.NonPublic | BindingFlags.Instance);
readonly static FieldInfo[] completionSourceFields = {m_ReadTaskCompletionSource, m_WriteTaskCompletionSource };
/// <summary>
/// This fixes a race that happens when a <see cref="WebSocket"/> fails and aborts after failure.
/// The <see cref="completionSourceFields"/> have an Exception that is not observed as the <see cref="WebSocket.Abort()"/>
/// done to WebSocketBase <see cref="m_InnerStream"/> is just <see cref="TaskCompletionSource{TResult}.TrySetCanceled()"/> which
/// does nothing with the completion source <see cref="Task.Exception"/>.
/// That in turn raises a <see cref="TaskScheduler.UnobservedTaskException"/>.
/// </summary>
public static void
CleanUpAndDispose(this WebSocket ws)
{
foreach(var completionSourceField in completionSourceFields) {
m_InnerStream
.GetValue(ws)
.Maybe(completionSourceField.GetValue)
.Maybe(s => s as TaskCompletionSource<object>)?
.Task
.Exception
.Maybe(_ => {}) // We just need to observe any exception.
;
}
ws.Dispose();
}
}
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
My app works fine with WiFi but when it is over 3G connection it crashes.
here is the code:
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
if (!App.ViewModel.IsDataLoaded)
{
await App.ViewModel.LoadDataAsync();
DataContext = App.ViewModel;
}
}
Code for LoadDataAsync
public async Task<bool> LoadDataAsync()
{
Uri uri = new Uri("http://www.28cinema.az/eng/");
HttpClient client = new HttpClient();
HtmlDocument htmlDocument = new HtmlDocument();
HtmlNode htmlNode = new HtmlNode(0, htmlDocument, 1);
MovieGroup data = new MovieGroup();
string HtmlResult;
HtmlResult = await client.GetStringAsync(uri);
data.Title = "Today";
htmlDocument.LoadHtml(HtmlResult);
htmlNode = htmlDocument.DocumentNode.SelectSingleNode("//div[#class='poster_wrapper']");
for (var i = 0; i < (htmlNode.ChildNodes.Count); i++)
{
data.Items.Add(new MovieData
{
DetailsUrl = htmlNode.SelectSingleNode("div[" + (i + 1) + "]/div[1]/div[1]/a[1]").GetAttributeValue("href", ""),
Title = htmlNode.SelectSingleNode("div[" + (i + 1) + "]/div[1]/div[1]/a[1]").InnerText,
Poster = htmlNode.SelectSingleNode("div[" + (i + 1) + "]/img").GetAttributeValue("src", "No poster"),
Cinema = "28 Cinema"
});
}
Today = data;
IsDataLoaded = true;
return true;
}
Exception message : No network connection and A task was canceled.
Stack Trace :
at Cineman.ViewModels.MovieModel.<CreateTodayGroupAsync>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Cineman.ViewModels.MovieModel.<LoadDataAsync>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Cineman.MainPage.<OnNavigatedTo>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>b__0(Object state)
Any suggestions will be appreciated.
UPD: further looking revealed this line in local variables during breakpoint: 'htmlNode.InnerHtml' threw an exception of type 'System.NullReferenceException'
As you discovered, if you attempt to do an HTTP request while there is no network connection, it will throw an exception.
I recommend that you handle the exception, e.g., with a try/catch. How you display the exception details to the user is up to you.
Well it resolved when I restarted Visual Studio. Weird!