I am trying to add a device with "Microsoft.Azure.Devices.Device::AddDeviceAsync(Device)" inside an Azure function with the following code :
public static async Task Run(string myQueueItem, TraceWriter log)
{
log.Info($"C# ServiceBus queue trigger function processed message: {myQueueItem}");
var manager = new Manager();
RegisterMessage message = manager.ConvertMessage(myQueueItem);
await manager.AddToHub(log, message.MacAddress);
log.Info("fin du run");
}
public class Manager {
string EndpointUrl = "endpoint";
string PrimaryKey = "key";
string connectionString = "connectionString";
RegistryManager registryManager;
DocumentClient client;
public Manager() {
registryManager = RegistryManager.CreateFromConnectionString(connectionString);
client = new DocumentClient(new Uri(EndpointUrl), PrimaryKey);
}
public async Task AddToHub(TraceWriter log, string macAddress) {
string deviceId = this.GenerateUniqueDevice(macAddress);
var device = new Device(deviceId);
try {
await registryManager.AddDeviceAsync(device);
}
catch(Exception e) {
log.Info($"{e.Message}");
}
}
public RegisterMessage ConvertMessage(string queueItem) {
return JsonConvert.DeserializeObject<RegisterMessage>(queueItem);
}
private string GenerateUniqueDevice(string macAddress)
{
...
}
}
this code is working perfectly fine on Visual Studio but inside Azure Function portal i got the following error
2018-02-28T14:30:28.454 [Info] Function started
(Id=3013dd9c-7248-4a01-8a4a-c087595eef97) 2018-02-28T14:30:28.720
at Microsoft.Azure.Devices.HttpClientHelper.d__36.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.HandleNonSuccessAndDebuggerNotifica>tion(Task task)
at Microsoft.Azure.Devices.HttpClientHelper.d__12`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.HandleNonSuccessAndDebuggerNotifica>tion(Task task)
at Submission#0.Manager.d__6.MoveNext() in >D:\home\site\wwwroot\PaymentQueueTrigger\run.csx:line 41
ID:041b47841b234f9287236022c701f479-G:7-TimeStamp:02/28/2018
14:30:28"} 2018-02-28T14:30:28.798 [Info] Function completed (Success,
Id=3013dd9c-7248-4a01-8a4a-c087595eef97, Duration=343ms)
But the device parameter isn't null when I log it.
Any idea ?
Related
I am trying to upload multiple files to Azure Storage asynchronously using Task.WhenAll(tasks);
However, I keep running into the following error
Microsoft.WindowsAzure.Storage.StorageException
HResult=0x80131500
Message=Error while copying content to a stream.
Source=Microsoft.WindowsAzure.Storage
StackTrace:
at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.<ExecuteAsyncInternal>d__4`1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.<UploadFromStreamAsyncHelper>d__34.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.<UploadFromStreamAsyncHelper>d__33.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at RetsIntegration.Services.AzureBlobStorage.<CreateAsync>d__9.MoveNext()
Inner Exception 1:
HttpRequestException: Error while copying content to a stream.
Inner Exception 2:
IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
Inner Exception 3:
SocketException: An existing connection was forcibly closed by the remote host
The error happens after a couple of minutes of executing the tasks.
I create multiple tasks to upload images using the following logic
public async Task ProcessTasks(IEnumerable<FileObject> files)
{
List<Task> tasks = new List<Task>();
foreach (FileObject file in files)
{
string path = GetImageFullName(file, file.Filename);
Task task Storage.CreateAsync(file.Content, path);
tasks.Add(task);
}
// begings the upload to Azure
await Task.WhenAll(tasks);
}
Here is the implementation of the CreateAsync method from the Storage class
public async Task CreateAsync(Stream stream, string path)
{
var azure = GetAzurePath(path);
// ContainerFactory is IBlobContainerFactory type
var container = await ContainerFactory.GetAsync();
CloudBlockBlob blockBlob = container.GetBlockBlobReference(azure);
await blockBlob.UploadFromStreamAsync(stream);
}
Here is how I create the Blob containers. Note when I create the container I increase the server timeout to 4 hours which should be plenty of time to complete the upload.
public class DefaultBlobContainerFactory : IBlobContainerFactory
{
private readonly CloudBlobContainer _container;
public DefaultBlobContainerFactory(AzureBlobOptions azureBlobOptions)
{
try
{
CloudBlobClient blobClient = GetClient(azureBlobOptions);
_container = blobClient.GetContainerReference(azureBlobOptions.DocumentContainer);
}
catch (StorageException)
{
throw;
}
}
protected virtual CloudBlobClient GetClient(AzureBlobOptions azureBlobOptions)
{
if (azureBlobOptions.ConnectionString != null && CloudStorageAccount.TryParse(azureBlobOptions.ConnectionString, out CloudStorageAccount cloudStorageAccount))
{
return cloudStorageAccount.CreateCloudBlobClient();
}
if (azureBlobOptions.BaseUri != null && azureBlobOptions.Token != null)
{
return new CloudBlobClient(azureBlobOptions.BaseUri, new StorageCredentials(azureBlobOptions.Token));
}
throw new ArgumentException("One of the following must be set: 'ConnectionString' or 'BaseUri'+'Token'!");
}
public async Task<CloudBlobContainer> GetAsync()
{
await _container.CreateIfNotExistsAsync(new BlobRequestOptions()
{
ServerTimeout = TimeSpan.FromHours(4),
}, null);
return _container;
}
}
What could be causing this issue? How can I fix it?
i am trying to make Azure AD B2C work in my xamarin app. to check if we already are logged in i am using a code like below.
public async Task<bool> IsLoggedIn()
{
IEnumerable<IAccount> accounts = await App.PCA.GetAccountsAsync();
if (accounts != null)
{
return accounts.Any();
}
return false;
}
}
My code on Start looks like this
protected async override void OnStart()
{
var authenticationService = Container.Resolve<IAuthenticationService>();
bool isLoggedIn;
isLoggedIn = await authenticationService.IsLoggedIn();
if (isLoggedIn)
{
var cachingService = Container.Resolve<ICachingService>();
AppUser = await authenticationService.Login(cachingService.CurrentMode);
await NavigationService.NavigateAsync("http://www.xxxx.com/root/navigation/main");
}
else
{
await NavigationService.NavigateAsync("http://www.xxxx.com/navigation/login");
}
}
}
if i just return false from IsLoggedIn it shows the login page properly.
But calling
IEnumerable<IAccount> accounts = await App.PCA.GetAccountsAsync();
seems to be problematic.
i get exception (sometimes) that
System.NullReferenceException: Object reference not set to an instance of an object
but looking at App object in "QuickWatch" i see PAC object being properly populated.
UPDATE
App.cs constructor looks like this
public static PublicClientApplication PCA = null;
public App(IPlatformInitializer initializer = null) : base(initializer)
{
PCA = new PublicClientApplication(GlobalSetting.Instance.ClientID, GlobalSetting.Instance.AuthoritySignUpSignIn);
PCA.RedirectUri = $"msal{GlobalSetting.Instance.ClientID}://auth";
}
my login method looks like this
public async Task<User> Login(string mode)
{
IEnumerable<IAccount> accounts = await App.PCA?.GetAccountsAsync();
AuthenticationResult ar;
try
{ //get token from cache.
ar = await App.PCA?.AcquireTokenSilentAsync(GlobalSetting.Instance.Scopes, GetAccountByPolicy(accounts, GlobalSetting.Instance.PolicySignUpSignIn), GlobalSetting.Instance.AuthoritySignUpSignIn, false);
}
catch (MsalUiRequiredException ex)
{
// get token from interaction.
ar = await App.PCA?.AcquireTokenAsync(GlobalSetting.Instance.Scopes, GetAccountByPolicy(accounts, GlobalSetting.Instance.PolicySignUpSignIn), App.UiParent);
}
//fetch token and make actual user object.
return new User
{
Id = _cachingService.LoggedInUserId,
Name = "Jessica Doe",
ProfilePicUrl = "https://content-static.upwork.com/uploads/2014/10/01xxx27/profilephoto1.jpg",
BusinessProfile = _userService.GetBusinessProfile(_cachingService.LoggedInUserId),
ProfileVariables = _userService.GetUserProfileVariables(_cachingService.LoggedInUserId),
Settings = _userService.GetSettings(_cachingService.LoggedInUserId)
};
}
it works when i dont call AcquireTokenSilentAsync and just send a fake User object and does not work when i call AcquireTokenSilentAsync.
ar object gets populated, it navigates to the main page hits it's view model constructor but but shows a blank page.
i have also tried diffrent versions of MSAL. now on the latest version.
UPdate2
drilled down to this exception
{Microsoft.Identity.Client.MsalClientException: The application does not have keychain access groups enabled in the Entitlements.plist. As a result, there was a failure to save to the iOS keychain. The keychain access group '3G3LMCD5R.com.microsoft.adalcache' is not enabled in the Entitlements.plist. See https://aka.ms/msal-net-enable-keychain-groups for more details on enabling keychain access groups and entitlements. at Microsoft.Identity.Core.iOSTokenCacheAccessor.Save (System.String account, System.String service, System.String generic, System.Int32 type, System.String value) [0x00052] in :0 at Microsoft.Identity.Core.iOSTokenCacheAccessor.SaveAccessToken (Microsoft.Identity.Core.Cache.MsalAccessTokenCacheItem item) [0x00028] in :0 at Microsoft.Identity.Core.Telemetry.TelemetryTokenCacheAccessor.SaveAccessToken (Microsoft.Identity.Core.Cache.MsalAccessTokenCacheItem item) [0x00000] in :0 at Microsoft.Identity.Core.Telemetry.TelemetryTokenCacheAccessor.SaveAccessToken (Microsoft.Identity.Core.Cache.MsalAccessTokenCacheItem item, Microsoft.Identity.Core.RequestContext requestContext) [0x0002a] in :0 at Microsoft.Identity.Client.TokenCache.SaveAccessAndRefreshToken (Microsoft.Identity.Core.Instance.IValidatedAuthoritiesCache validatedAuthoritiesCache, Microsoft.Identity.Core.Instance.IAadInstanceDiscovery aadInstanceDiscovery, Microsoft.Identity.Client.Internal.Requests.AuthenticationRequestParameters requestParams, Microsoft.Identity.Core.OAuth2.MsalTokenResponse response) [0x00143] in :0 at Microsoft.Identity.Client.Internal.Requests.RequestBase.CacheTokenResponseAndCreateAuthenticationResult (Microsoft.Identity.Core.OAuth2.MsalTokenResponse msalTokenResponse) [0x001b4] in :0 at Microsoft.Identity.Client.Internal.Requests.InteractiveRequest+d__9.MoveNext () [0x00168] in :0 --- End of stack trace from previous location where exception was thrown --- at Microsoft.Identity.Client.Internal.Requests.RequestBase+d__28.MoveNext () [0x00160] in :0 --- End of stack trace from previous location where exception was thrown --- at Microsoft.Identity.Client.PublicClientApplication+d__24.MoveNext () [0x000ef] in :0 --- End of stack trace from previous location where exception was thrown --- at Microsoft.Identity.Client.PublicClientApplication+d__17.MoveNext () [0x000ac] in :0 --- End of stack trace from previous location where exception was thrown --- at CDThat.Services.AzureADB2CAuthenticationService+d__3.MoveNext () [0x000fc] in C:\CDthatbest\CDThat\Services\AzureADB2CAuthenticationService.cs:45 --- End of stack trace from previous location where exception was thrown --- at CDThat.ViewModels.LoginPageViewModel+d__8.MoveNext () [0x0003c] in C:\CDthatbest\CDThat\ViewModels\LoginPageViewModel.cs:56 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.b__6_0 (System.Object state) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/12.2.1.11/src/Xamarin.iOS/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:1023 at Foundation.NSAsyncSynchronizationContextDispatcher.Apply () [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/12.2.1.11/src/Xamarin.iOS/Foundation/NSAction.cs:178 at (wrapper managed-to-native) UIKit.UIApplication.UIApplicationMain(int,string[],intptr,intptr) at UIKit.UIApplication.Main (System.String[] args, System.IntPtr principal, System.IntPtr delegate) [0x00005] in /Library/Frameworks/Xamarin.iOS.framework/Versions/12.2.1.11/src/Xamarin.iOS/UIKit/UIApplication.cs:79 at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0002c] in /Library/Frameworks/Xamarin.iOS.framework/Versions/12.2.1.11/src/Xamarin.iOS/UIKit/UIApplication.cs:63 at CDThat.iOS.Application.Main (System.String[] args) [0x00014] in C:\CDthatbest\CDThat.iOS\Main.cs:16 ErrorCode: missing_entitlements}
It might be a timing issue (accessing the PCA property to early). I would first change the code to handle the empty PCA property more gracefully:
public async Task<bool> IsLoggedIn()
{
// Added a null check on the PCA property
IEnumerable<IAccount> accounts = await App.PCA?.GetAccountsAsync();
if (accounts != null)
{
return accounts.Any();
}
return false;
}
}
And then try a different event (such as PageAppearing) instead of OnStart to access the PCA property.
Hope it helps!
I have a strange issue with a stateful service timing out, only when called downstream by another service.
The idea of this project is to record the latency of hops between nodes, given n number of hops. The implementation is in 3 projects:
API - to call downstream to the worker
Worker Service - to decrement a count and call another WorkerService
Result Service - to record the results to be fetched by the API.
The solution throws an exception both on premise and in Azure cloud, but works perfectly locally.
Implementation:
internal sealed class WorkerService : StatelessService, IHopWorker
{
public WorkerService(StatelessServiceContext context)
: base(context)
{ }
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return this.CreateServiceRemotingInstanceListeners();
}
public async Task Hop(HopCounter counter)
{
counter.HopCount = counter.HopCount - 1;
counter.JunctionIds.Add(Context.NodeContext.NodeId.ToString());
if (counter.HopCount < 1)
{
counter.Completed = DateTime.Now;
await new ServiceProxyFactory().CreateServiceProxy<IResultService>(new Uri("fabric:/AsfNetworkHops/ResultsService"), new ServicePartitionKey("Data")).AddResults(counter);
}
else
{
await new ServiceProxyFactory().CreateServiceProxy<IHopWorker>(new Uri("fabric:/AsfNetworkHops/WorkerService"), targetReplicaSelector: TargetReplicaSelector.RandomInstance).Hop(counter);
}
}
}
Result Service
internal sealed class ResultsService : StatefulService, IResultService
{
Task<IReliableDictionary<string, HopCounter>> Results => StateManager.GetOrAddAsync<IReliableDictionary<string, HopCounter>>("results");
public ResultsService(StatefulServiceContext context)
: base(context, new ReliableStateManager(context, new ReliableStateManagerConfiguration(
new ReliableStateManagerReplicatorSettings
{
MaxReplicationMessageSize = 1073741824
})))
{
}
protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
{
return this.CreateServiceRemotingReplicaListeners();
}
public async Task AddResults(HopCounter counter)
{
using (var transcation = StateManager.CreateTransaction())
{
var results = await Results;
await results.AddAsync(transcation, Guid.NewGuid().ToString(), counter);
await transcation.CommitAsync();
}
}
public async Task<HopCounter[]> GetResults()
{
IList<HopCounter> results = new List<HopCounter>();
using (var tx = StateManager.CreateTransaction())
{
var res = await Results;
var enumerator = (await res.CreateEnumerableAsync(tx)).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(new CancellationToken()))
{
results.Add(enumerator.Current.Value);
}
await tx.CommitAsync();
return results.ToArray();
}
}
}
API Layer
[Route("api/[controller]")]
public class HopController : Controller
{
[HttpGet]
[Route("health")]
public IActionResult Health()
{
return Ok("OK");
}
[HttpGet]
[Route("start")]
public async Task<IActionResult> Start(int hopCount = 10)
{
try
{
var counter = new HopCounter();
counter.HopCount = hopCount;
counter.Initiated = DateTime.Now;
IHopWorker worker = null;
try
{
worker = new ServiceProxyFactory().CreateServiceProxy<IHopWorker>(new Uri("fabric:/AsfNetworkHops/WorkerService"));
}
catch (Exception excep)
{
return Ok($"Error creating proxy {excep.Message} {excep.StackTrace}");
}
await worker.Hop(counter);
return Ok();
}
catch (Exception excep)
{
return Ok(excep);
}
}
[HttpGet]
[Route("results")]
public async Task<IActionResult> Results()
{
try
{
IResultService results = null;
try
{
results = new ServiceProxyFactory().CreateServiceProxy<IResultService>(
new Uri("fabric:/AsfNetworkHops/ResultsService"), new ServicePartitionKey("Data"));
}
catch (Exception excep)
{
return Ok($"Error creating proxy {excep.Message} {excep.StackTrace}");
}
return Ok(await results.GetResults());
}
catch (Exception excep)
{
return Ok(excep);
}
}
}
App Manifest:
<ApplicationManifest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ApplicationTypeName="AsfNetworkHopsType" ApplicationTypeVersion="1.0.0" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<Parameters>
<Parameter Name="ResultsService_MinReplicaSetSize" DefaultValue="3" />
<Parameter Name="ResultsService_PartitionCount" DefaultValue="1" />
<Parameter Name="ResultsService_TargetReplicaSetSize" DefaultValue="3" />
<Parameter Name="NetworkHopsAPI_InstanceCount" DefaultValue="-1" />
<Parameter Name="WorkerService_InstanceCount" DefaultValue="-1" />
</Parameters>
<!-- Import the ServiceManifest from the ServicePackage. The ServiceManifestName and ServiceManifestVersion
should match the Name and Version attributes of the ServiceManifest element defined in the
ServiceManifest.xml file. -->
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="ResultsServicePkg" ServiceManifestVersion="1.0.0" />
<ConfigOverrides />
</ServiceManifestImport>
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="NetworkHopsAPIPkg" ServiceManifestVersion="1.0.0" />
<ConfigOverrides />
</ServiceManifestImport>
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="WorkerServicePkg" ServiceManifestVersion="1.0.0" />
<ConfigOverrides />
</ServiceManifestImport>
<DefaultServices>
<!-- The section below creates instances of service types, when an instance of this
application type is created. You can also create one or more instances of service type using the
ServiceFabric PowerShell module.
The attribute ServiceTypeName below must match the name defined in the imported ServiceManifest.xml file. -->
<Service Name="ResultsService" ServicePackageActivationMode="ExclusiveProcess">
<StatefulService ServiceTypeName="ResultsServiceType" TargetReplicaSetSize="[ResultsService_TargetReplicaSetSize]" MinReplicaSetSize="[ResultsService_MinReplicaSetSize]">
<NamedPartition>
<Partition Name="Data" />
</NamedPartition>
</StatefulService>
</Service>
<Service Name="NetworkHopsAPI" ServicePackageActivationMode="ExclusiveProcess">
<StatelessService ServiceTypeName="NetworkHopsAPIType" InstanceCount="[NetworkHopsAPI_InstanceCount]">
<SingletonPartition />
</StatelessService>
</Service>
<Service Name="WorkerService" ServicePackageActivationMode="ExclusiveProcess">
<StatelessService ServiceTypeName="WorkerServiceType" InstanceCount="[WorkerService_InstanceCount]">
<SingletonPartition />
</StatelessService>
</Service>
</DefaultServices>
</ApplicationManifest>
DTO
[DataContract]
[Serializable]
public class HopCounter
{
[DataMember]
private DateTime _completed;
[DataMember]
public DateTime Initiated { get; set; }
[DataMember]
public DateTime Completed
{
get { return _completed; }
set
{
_completed = value;
MilisecondsTaken = (Completed - Initiated).Milliseconds;
}
}
[DataMember]
public int HopCount { get; set; }
[DataMember]
public List<string> JunctionIds { get; set; } = new List<string>();
[DataMember]
public bool WorkerOnly { get; set; }
[DataMember]
public double MilisecondsTaken { get; set; }
}
The timeout only occurs if the Results Service is called, otherwise it returns a HTTP 200
This happens in both .Net Core & .Net 4.6.1 so must be the pattern I am using but it seems like a pretty normal access pattern to me.
I have an example application here.
Can anyone help?
The error is:
The operation has timed out. at
Microsoft.ServiceFabric.Replicator.DynamicStateManager.d__188.MoveNext()
--- End of stack trace from previous location where exception was thrown --- at
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) at
Microsoft.ServiceFabric.Replicator.DynamicStateManager.d__187.MoveNext()
--- End of stack trace from previous location where exception was thrown --- at
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) at
Microsoft.ServiceFabric.Replicator.DynamicStateManager.d__170.MoveNext()
--- End of stack trace from previous location where exception was thrown --- at
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) at
Microsoft.ServiceFabric.Replicator.DynamicStateManager.d__1091.MoveNext()
--- End of stack trace from previous location where exception was thrown --- at
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) at
Microsoft.ServiceFabric.Data.ReliableStateManagerImpl.<Microsoft-ServiceFabric-Data-IReliableStateManager-GetOrAddAsync>d__231.MoveNext()
--- End of stack trace from previous location where exception was thrown --- at
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) at
Microsoft.ServiceFabric.Data.ReliableStateManagerImpl.d__251.MoveNext()
--- End of stack trace from previous location where exception was thrown --- at
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at Results.Results.d__4.MoveNext() in
C:\dev\asf-latency\Results\Results.cs:line 42
I have a working Azure App Service connected to a Notification Hub configured with GCM and APNS. It has been working perfectly for months with on both platforms.
I have now turned on authentication in the app service and configured google and facebook. These also work perfectly, and the correct access is honoured for the easy tables.
However, device registration from the mobile app now fails since the authentication has been turned on.
The following is the error I am getting on the app service (NodeJS):
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.Azure.AppService.Push.PushRequestHandler.<HandleCreateOrUpdateInstallationAsync>d__14.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.Azure.AppService.Push.PushRequestHandler.<HandlePushRequestAsync>d__f.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.Azure.AppService.Push.PushModule.<OnPostAuthenticateRequestAsync>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 Microsoft.Azure.AppService.Authentication.HttpModuleDispatcher.<DispatchAsync>d__13.MoveNext()
2016-11-14T09:43:00 PID[7348] Information Sending response: 500.79 Internal Server Error
2016-11-14T09:43:00 PID[7348] Critical System.ComponentModel.Win32Exception (0x80004005): An operation was attempted on a nonexistent network connection
at CHttpRequest.ReadEntityBody(Byte[] buffer, Int32 maxLength, Boolean allowAsync, Int32& bytesReceived, Int32& bytesRemaining, Boolean& completionPending)
at Microsoft.Azure.AppService.Authentication.HttpRequestBase.AsyncReadHelper.Read()
at Microsoft.Azure.AppService.Authentication.HttpRequestBase.AsyncReadHelper..ctor(HttpRequestBase request, Int32 maxLength)
at Microsoft.Azure.AppService.Authentication.HttpRequestBase.<ReadRequestContentAsync>d__8.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.Azure.AppService.Push.PushRequestHandler.<HandleCreateOrUpdateInstallationAsync>d__14.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.Azure.AppService.Push.PushRequestHandler.<HandlePushRequestAsync>d__f.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.Azure.AppService.Push.PushModule.<OnPostAuthenticateRequestAsync>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 Microsoft.Azure.AppService.Authentication.HttpModuleDispatcher.<DispatchAsync>d__13.MoveNext()
2016-11-14T09:43:00 PID[7348] Information Sending response: 500.79 Internal Server Error
I am able to send notifications (using test send and via my server push code) to existing registrations, I am just not able to create new registrations.
When I turn the authentication off, it all works normally again.
Do I need to manually create the registrations in the notification hub in this authentication scenario?
I am at a loss as to where I am going wrong, so any help would be greatly appreciated.
As an alternative to the RegisterAsync that is causing the problem; you can use a HttpClient call to PUT a Notification Hub installation. The following code will set up the installation on Android, for example:
public async Task RegisterForPushNotifications(MobileServiceClient client)
{
if (GcmClient.IsRegistered(RootView))
{
try
{
var registrationId = GcmClient.GetRegistrationId(RootView);
//var push = client.GetPush();
//await push.RegisterAsync(registrationId);
var installation = new DeviceInstallation
{
InstallationId = client.InstallationId,
Platform = "gcm",
PushChannel = registrationId
};
// Set up tags to request
installation.Tags.Add("topic:Sports");
// Set up templates to request
PushTemplate genericTemplate = new PushTemplate
{
Body = "{\"data\":{\"message\":\"$(messageParam)\"}}"
};
// Register with NH
var response = await client.InvokeApiAsync<DeviceInstallation, DeviceInstallation>(
$"/push/installations/{client.InstallationId}",
installation,
HttpMethod.Put,
new Dictionary<string, string>());
}
catch (Exception ex)
{
Log.Error("DroidPlatformProvider", $"Could not register with NH: {ex.Message}");
}
}
else
{
Log.Error("DroidPlatformProvider", $"Not registered with GCM");
}
}
The DeviceInstallation class looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace TaskList.Abstractions
{
public class DeviceInstallation
{
public DeviceInstallation()
{
Tags = new List<string>();
Templates = new Dictionary<string, PushTemplate>();
}
[JsonProperty(PropertyName = "installationId")]
public string InstallationId { get; set; }
[JsonProperty(PropertyName = "platform")]
public string Platform { get; set; }
[JsonProperty(PropertyName = "pushChannel")]
public string PushChannel { get; set; }
[JsonProperty(PropertyName = "tags")]
public List<string> Tags { get; set; }
[JsonProperty(PropertyName = "templates")]
public Dictionary<string, PushTemplate> Templates { get; set; }
}
public class PushTemplate
{
public PushTemplate()
{
Tags = new List<string>();
Headers = new Dictionary<string, string>();
}
[JsonProperty(PropertyName = "body")]
public string Body { get; set; }
[JsonProperty(PropertyName = "tags")]
public List<string> Tags { get; set; }
[JsonProperty(PropertyName = "headers")]
public Dictionary<string, string> Headers { get; set; }
}
}
Place the RegisterForPushNotifications() method in your platform-specific code. The DeviceInstallation can be in a PCL.
This is an issue with the push blade, and not something you can solve by yourself. I've reached out via email so that we can support you directly.
Not sure if you are using Xamarin.Forms but I am and been struggling with this for a week and a half.
Found that:
Firebase Cloud Messaging (FCM) is the new version of GCM
Firebase library cannot be installed in Xamarin forms due to version conflict of Android Support lib
Workaround provided by Habib Ali (not tested by me yet)
i am trying to insert an image from an Win 8 App into Azure blob .I am running into an 500 exception when i try to do this . This is the class i am using -
private MobileServiceCollection<TodoItem, TodoItem> items;
private IMobileServiceTable<TodoItem> todoTable = App.MobileService.GetTable<TodoItem>();
[DataContract]
public class TodoItem
{
[DataMember(Name = "id")]
public int ID { get; set; }
[DataMember(Name = "text")]
public string Text { get; set; }
[DataMember(Name = "containerName")]
public string ContainerName { get; set; }
[DataMember(Name = "resourceName")]
public string ResourceName { get; set; }
[DataMember(Name = "sasQueryString")]
public string SasQueryString { get; set; }
[DataMember(Name = "imageUri")]
public string ImageUri { get; set; }
}
The Exception is thrown at line -await todoTable.InsertAsync(todoItem);
At this time the exception is thrown the value of SASQueryString and ImageUri is NULL.
private async void OnTakePhotoClick(object sender, RoutedEventArgs e)
{
// Capture a new photo or video from the device.
CameraCaptureUI cameraCapture = new CameraCaptureUI();
media = await cameraCapture
.CaptureFileAsync(CameraCaptureUIMode.PhotoOrVideo);
TodoItem todoitem = new TodoItem { Text="NA",ContainerName="todoitemimages"};
InsertTodoItem(todoitem);
}
private async void InsertTodoItem(TodoItem todoItem)
{
string errorString = string.Empty;
if (media != null)
{
// Set blob properties of TodoItem.
todoItem.ResourceName = media.Name;
}
// Send the item to be inserted. When blob properties are set this
// generates an SAS in the response.
await todoTable.InsertAsync(todoItem);
// If we have a returned SAS, then upload the blob.
if (!string.IsNullOrEmpty(todoItem.SasQueryString))
{
// Get the new image as a stream.
using (var fileStream = await media.OpenStreamForReadAsync())
{
// Get the URI generated that contains the SAS
// and extract the storage credentials.
StorageCredentials cred = new StorageCredentials(todoItem.SasQueryString);
var imageUri = new Uri(todoItem.ImageUri);
// Instantiate a Blob store container based on the info in the returned item.
CloudBlobContainer container = new CloudBlobContainer(
new Uri(string.Format("https://{0}/{1}",
imageUri.Host, todoItem.ContainerName)), cred);
// Upload the new image as a BLOB from the stream.
CloudBlockBlob blobFromSASCredential =
container.GetBlockBlobReference(todoItem.ResourceName);
await blobFromSASCredential.UploadFromStreamAsync(fileStream.AsInputStream());
}
}
// Add the new item to the collection.
items.Add(todoItem);
}
IS there anyway i can resolve this exception .Thanks.
These are the exception details -
Microsoft.WindowsAzure.MobileServices.MobileServiceInvalidOperationException
was unhandled HResult=-2146233079 Message=Error: Internal Server
Error Source=Microsoft.Threading.Tasks StackTrace:
at Microsoft.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task)
at Microsoft.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccess(Task
task)
at Microsoft.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at Microsoft.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.WindowsAzure.MobileServices.MobileServiceTable`1.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 DeltaVMobile.CrudeStorageScenario.d_22.MoveNext() in
c:\Users\~
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.b__0(Object
state)
at System.Threading.WinRTSynchronizationContext.Invoker.InvokeCore()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext
executionContext, ContextCallback callback, Object state, Boolean
preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean
preserveSyncCtx)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch() InnerException:
By default, Azure Mobile Services have "dynamic schema" enabled, which means that you don't really need to define the columns in your tables - as long as you insert data, it will "figure out" the appropriate type and create the column for you. But it needs to figure out which type to use. In your case, this is the request which will be sent to the service (pretty-printing of JSON added for clarity, in reality it's sent without unnecessary whitespaces):
POST .../tables/TodoItem
Content-Type: application/json
{
"text":null,
"containerName":"todoitemimages",
"resourceName":null,
"sasQueryString":null,
"imageUri":null
}
When this gets to the service for the first time, it knows that you're trying to insert columns such as "text", "resourceName", but since there is no value associated to it (null can be of any type), it will fail to insert that data.
If this is indeed your problem, you have basically two choices: a simple one is to do a dummy insert once during development with all members of the type with some value - and right away issue a delete for the item which was inserted. This way the columns will be created and after that the runtime doesn't have to "guess" their types. The other choice is to set the EmitDefaultValue property in the [DataMember] attribute to false, which will make the serializer not emit the fields in the request with a null value.