public HttpResponseMessageWrapper <Item> UpdateItem(HttpRequestMessage req, Guid id) { Operation operation = null; HttpStatusCode code = AuthenticateUser(req); if (code != HttpStatusCode.OK) { // user not authenticated return(ReturnResult <Item>(req, operation, code)); } List <Item> clientItems = null; code = ProcessRequestBody <List <Item> >(req, out clientItems, out operation); if (code != HttpStatusCode.OK) // error encountered processing body { return(ReturnResult <Item>(req, operation, code)); } Item originalItem = clientItems[0]; Item newItem = clientItems[1]; // make sure the item ID's match if (originalItem.ID != id || newItem.ID != id) { TraceLog.TraceError("ID in URL does not match entity body"); return(ReturnResult <Item>(req, operation, HttpStatusCode.BadRequest)); } // if parent ID is an empty guid, make it null instead so as to not violate ref integrity rules if (originalItem.ParentID == Guid.Empty) { originalItem.ParentID = null; } if (newItem.ParentID == Guid.Empty) { newItem.ParentID = null; } if (newItem.LastModified.Year == 1970) { // web client sets Date(0) to get server timestamp (ticks since 1970) newItem.LastModified = DateTime.UtcNow; } // get the folder for the item try { Item requestedItem = this.StorageContext.Items.Include("ItemTags").Include("FieldValues").Single <Item>(t => t.ID == id); // if the Folder does not belong to the authenticated user, return 403 Forbidden if (requestedItem.UserID != CurrentUser.ID) { TraceLog.TraceError("Entity does not belong to current user)"); return(ReturnResult <Item>(req, operation, HttpStatusCode.Forbidden)); } // reset the UserID fields to the appropriate user, to ensure update is done in the context of the current user originalItem.UserID = requestedItem.UserID; newItem.UserID = requestedItem.UserID; Folder originalFolder = this.StorageContext.Folders.Single <Folder>(tl => tl.ID == originalItem.FolderID); Folder newFolder = this.StorageContext.Folders.Single <Folder>(tl => tl.ID == newItem.FolderID); if (originalFolder.UserID != CurrentUser.ID || newFolder.UserID != CurrentUser.ID || originalItem.UserID != CurrentUser.ID || newItem.UserID != CurrentUser.ID) { // folder or item does not belong to the authenticated user, return 403 Forbidden TraceLog.TraceError("Folder of Entity does not belong to current user)"); return(ReturnResult <Item>(req, operation, HttpStatusCode.Forbidden)); } try { bool changed = false; if (requestedItem.ItemTags != null && requestedItem.ItemTags.Count > 0) { // delete all the itemtags associated with this item foreach (var tt in requestedItem.ItemTags.ToList()) { this.StorageContext.ItemTags.Remove(tt); } changed = true; } ItemProcessor ip = ItemProcessor.Create(CurrentUser, StorageContext, newItem.ItemTypeID); if (ip != null) { // do itemtype-specific processing ip.ProcessUpdate(originalItem, newItem); } // call update and make sure the changed flag reflects the outcome correctly changed = (Update(requestedItem, originalItem, newItem) == true ? true : changed); if (changed == true) { int rows = this.StorageContext.SaveChanges(); if (rows < 0) { TraceLog.TraceError("Internal Server Error (database operation did not succeed)"); return(ReturnResult <Item>(req, operation, HttpStatusCode.InternalServerError)); } else { if (rows == 0) { TraceLog.TraceInfo("Inconsistency between the results of Update and zero rows affected"); } if (newFolder.Name.StartsWith("$") == false) { WorkflowHost.WorkflowHost.InvokeWorkflowForOperation(this.StorageContext, null, operation); } TraceLog.TraceInfo("Accepted"); return(ReturnResult <Item>(req, operation, requestedItem, HttpStatusCode.Accepted)); } } else { TraceLog.TraceInfo("Accepted (no changes)"); return(ReturnResult <Item>(req, operation, requestedItem, HttpStatusCode.Accepted)); } } catch (Exception ex) { // item not found - return 404 Not Found TraceLog.TraceException("Resource not found (Item)", ex); return(ReturnResult <Item>(req, operation, HttpStatusCode.NotFound)); } } catch (Exception ex) { // folder not found - return 404 Not Found TraceLog.TraceException("Resource not found (Folder)", ex); return(ReturnResult <Item>(req, operation, HttpStatusCode.NotFound)); } }