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
Related
I'm using System.Reactive within my ios project and i'm aware i need to use ObserveOn in order to specify on which thread to execute the subscriber on. However i can't seem to get this working properly.
For all i can tell this should be working, or am i implementing it wrong?
public class UiContext : IScheduler
{
/// <inheritdoc />
public IDisposable Schedule<TState>(TState state, Func<IScheduler, TState, IDisposable> action)
{
NSOperationQueue.MainQueue.AddOperation(() => action(this, state));
return Disposable.Empty;
}
/// <inheritdoc />
public IDisposable Schedule<TState>(TState state, TimeSpan dueTime, Func<IScheduler, TState, IDisposable> action)
{
NSOperationQueue.MainQueue.AddOperation(() => action(this, state));
return Disposable.Empty;
}
/// <inheritdoc />
public IDisposable Schedule<TState>(TState state, DateTimeOffset dueTime, Func<IScheduler, TState, IDisposable> action)
{
NSOperationQueue.MainQueue.AddOperation(() => action(this, state));
return Disposable.Empty;
}
/// <inheritdoc />
public DateTimeOffset Now { get; }
}
void SomeMethod()
{
WhenValidationChanged
.ObserveOn(new UiContext())
.SubscribeOn(new UiContext())
.Throttle(TimeSpan.FromMilliseconds(50))
.Subscribe(OnValidationChanged);
}
private void OnValidationChanged(object obj)
{
if (TableView.DataSource is InfoFieldsDataSource dataSource)
{
var validationErrors = dataSource.Items.OfType<InfoFieldViewModelBase>().Count(d => !d.IsValid);
// Exception is raised about not being executed on UI thread
_validationController.View.BackgroundColor = validationErrors > 0 ? UIColor.Green : UIColor.Red;
}
}
Calling .ObserveOn(new UiContext()) before .Throttle(TimeSpan.FromMilliseconds(50)) probably has no effect as Throttle can change the scheduler - each operator can change the scheduler. You should always do .ObserveOn just before the operator or subscribe call you want it applied to.
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 ?
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 need another pair of eyes to take a look at this. It's driving me nuts.
I am intermittently getting a 'System.AggregateException' when running a console app that connects to a web api.
I am doing this in a local testing environment through visual studio(IIS Express).
As stated, I have two different apps running locally on IIS Express(2 different ports). One is a console app and the other is a web api. The console app connects to the web api.
It's about 50/50 if it works or not. 50% of the time it works fine and spits out the expected results. But the other 50% of the time, it fails with the errors below. When it does fail, it's always immediate, like 2 or 3 seconds after starting the console app.
After some Googling and fiddling around with various settings, I know it's not either of these:
not a timeout issue
not a firewall issue
I've tried setting breakpoints at various points, but it never really reveals anything significant.
The exception I get when it fails is:
An exception of type 'System.AggregateException' occurred in mscorlib.dll but was not handled in user code
Here is the inner exception:
No connection could be made because the target machine actively refused it http://localhost:45321
The stack trace indicates:
at System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult, TransportContext& context)
at System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar)
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task1.GetResultCore(Boolean waitCompletionNotification)
at System.Threading.Tasks.Task1.get_Result()
at BeatGenerator.BeatGeneratorMain.<>c.b__2_0(Task1 postTask) in C:\Users\xxx\Documents\VS2012\DrumBeats\BeatGenerator\BeatGeneratorMain.cs:line 72
at System.Threading.Tasks.ContinuationResultTaskFromResultTask2.InnerInvoke()
at System.Threading.Tasks.Task.Execute()
Here is the error line:
var response = await http.PostAsJsonAsync("http://localhost:45321/api/drumcorp/beats/generate", drumbeat)
.ContinueWith((postTask) => postTask.Result.EnsureSuccessStatusCode());
This is the console app that connects to API controller:
public class DrumBeats
{
public int StartBeat { get; set; }
public int EndBeat { get; set; }
public int ChordId { get; set; }
}
public class BeatGeneratorMain
{
static void Main(string[] args)
{
Generate().Wait();
}
private static async Task Generate()
{
var drumbeat = new DrumBeats();
drumbeat.ChordId = 122;
drumbeat.StartBeat = 2;
drumbeat.EndBeat = 4;
var creds = new NetworkCredential("testUser", "xxxx", "xxx"); //username, pw, domain
var handler = new HttpClientHandler { Credentials = creds };
using (var http = new HttpClient(handler))
{
http.Timeout = TimeSpan.FromMinutes(10);
var response = await http.PostAsJsonAsync("http://localhost:45321/api/drumcorp/beats/generate", drumbeat)
.ContinueWith((postTask) => postTask.Result.EnsureSuccessStatusCode());
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
}
This is the relevant section of the web api controller app:
public class DrumBeats //same as in console app
{
public int StartBeat { get; set; }
public int EndBeat { get; set; }
public int ChordId { get; set; }
}
[HttpPost("api/drumcorp/beats/generate")]
public string PostMethodBeats([FromBody] DrumBeats drumbeat)
{
string beatsChart = DrumBeatMaster.ReturnBeatsChart(DrumBeats.ChordId, DrumBeats.StartBeat, DrumBeats.EndBeat);
var mesg = "<b>Beats Created</b><br /><br /> ";
return mesg + beatsChart;
}
DrumBeatMaster.ReturnBeatsChart is just a simple helper method that processes the beats and spits out a string.
To understand what is the exception you will have to catch the aggregate exception and throw them flattened like
try
{
// Your code
}
catch (AggregateException agg)
{
throw agg.Flatten();
}
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.