private void ProcessDelete(ApiRequest request)
        {
            // Notify extensions
            Extensions.OnRequestAction(new ApiExtensionResponseData {
                action = "DELETE", context = "BEFORE_DATA_DELETE", data = null
            });

            HttpContext context = request.HttpContext;

            TENTITY objectToDelete = null;

            // Does the request contain the entity PK(s)?
            if (request.QueryParts != null && request.QueryParts.Length > 1)
            {
                var pks = request.QueryParts.Skip(1).Select(pk => HttpUtilities.UrlDecode(pk));
                if (pks != null && pks.Any())
                {
                    objectToDelete = DataObjectFactory.CreateDataObject(pks);
                }
            }

            // Does the request contain json encoded body? (e.g. when called via SDK)
            if (objectToDelete == null)
            {
                JsonSerializerSettings settings = GetJsonSerializerSettings(request);
                string jsonIncomingEntity       = request.JsonEntityData;

                if (jsonIncomingEntity == null)
                {
                    throw new GOServerException("objectToDeleteNotFound");
                }

                if (request.IsDatasetApi)
                {
                    objectToDelete = DataObjectFactory.DeserializeFromContainer(jsonIncomingEntity, settings);
                }
                else
                {
                    objectToDelete = JsonConvert.DeserializeObject <TENTITY>(jsonIncomingEntity, settings);

                    if (objectToDelete != null)
                    {
                        var dataset = ApplicationSettings.Container.Resolve <IObjectsDataSet>();
                        dataset.AddObject(objectToDelete);
                    }
                }

                if (objectToDelete != null)
                {
                    objectToDelete.ObjectsDataSet.EnsureInitialized();
                    objectToDelete.ObjectsDataSet.ReconstructIndexes();
                }
            }

            context.Response.StatusCode = (int)HttpStatusCode.NoContent;

            if (objectToDelete != null)
            {
                // We fetch the instance from storage and then fetch the corresponding entity data provider for the type
                // This is so that for entity hierarchies we call Delete on the actual instance type
                var     instance = DataProvider.Get(objectToDelete, skipSecurity: true);
                dynamic provider = ApplicationSettings.Container.Resolve <IEntityDataProvider>().GetDataProviderForEntity(instance);

                // If this is a 'dry' delete request (means we process the delete logic without actually deleting anything), then the response is the delete stack info
                if (DoDryDelete(request, instance, provider))
                {
                    context.Response.StatusCode = (int)HttpStatusCode.OK;
                }
                else
                {
                    provider.Delete(instance);
                }
            }
        }
        private void ProcessPost(ApiRequest request)
        {
            TENTITY objectToSave = null;

            JsonSerializerSettings settings = GetJsonSerializerSettings(request);

            string jsonIncomingEntity = request.JsonEntityData;

            if (request.IsDatasetApi)
            {
                objectToSave = DataObjectFactory.DeserializeFromContainer(jsonIncomingEntity, settings);

                // Case where trying to save existing object, not dirty => either:
                // (a) only PK is passed to the client, or
                // (b) the main/primary entity is not present in the incoming dataset, in which case the deserialize call above will have created a new instance of the main/primary entity
                // In both cases we should retrieve the main/primary object from database, and combine the datasets
                if (objectToSave.IsNew == false && objectToSave.IsDirty == false)
                {
                    var objectFromDatabase = DataProvider.Get(objectToSave);
                    objectFromDatabase.ObjectsDataSet.AddOrReplaceObject(objectToSave);
                    objectToSave = objectFromDatabase;
                }
            }
            else
            {
                objectToSave = DataObjectFactory.DeserializeObject(jsonIncomingEntity, settings);

                if (objectToSave != null)
                {
                    var dataset = ApplicationSettings.Container.Resolve <IObjectsDataSet>();
                    dataset.AddObject(objectToSave);
                    objectToSave.IsDirty = true;                     // Force Save
                }
            }

            if (objectToSave != null)
            {
                objectToSave.ObjectsDataSet.EnsureInitialized();
                objectToSave.ObjectsDataSet.ReconstructIndexes();
            }

            // Notify extensions
            Extensions.OnRequestAction(new ApiExtensionResponseData {
                action = objectToSave.IsNew ? "CREATE" : "UPDATE", context = "BEFORE SAVE", data = ""
            });

            string response = String.Empty;
            var    result   = DataProvider.Save(objectToSave, null, request.IncludeList);

            if (result == null)
            {
                if (!objectToSave.IsMarkedForDeletion)
                {
                    throw new ResourceNotFoundException();
                }
                else
                {
                    response = null;
                }
            }
            else
            {
                result.ObjectsDataSet.SerializeTechnicalProperties = false;

                if (!request.IsDatasetApi)
                {
                    result.ObjectsDataSet.InitializeRelationsToInclude(typeof(TENTITY), request.Includes);
                }

                object dataToSerialize = request.IsDatasetApi ? DataObjectFactory.CreateDataSetContainer(result) : result;

                response = JsonConvert.SerializeObject(dataToSerialize, settings);
            }

            // Notify extensions
            Extensions.OnRequestAction(new ApiExtensionResponseData {
                action = objectToSave.IsNew ? "CREATE" : "UPDATE", context = "JSON WRITE", data = response
            });

            WriteResponse(request.HttpContext, response);
        }