public async void Should_UploadContinue_Success_200_Pdf() { var request = TestFactory.CreateHttpRequestWithDataStream("Data/Sample 1.pdf"); var uploadDir = _app.Repository.GetBlobDirectory(BlobNames.UploadDirectory + "/test"); var uploadTmpTable = _app.Repository.GetTable(TableNames.CommUpload); var tmpUploadEntity = new TableEntityAdapter <UploadSession>( new UploadSession { SessionId = "test" }, "test", new IdGenerator().UploadSessionId()); // call Azure Function var response = (ObjectResult)await UploadFunctions.Continue(request, "test", $"{DateTime.Now:u} Sample 1.pdf", uploadDir, tmpUploadEntity, uploadTmpTable, _logger); var upload = response.Value.IsOrMap <UploadSession>(); Assert.Equal(StatusCodes.Status200OK, response.StatusCode); Assert.Null(upload.ManifestFile); Assert.Contains("test", upload.SessionId); Assert.Contains("Sample 1.pdf", upload.LastUploadedFile); _output.WriteLine(upload.ToJson(Formatting.Indented)); }
public async void Should_UploadContinue_Fail_400_With_No_Filename() { var request = TestFactory.CreateHttpRequestWithDataStream($"Data/Sample 1.pdf"); var uploadDir = _app.Repository.GetBlobDirectory(BlobNames.UploadDirectory + "/test"); var uploadTmpTable = _app.Repository.GetTable(TableNames.CommUpload); var tmpUploadEntity = new TableEntityAdapter <UploadSession>( new UploadSession { SessionId = "test" }, "test", new IdGenerator().UploadSessionId()); // call Azure Function var response = (ObjectResult)await UploadFunctions.Continue(request, "test", null, uploadDir, tmpUploadEntity, uploadTmpTable, _logger); var upload = response.Value.IsOrMap <UploadSession>(); Assert.Equal(StatusCodes.Status400BadRequest, response.StatusCode); Assert.Null(upload.ManifestFile); Assert.Null(upload.LastUploadedFile); Assert.Equal("A filename is required. (Parameter 'filename')", upload.Errors); _output.WriteLine(upload.ToJson(Formatting.Indented)); }
public static async Task <IActionResult> Continue( [HttpTrigger(AuthorizationLevel.Function, "post", Route = ServiceNames.UploadContinue + "/{session}/{filename}")] HttpRequest req, string session, string filename, [Blob(BlobNames.UploadDirectory + "/{session}")] CloudBlobDirectory uploadDir, [Table(TableNames.CommUpload, CommUploadPartitionKeys.Temp, "{session}")] TableEntityAdapter <UploadSession> upload, [Table(TableNames.CommUpload)] CloudTable uploadTable, ILogger log) { try { if (filename.IsNullOrEmpty()) { throw new ArgumentException("A filename is required.", nameof(filename)); } var uploadTo = await req.Body.UploadTo(uploadDir, filename); upload.OriginalEntity.ManifestFile = new[] { upload.OriginalEntity.ManifestFile, filename }.IsIfManifest(); upload.OriginalEntity.LastUploadedFile = filename; var result = await upload.UpdateIn(uploadTable); return(new OkObjectResult(upload.OriginalEntity)); } catch (Exception ex) { log.LogError(ex.StackTrace); return(new BadRequestObjectResult(new UploadSession { Errors = ex.Message })); } }
public static async Task DeliveryPostage( [QueueTrigger(QueueNames.CommSendPostage)] MessageDispatch sendMessage, [Table(TableNames.CommSchedule, CommSchedulePartitionKeys.InProgress, "{RowKey}")] TableEntityAdapter <MessageSchedule> schedule, [Table(TableNames.CommMessage, CommMessagePartitionKeys.Created, "{MessageReference}")] TableEntityAdapter <Message> message, [Table(TableNames.CommSchedule)] CloudTable scheduleTable, [Inject] App app, [Inject] IScheduleIdGenerator idGenerator, ILogger log) { if (schedule == null) { return; } var postage = message.GetMessageOf <Postage>(); // handle unexpected non existing message if (postage == null) { await schedule.MoveTo(scheduleTable, s => CommSchedulePartitionKeys.Skipped).ConfigureAwait(false); return; } await schedule.MarkScheduleSent(scheduleTable, app, idGenerator); }
public async void Should_UploadEnd_Fail_400_With_No_Data() { var request = TestFactory.CreateHttpRequest("none", "nil"); var uploadDir = _app.Repository.GetBlobDirectory(BlobNames.UploadDirectory + "/test"); var uploadTmpTable = _app.Repository.GetTable(TableNames.CommUpload); var queue = _app.Repository.GetQueue(QueueNames.CommProcess); var tmpUploadEntity = new TableEntityAdapter <UploadSession>( new UploadSession { SessionId = "test" }, "test", new IdGenerator().UploadSessionId()); // call Azure Function var response = (ObjectResult)await UploadFunctions.End(request, "test", $"{DateTime.Now:u} Sample 2.pdf", uploadDir, tmpUploadEntity, uploadTmpTable, queue, _app.App, _logger); var upload = response.Value.IsOrMap <UploadSession>(); Assert.Equal(StatusCodes.Status400BadRequest, response.StatusCode); Assert.Null(upload.ManifestFile); Assert.Null(upload.LastUploadedFile); Assert.Null(upload.UploadEnd); _output.WriteLine(upload.ToJson(Formatting.Indented)); }
public static async Task <TableEntityAdapter <T> > MoveTo <T>(this TableEntityAdapter <T> record , CloudTable cloudTable, Func <T, string> partitionKey, Func <T, string> rowKey = null, Func <T, T> updateOriginalEntity = null) { // update the OriginalEntity.Property value has cause some funny error without cloning the object // System.Private.CoreLib: Exception while executing function: TransferEnd. // Microsoft.Azure.WebJobs.Host: Error while handling parameter upload after function returned:. // Microsoft.WindowsAzure.Storage: Not Found. // var oe = record.OriginalEntity; var oe = record.OriginalEntity.JClone <T>(); var moveEntity = new TableEntityAdapter <T>( updateOriginalEntity == null ? oe : updateOriginalEntity(oe) , partitionKey(oe) , rowKey == null ? record.RowKey : rowKey(oe) ); var operations = new[] { record.CreateOperationDelete(), moveEntity.CreateOperationInsert(), } .Where(op => op != null) .Select(cloudTable.ExecuteAsync) .ToArray(); await Task.WhenAll(operations); return(moveEntity); }
public async Task ProcessWebhookEvents( [QueueTrigger(WebhookQueueNames.ProcessWebhookEvents)] Tuple <string, string> keys, [Table(nameof(WebhookContainerName.WebhookPayloads), nameof(PartitionKeyValue.New), "{Item2}")] TableEntityAdapter <PayloadContent> context, [CosmosDB(nameof(DatabaseName.Sufong2001), nameof(WebhookContainerName.WebhookPayloads), ConnectionStringSetting = DatabaseConfig.CosmosDbConnectionString)] IAsyncCollector <InvoiceEntity> invoicesOut, [Table(nameof(WebhookContainerName.WebhookPayloads))] CloudTable payloadTable, ILogger log) { if (context == null) { return; } var getInvoices = context.OriginalEntity.Payload.To <Payload>().Events .Where(e => e.EventCategory == "INVOICE") .GroupBy(e => e.TenantId) .Select(GetInvoicesAsync); // Get Invoice details from Xero var result = await Task.WhenAll(getInvoices); var invoices = result.SelectMany(i => i); var operations = invoices.Select(i => invoicesOut.AddAsync(i)); await Task.WhenAll(operations); await context.MoveTo(payloadTable, p => nameof(PartitionKeyValue.Processed)); }
public IHttpActionResult SetAvatar(ODataActionParameters parameters) { if (!ModelState.IsValid) { return(BadRequest()); } var userId = Request.Headers.Authorization.Parameter.Split(':')[0]; string avatarUrl = (string)parameters["avatarUrl"]; TableOperation retrieveOperation = TableOperation.Retrieve <TableEntityAdapter <User> >("User", userId); TableResult retrievedResult = UserTable.Execute(retrieveOperation); TableEntityAdapter <User> userEntity = (TableEntityAdapter <User>)retrievedResult.Result; if (userEntity != null) { userEntity.OriginalEntity.AvatarUrl = avatarUrl; TableOperation updateOperation = TableOperation.Replace(userEntity); UserTable.Execute(updateOperation); return(Ok()); } else { return(BadRequest("User does not exist.")); } }
public IHttpActionResult Delete(string formId) { // Create a retrieve operation that expects a customer entity. TableOperation retrieveOperation = TableOperation.Retrieve <TableEntityAdapter <Form> >("test", formId); // Execute the operation. TableResult retrievedResult = FormTable.Execute(retrieveOperation); // Assign the result to a Form. TableEntityAdapter <Form> formAdapter = (TableEntityAdapter <Form>)retrievedResult.Result; // Create the Delete TableOperation. if (formAdapter != null) { TableOperation deleteOperation = TableOperation.Delete(formAdapter); // Execute the operation. FormTable.Execute(deleteOperation); return(StatusCode(HttpStatusCode.NoContent)); } else { return(NotFound()); } }
/// <summary> /// Gets the size of the adapter in bytes. Calculates based from /// https://blogs.msdn.microsoft.com/avkashchauhan/2011/11/30/how-the-size-of-an-entity-is-caclulated-in-windows-azure-table-storage/ /// </summary> /// <typeparam name="T"></typeparam> /// <param name="adapter"></param> /// <returns></returns> public static int GetAdapterSize <T>(this TableEntityAdapter <T> adapter) { var messageSize = 4; // Message Overhead messageSize += !string.IsNullOrEmpty(adapter.PartitionKey) ? adapter.PartitionKey.Length * 2 : 0; messageSize += !string.IsNullOrEmpty(adapter.RowKey) ? adapter.RowKey.Length + 2 : 0; var properties = adapter.WriteEntity(new OperationContext()); foreach (var kp in properties) { var propertySize = 8; // Property Overhead propertySize += kp.Key.Length * 2; switch (kp.Value.PropertyType) { case EdmType.String: propertySize += !string.IsNullOrEmpty(kp.Value.StringValue) ? kp.Value.StringValue.Length * 2 + 4 : 0; break; case EdmType.Binary: propertySize += kp.Value.BinaryValue?.Length + 4 ?? 0; break; case EdmType.Boolean: propertySize += kp.Value.BooleanValue.HasValue ? 1 : 0; break; case EdmType.DateTime: propertySize += kp.Value.DateTime.HasValue ? 8 : 0; break; case EdmType.Double: propertySize += kp.Value.DoubleValue.HasValue ? 8 : 0; break; case EdmType.Guid: propertySize += kp.Value.GuidValue.HasValue ? 16 : 0; break; case EdmType.Int32: propertySize += kp.Value.Int32Value.HasValue ? 4 : 0; break; case EdmType.Int64: propertySize += kp.Value.Int64Value.HasValue ? 8 : 0; break; default: throw new ArgumentOutOfRangeException(); } messageSize += propertySize; } return(messageSize); }
public async Task StoreCode(Code item) { var table = await GetCloudTable(_appSecretSettings.TableStorageConnectionString, _appSettings.TableStorageContainerName); TableEntityAdapter <Code> entity = new TableEntityAdapter <Code>(item, item.EventName, item.PromoCode); TableOperation insertOperation = TableOperation.InsertOrReplace(entity); await table.ExecuteAsync(insertOperation); }
public static async Task <TableResult> InsertAsync <T>(this CloudTableClient tableClient, string tableName, T item, string partitionKey, string rowKey) { var table = tableClient.GetTableReference(tableName); await table.CreateIfNotExistsAsync(); var tableEntity = new TableEntityAdapter <T>(item, partitionKey, rowKey); var tableOperation = TableOperation.Insert(tableEntity); return(await table.ExecuteAsync(tableOperation)); }
public async Task StoreDevice(Device device) { //get cloudtable var table = await GetCloudTable(_appSettings.TableStorageConnectionString, _appSettings.StoreDeviceContainerName); TableEntityAdapter <Device> entity = new TableEntityAdapter <Device>(device, _appSettings.StoreDevicePartitionKey, device.Id.ToString()); TableOperation insertOperation = TableOperation.Insert(entity); await table.ExecuteAsync(insertOperation); }
public async Task <bool> InsertUserMapping(UserMapping userMapping, string partitionKey) { var table = await GetCloudTable(_appSettings.StorageConnectionString, _appSettings.MappingTableContainerName); TableEntityAdapter <UserMapping> entity = new TableEntityAdapter <UserMapping>(userMapping, partitionKey, Guid.NewGuid().ToString()); TableOperation insertOperation = TableOperation.InsertOrReplace(entity); TableResult result = await table.ExecuteAsync(insertOperation); return(true); }
private async Task AddDefinitionToTableAsync(Guid instanceId, WordInformation word) { word.Serialize(); var tableEntity = new TableEntityAdapter <WordInformation>() { PartitionKey = $"{instanceId}_{word.WordName}", RowKey = Guid.NewGuid().ToString(), OriginalEntity = word, }; await definitionsTable.ExecuteAsync(TableOperation.Insert(tableEntity)); }
public async Task <Message> StoreMessage(Message message) { if (message.Contents == null) { _logger.LogError($"Message contents cannot be null."); return(null); } if (message.Contents.Length > MessageEntity.MaxMessageSize) { _logger.LogError($"Message contents are too large. It was {message.Contents.Length}, but the max size is {MessageEntity.MaxMessageSize}"); return(null); } var groupTable = _tableClient.GetTableReference(message.GroupId.ToTableString()); if (!await groupTable.ExistsAsync()) { _logger.LogError($"Could not find any group with ID {message.GroupId}."); return(null); } // Make sure the user belongs to the group TableOperation getUserOp = TableOperation.Retrieve <TableEntityAdapter <UserEntity> >(PartitionNames.User, message.SenderId.ToIdString()); TableResult getUserResult = await groupTable.ExecuteAsync(getUserOp); if (!(getUserResult.Result is TableEntityAdapter <UserEntity> user)) { _logger.LogError($"User ID {message.SenderId} does not belong to group ID {message.GroupId}."); return(null); } Guid messageId = Guid.NewGuid(); message.Timestamp = DateTime.UtcNow; message.SenderName = user.OriginalEntity.Name; var messageEntity = new TableEntityAdapter <MessageEntity>(new MessageEntity { SenderId = message.SenderId, Contents = message.Contents, SentTimestamp = message.Timestamp, SenderName = message.SenderName, }, PartitionNames.Message, messageId.ToIdString()); TableOperation insertOp = TableOperation.Insert(messageEntity); TableResult insertResult = await groupTable.ExecuteAsync(insertOp); if (insertResult.HttpStatusCode != StatusCodes.Status204NoContent) { _logger.LogError($"Failed to add message from sender {message.SenderId} to group {message.GroupId}. Status code: {insertResult.HttpStatusCode}"); return(null); } return(message); }
public async Task <ServiceResult> AddUserToGroup(User user, Guid groupId) { var groupTable = _tableClient.GetTableReference(groupId.ToTableString()); if (!await groupTable.ExistsAsync()) { _logger.LogError($"Could not find any group with ID {groupId}."); return(ServiceResult.NotFound); } TableOperation getExistingUser = TableOperation.Retrieve <TableEntityAdapter <UserEntity> >(PartitionNames.User, user.Id.ToIdString()); TableResult existsResult = await groupTable.ExecuteAsync(getExistingUser); if (existsResult.Result is TableEntityAdapter <UserEntity> ) { // User already exists. We're done! return(ServiceResult.Success); } // Verify group isn't currently full. int groupCount = await GetGroupCount(groupId); if (groupCount >= MaxGroupSize) { _logger.LogInformation($"Unable to add user {user.Name}-{user.Id} to group ID {groupId}. Group already has {groupCount} users."); return(ServiceResult.InvalidArguments); } var userEntity = new TableEntityAdapter <UserEntity>( new UserEntity { Name = user.Name, LastSeen = DateTime.UtcNow }, PartitionNames.User, user.Id.ToIdString()); TableOperation addUser = TableOperation.Insert(userEntity); TableResult addResult = await groupTable.ExecuteAsync(addUser); if (addResult.HttpStatusCode != StatusCodes.Status204NoContent) { _logger.LogError($"Unable to add user {user.Name}-{user.Id} to group {groupId}. Result code: {addResult.HttpStatusCode}"); return(ServiceResult.ServerError); } // User added. Do bookkeeping GroupMetadata metadata = await GetGroupMetadata(groupId); await AddOrUpdateToGroupsList(metadata, groupId, groupCount + 1); await AddToUserGroups(user.Id, groupId, DateTime.UtcNow); return(ServiceResult.Success); }
public async Task <IHttpActionResult> SignIn(ODataActionParameters parameters) { if (!ModelState.IsValid) { return(BadRequest()); } string code = (string)parameters["code"]; HttpResponseMessage response = await client.GetAsync($"https://api.weixin.qq.com/sns/jscode2session?appid={ConfigurationManager.AppSettings["wxAppId"]}&secret={ConfigurationManager.AppSettings["wxAppSecret"]}&js_code={code}&grant_type=authorization_code"); if (response.IsSuccessStatusCode) { var stream = await response.Content.ReadAsStreamAsync(); var serializer = new DataContractJsonSerializer(typeof(SignInResult)); var result = (SignInResult)serializer.ReadObject(stream); if (result.Success) { TableOperation retrieveOperation = TableOperation.Retrieve <TableEntityAdapter <User> >("User", result.OpenId); TableResult retrievedResult = UserTable.Execute(retrieveOperation); TableEntityAdapter <User> userEntity = (TableEntityAdapter <User>)retrievedResult.Result; if (userEntity != null) { userEntity.OriginalEntity.SignInHash = result.SessionKey.GetHashCode(); TableOperation updateOperation = TableOperation.Replace(userEntity); UserTable.Execute(updateOperation); } else { User user = new User { Id = result.OpenId, SignInHash = result.SessionKey.GetHashCode() }; userEntity = new TableEntityAdapter <User>(user, "User", user.Id); TableOperation insertOperation = TableOperation.Insert(userEntity); UserTable.Execute(insertOperation); } return(Json(userEntity.OriginalEntity)); } else { return(BadRequest(result.ErrorMsg)); } } return(BadRequest()); }
private async Task AddWordToReferenceTableAsync(Guid instanceId, string wordName, IEnumerable <WordInformation> wordInfo) { var wordRef = new WordReference(wordName, wordInfo); wordRef.Serialize(); var tableEntity = new TableEntityAdapter <WordReference>() { PartitionKey = instanceId.ToString(), RowKey = wordName, OriginalEntity = wordRef, }; await this.wordReferencesTable.ExecuteAsync(TableOperation.Insert(tableEntity)); }
public async Task StoreLink(Link item) { var table = await GetCloudTable(_appSecretSettings.TableStorageConnectionString, _appSecretSettings.TableStorageContainerName); // Create the batch operation. TableBatchOperation batchOperation = new TableBatchOperation(); // Create a TableEntityAdapter based on the item TableEntityAdapter <Link> entity = new TableEntityAdapter <Link>(item, _appSecretSettings.TableStoragePartitionKey, GetRowKey(item.Label)); batchOperation.InsertOrReplace(entity); // Execute the batch operation. await table.ExecuteBatchAsync(batchOperation); }
public async Task <Device> ReplaceDevice(Device device) { // Get cloudtable var table = await GetCloudTable(_appSettings.TableStorageConnectionString, _appSettings.StoreDeviceContainerName); // Create the entity based on passed in device TableEntityAdapter <Device> entity = new TableEntityAdapter <Device>(device, _appSettings.StoreDevicePartitionKey, device.Id.ToString()); // Create the InsertOrReplace operation TableOperation updateOperation = TableOperation.InsertOrMerge(entity); // Execute the operation. await table.ExecuteAsync(updateOperation); return(device); }
public async Task <IEnumerable <WordInformation> > GetAndSaveWordInformation(Guid instanceId, string word) { var wordInfo = await oedClient.GetInformation(word); foreach (var info in wordInfo) { var tableEntity = new TableEntityAdapter <WordInformation>() { PartitionKey = instanceId.ToString(), RowKey = word, OriginalEntity = info, }; await mainTable.ExecuteAsync(TableOperation.Insert(tableEntity)); } return(wordInfo); }
/// <summary> /// Stuff the result in table storage /// </summary> /// <param name="receipt"></param> /// <returns></returns> private async Task SaveReceiptResult(Receipt receipt) { if (receipt != null) { receipt.Url = null; // remove as this has the SAS token which will expire var entity = new TableEntityAdapter <Receipt>(receipt, receipt.RequestReceived.ToString("yyyyMMdd"), receipt.Id); var insert = Microsoft.Azure.Cosmos.Table.TableOperation.InsertOrMerge(entity); try { _logger.LogInformation($"Saving receipt to table storage: Id: {receipt.Id} Total: {receipt.Total}"); var res = await _receiptTable.ExecuteAsync(insert); } catch (Exception exp) { _logger.LogError($"Error saving to table storage: {exp.Message}"); } } }
public async Task StoreCodes(List <Code> items) { var table = await GetCloudTable(_appSecretSettings.TableStorageConnectionString, _appSettings.TableStorageContainerName); // Need to split list into block of 100 as 100 is the maximum amount of item permitted in a batch operation https://docs.microsoft.com/en-us/azure/cosmos-db/table-storage-how-to-use-dotnet#insert-a-batch-of-entities var listOfListOfItems = items.ChunkBy(100); foreach (var listOfItems in listOfListOfItems) { // Create the batch operation. TableBatchOperation batchOperation = new TableBatchOperation(); // Add each item to the batch foreach (var item in listOfItems) { var rowKey = item.PromoCode; TableEntityAdapter <Code> entity = new TableEntityAdapter <Code>(item, item.EventName, item.PromoCode); batchOperation.InsertOrReplace(entity); } // Execute the batch operation. await table.ExecuteBatchAsync(batchOperation); } }
private static T GetMessageOf <T>(this TableEntityAdapter <Message> message) where T : IMessage { if (message == null) { return(default);
public async void Should_Upload_Completed_With_Manifest_Last() { var request = TestFactory.CreateHttpRequestWithDataStream($"Data/Sample 2.pdf"); var uploadDir = _app.Repository.GetBlobDirectory(BlobNames.UploadDirectory); var uploadTmpTable = _app.Repository.GetTable(TableNames.CommUpload); var queue = _app.Repository.GetQueue(QueueNames.CommProcess); // call step1 upload start var response = (ObjectResult)await UploadFunctions.Start(request, $"{DateTime.Now:u} Sample 2.pdf", uploadDir, uploadTmpTable, new IdGenerator(), _app.App, _logger); var upload = response.Value.IsOrMap <UploadSession>(); Assert.Equal(StatusCodes.Status200OK, response.StatusCode); Assert.Null(upload.ManifestFile); Assert.NotNull(upload.UploadStart); Assert.Null(upload.UploadEnd); Assert.Contains("Sample 2.pdf", upload.LastUploadedFile); _output.WriteLine(upload.ToJson(Formatting.Indented)); // call step2 upload continue var sessionId = upload.SessionId; var sessionBlobDirectory = _app.Repository.GetBlobDirectory(BlobNames.UploadDirectory + $"/{sessionId}"); var tmpEntity = new TableEntityAdapter <UploadSession>(upload, CommUploadPartitionKeys.Temp, sessionId); request = TestFactory.CreateHttpRequestWithDataStream("Data/Sample 1.pdf"); response = (ObjectResult)await UploadFunctions.Continue(request, sessionId, $"{DateTime.Now:u} Sample 1.pdf", sessionBlobDirectory, tmpEntity, uploadTmpTable, _logger); upload = response.Value.IsOrMap <UploadSession>(); Assert.Equal(StatusCodes.Status200OK, response.StatusCode); Assert.Null(upload.ManifestFile); Assert.NotNull(upload.UploadStart); Assert.Null(upload.UploadEnd); Assert.Contains("Sample 1.pdf", upload.LastUploadedFile); _output.WriteLine(upload.ToJson(Formatting.Indented)); // call step3 upload end tmpEntity = new TableEntityAdapter <UploadSession>(upload, CommUploadPartitionKeys.Temp, sessionId); request = TestFactory.CreateHttpRequestWithDataStream($"Data/{CommunicationManifest.FileName}"); response = (ObjectResult)await UploadFunctions.End(request, sessionId, CommunicationManifest.FileName, sessionBlobDirectory, tmpEntity, uploadTmpTable, queue, _app.App, _logger); upload = response.Value.IsOrMap <UploadSession>(); Assert.Equal(StatusCodes.Status200OK, response.StatusCode); Assert.NotNull(upload.ManifestFile); Assert.NotNull(upload.UploadStart); Assert.NotNull(upload.UploadEnd); Assert.Contains(CommunicationManifest.FileName, upload.LastUploadedFile); _output.WriteLine(upload.ToJson(Formatting.Indented)); }
public static async Task <IActionResult> End( [HttpTrigger(AuthorizationLevel.Function, "post", Route = ServiceNames.UploadEnd + "/{session}/{filename?}")] HttpRequest req, string session, string filename, [Blob(BlobNames.UploadDirectory + "/{session}")] CloudBlobDirectory uploadDir, [Table(TableNames.CommUpload, CommUploadPartitionKeys.Temp, "{session}")] TableEntityAdapter <UploadSession> upload, [Table(TableNames.CommUpload)] CloudTable uploadTable, [Queue(QueueNames.CommProcess)] CloudQueue processQueue, [Inject] App app, ILogger log) { try { if (session.IsNullOrEmpty()) { throw new ArgumentException("The Session Id is required.", nameof(session)); } // save the file var uploadTo = await req.Body.UploadTo(uploadDir, filename); #region unexpected behaviour notes /* * update the OriginalEntity.Property value has cause some funny error without cloning the object * System.Private.CoreLib: Exception while executing function: TransferEnd. * Microsoft.Azure.WebJobs.Host: Error while handling parameter upload after function returned:. * Microsoft.WindowsAzure.Storage: Not Found. * * upload.OriginalEntity.UploadEnd = app.DateTimeNow; */ #endregion unexpected behaviour notes UploadSession UpdateOriginalEntity(UploadSession uploadSession) { uploadSession.UploadEnd = app.DateTimeNow; uploadSession.ManifestFile = new[] { upload.OriginalEntity.ManifestFile, filename }.IsIfManifest(); uploadSession.LastUploadedFile = new[] { filename, uploadSession.LastUploadedFile }.FirstIsNotEmpty(); return(uploadSession); } // close the upload session upload = await upload.MoveTo(uploadTable , uploadSession => CommUploadPartitionKeys.Completed , updateOriginalEntity : UpdateOriginalEntity ); // raise the UploadCompleted event await new UploadCompleted { SessionId = session }.AddMessageToAsync(processQueue); return(new OkObjectResult(upload.OriginalEntity)); } catch (Exception ex) { log.LogError(ex.StackTrace); return(new BadRequestObjectResult(new UploadSession { Errors = ex.Message })); } }