0
votes

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:

1
I have the same issue. Did you managed to resolve this problem? If so, would you write the solution?fzl

1 Answers

0
votes

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.