Esempio n. 1
0
        public bool EntityFunction(int key, [FromODataUri] EdmEntityObject customer)
        {
            Assert.NotNull(customer);
            dynamic result = customer;

            Assert.Equal("NS.Customer", customer.GetEdmType().FullName());

            // entity call
            if (key == 9)
            {
                Assert.Equal(91, result.Id);
                Assert.Equal("John", result.Name);

                dynamic          address    = result.Location;
                EdmComplexObject addressObj = Assert.IsType <EdmComplexObject>(address);
                Assert.Equal("NS.Address", addressObj.GetEdmType().FullName());
                Assert.Equal("NE 24th St.", address.Street);
                Assert.Equal("Redmond", address.City);
            }
            else
            {
                // entity reference call
                Assert.Equal(8, result.Id);
                Assert.Equal("Id", String.Join(",", customer.GetChangedPropertyNames()));

                Assert.Equal("Name,Location", String.Join(",", customer.GetUnchangedPropertyNames()));
            }

            return(true);
        }
Esempio n. 2
0
        public IHttpActionResult PatchCustomerBySSN([FromODataUri] string ssnKey, EdmEntityObject delta)
        {
            IList <string>   changedPropertyNames = delta.GetChangedPropertyNames().ToList();
            IEdmEntityObject originalCustomer     = null;

            foreach (var customer in AlternateKeysDataSource.Customers)
            {
                object value;
                if (customer.TryGetPropertyValue("SSN", out value))
                {
                    string stringKey = (string)value;
                    if (ssnKey == stringKey)
                    {
                        originalCustomer = customer;
                    }
                }
            }

            if (originalCustomer == null)
            {
                return(NotFound());
            }

            object nameValue;

            delta.TryGetPropertyValue("Name", out nameValue);
            //Assert.NotNull(nameValue);
            //string strName = Assert.IsType<string>(nameValue);
            dynamic original = originalCustomer;

            //original.Name = strName;
            original.Name = nameValue;

            return(Ok(originalCustomer));
        }
Esempio n. 3
0
        /// <summary>
        /// Обновление сущности (свойства могут быть заданы частично, т.е. указывать можно значения только измененных свойств).
        /// Если сущности с заданным ключом нет в БД происходит Upsert (в соответствии со стандартом).
        /// </summary>
        /// <param name="key"> Ключ обновляемой сущности. </param>
        /// <param name="edmEntity">Обновляемая сущность. </param>
        /// <returns>Обновлённая сущность.</returns>
        public HttpResponseMessage Patch([FromODataUri] Guid key, [FromBody] EdmEntityObject edmEntity)
        {
            try
            {
                if (key == null)
                {
                    throw new ArgumentNullException("key");
                }

                if (edmEntity == null)
                {
                    edmEntity = ReplaceOdataBindNull();
                }

                IEdmEntityType entityType = (IEdmEntityType)edmEntity.ActualEdmType;

                var dictionary = Request.Properties.ContainsKey(ExtendedODataEntityDeserializer.Dictionary) ?
                                 (Dictionary <string, object>)Request.Properties[ExtendedODataEntityDeserializer.Dictionary] :
                                 new Dictionary <string, object>();

                foreach (var prop in entityType.Properties())
                {
                    if (!dictionary.ContainsKey(prop.Name) && edmEntity.GetChangedPropertyNames().Contains(prop.Name) && prop is EdmNavigationProperty)
                    {
                        return(Request.CreateResponse(System.Net.HttpStatusCode.BadRequest, "Error processing request stream. Deep updates are not supported in PUT or PATCH operations."));
                    }

                    if (dictionary.ContainsKey(prop.Name) && dictionary[prop.Name] == null &&
                        (!prop.Type.IsNullable || prop.Type.IsCollection()))
                    {
                        return(Request.CreateResponse(System.Net.HttpStatusCode.BadRequest, $"The property {prop.Name} can not be null."));
                    }
                }

                DataObject obj = UpdateObject(edmEntity, key);
                ExecuteCallbackAfterUpdate(obj);

                var responseForPreferMinimal = TestPreferMinimal();
                if (responseForPreferMinimal != null)
                {
                    return(responseForPreferMinimal);
                }

                if (!Request.Headers.Contains("Prefer"))
                {
                    return(Request.CreateResponse(System.Net.HttpStatusCode.NoContent));
                }

                edmEntity = GetEdmObject(_model.GetEdmEntityType(type), obj, 1, null, null);
                var result = Request.CreateResponse(System.Net.HttpStatusCode.OK, edmEntity);
                result.Headers.Add("Preference-Applied", "return=representation");
                return(result);
            }
            catch (Exception ex)
            {
                return(InternalServerErrorMessage(ex));
            }
        }
Esempio n. 4
0
            public IHttpActionResult GetCustomer(int key, [FromODataUri] EdmEntityObject customer)
            {
                Assert.NotNull(customer);

                StringBuilder        sb            = new StringBuilder();
                IEnumerable <string> propertyNames = customer.GetChangedPropertyNames();

                foreach (string name in propertyNames)
                {
                    object value;
                    customer.TryGetPropertyValue(name, out value);
                    sb.Append(name + "=").Append(value).Append(",");
                }

                return(Ok("GetCustomer(" + sb.ToString() + ")"));
            }
Esempio n. 5
0
        public ITestActionResult PatchCustomerBySSN([FromODataUri] string ssnKey, [FromBody] EdmEntityObject delta)
        {
            Assert.Equal("SSN-6-T-006", ssnKey);

            IList <string> changedPropertyNames = delta.GetChangedPropertyNames().ToList();

            Assert.Single(changedPropertyNames);
            Assert.Equal("Name", String.Join(",", changedPropertyNames));

            IEdmEntityObject originalCustomer = null;

            foreach (var customer in AlternateKeysDataSource.Customers)
            {
                object value;
                if (customer.TryGetPropertyValue("SSN", out value))
                {
                    string stringKey = (string)value;
                    if (ssnKey == stringKey)
                    {
                        originalCustomer = customer;
                    }
                }
            }

            if (originalCustomer == null)
            {
                return(NotFound());
            }

            object nameValue;

            delta.TryGetPropertyValue("Name", out nameValue);
            Assert.NotNull(nameValue);
            string  strName  = Assert.IsType <string>(nameValue);
            dynamic original = originalCustomer;

            original.Name = strName;

            return(Ok(originalCustomer));
        }
Esempio n. 6
0
        /// <summary>
        /// Построение объекта данных по сущности OData.
        /// </summary>
        /// <param name="edmEntity"> Сущность OData. </param>
        /// <param name="key"> Значение ключевого поля сущности. </param>
        /// <param name="dObjs"> Список объектов для обновления. </param>
        /// <param name="endObject"> Признак, что объект добавляется в конец списка обновления. </param>
        /// <returns> Объект данных. </returns>
        private DataObject GetDataObjectByEdmEntity(EdmEntityObject edmEntity, object key, List <DataObject> dObjs, bool endObject = false)
        {
            if (edmEntity == null)
            {
                return(null);
            }

            IEdmEntityType entityType = (IEdmEntityType)edmEntity.ActualEdmType;
            Type           objType    = _model.GetDataObjectType(_model.GetEdmEntitySet(entityType).Name);

            // Значение свойства.
            object value;

            // Получим значение ключа.
            var keyProperty = entityType.Properties().FirstOrDefault(prop => prop.Name == _model.KeyPropertyName);

            if (key != null)
            {
                value = key;
            }
            else
            {
                edmEntity.TryGetPropertyValue(keyProperty.Name, out value);
            }

            // Загрузим объект из хранилища, если он там есть (используем представление по умолчанию), или создадим, если нет, но только для POST.
            // Тем самым гарантируем загруженность свойств при необходимости обновления и установку нужного статуса.
            DataObject obj = ReturnDataObject(objType, value);

            // Добавляем объект в список для обновления, если там ещё нет объекта с таким ключом.
            var objInList = dObjs.FirstOrDefault(o => o.__PrimaryKey.ToString() == obj.__PrimaryKey.ToString());

            if (objInList == null)
            {
                if (!endObject)
                {
                    // Добавляем объект в начало списка.
                    dObjs.Insert(0, obj);
                }
                else
                {
                    // Добавляем в конец списка.
                    dObjs.Add(obj);
                }
            }

            // Все свойства объекта данных означим из пришедшей сущности, если они были там установлены(изменены).
            foreach (var prop in entityType.Properties())
            {
                string dataObjectPropName = _model.GetDataObjectProperty(entityType.FullTypeName(), prop.Name).Name;
                if (edmEntity.GetChangedPropertyNames().Contains(prop.Name))
                {
                    // Обработка мастеров и детейлов.
                    if (prop is EdmNavigationProperty)
                    {
                        EdmNavigationProperty navProp = (EdmNavigationProperty)prop;

                        edmEntity.TryGetPropertyValue(prop.Name, out value);

                        EdmMultiplicity edmMultiplicity = navProp.TargetMultiplicity();

                        // var aggregator = Information.GetAgregatePropertyName(objType);

                        // Обработка мастеров.
                        if (edmMultiplicity == EdmMultiplicity.One || edmMultiplicity == EdmMultiplicity.ZeroOrOne)
                        {
                            if (value != null && value is EdmEntityObject)
                            {
                                EdmEntityObject edmMaster = (EdmEntityObject)value;
                                DataObject      master    = GetDataObjectByEdmEntity(edmMaster, null, dObjs);

                                Information.SetPropValueByName(obj, dataObjectPropName, master);
                            }
                            else
                            {
                                Information.SetPropValueByName(obj, dataObjectPropName, null);
                            }
                        }

                        // Обработка детейлов.
                        if (edmMultiplicity == EdmMultiplicity.Many)
                        {
                            Type        detType = Information.GetPropertyType(objType, dataObjectPropName);
                            DetailArray detarr  = (DetailArray)Information.GetPropValueByName(obj, dataObjectPropName);

                            if (value != null && value is EdmEntityObjectCollection)
                            {
                                EdmEntityObjectCollection coll = (EdmEntityObjectCollection)value;
                                if (coll != null && coll.Count > 0)
                                {
                                    foreach (var edmEnt in coll)
                                    {
                                        DataObject det = GetDataObjectByEdmEntity(
                                            (EdmEntityObject)edmEnt,
                                            null,
                                            dObjs,
                                            true);

                                        if (det.__PrimaryKey == null)
                                        {
                                            detarr.AddObject(det);
                                        }
                                        else
                                        {
                                            detarr.SetByKey(det.__PrimaryKey, det);
                                        }
                                    }
                                }
                            }
                            else
                            {
                                detarr.Clear();
                            }
                        }
                    }
                    else
                    {
                        // Обработка собственных свойств объекта (неключевых, т.к. ключ устанавливаем при начальной инициализации объекта obj).
                        if (prop.Name != keyProperty.Name)
                        {
                            Type dataObjectPropertyType = Information.GetPropertyType(objType, dataObjectPropName);
                            edmEntity.TryGetPropertyValue(prop.Name, out value);

                            // Если тип свойства относится к одному из зарегистрированных провайдеров файловых свойств,
                            // значит свойство файловое, и его нужно обработать особым образом.
                            if (FileController.HasDataObjectFileProvider(dataObjectPropertyType))
                            {
                                IDataObjectFileProvider dataObjectFileProvider = FileController.GetDataObjectFileProvider(dataObjectPropertyType);

                                // Обработка файловых свойств объектов данных.
                                string serializedFileDescription = value as string;
                                if (serializedFileDescription == null)
                                {
                                    // Файловое свойство было сброшено на клиенте.
                                    // Ассоциированный файл должен быть удален, после успешного сохранения изменений.
                                    // Для этого запоминаем метаданные ассоциированного файла, до того как свойство будет сброшено
                                    // (для получения метаданных свойство будет дочитано в объект данных).
                                    // Файловое свойство типа File хранит данные ассоциированного файла прямо в БД,
                                    // соответственно из файловой системы просто нечего удалять,
                                    // поэтому обходим его стороной, чтобы избежать лишных вычиток файлов из БД.
                                    if (dataObjectPropertyType != typeof(File))
                                    {
                                        _removingFileDescriptions.Add(dataObjectFileProvider.GetFileDescription(obj, dataObjectPropName));
                                    }

                                    // Сбрасываем файловое свойство в изменяемом объекте данных.
                                    Information.SetPropValueByName(obj, dataObjectPropName, null);
                                }
                                else
                                {
                                    // Файловое свойство было изменено, но не сброшено.
                                    // Если в метаданных файла присутствует FileUploadKey значит файл был загружен на сервер,
                                    // но еще не был ассоциирован с объектом данных, и это нужно сделать.
                                    FileDescription fileDescription = FileDescription.FromJson(serializedFileDescription);
                                    if (!(string.IsNullOrEmpty(fileDescription.FileUploadKey) || string.IsNullOrEmpty(fileDescription.FileName)))
                                    {
                                        Information.SetPropValueByName(obj, dataObjectPropName, dataObjectFileProvider.GetFileProperty(fileDescription));

                                        // Файловое свойство типа File хранит данные ассоциированного файла прямо в БД,
                                        // поэтому после успешного сохранения объекта данных, оссоциированный с ним файл должен быть удален из файловой системы.
                                        // Для этого запоминаем описание загруженного файла.
                                        if (dataObjectPropertyType == typeof(File))
                                        {
                                            _removingFileDescriptions.Add(fileDescription);
                                        }
                                    }
                                }
                            }
                            else
                            {
                                // Преобразование типов для примитивных свойств.
                                if (value is DateTimeOffset)
                                {
                                    value = ((DateTimeOffset)value).UtcDateTime;
                                }
                                if (value is EdmEnumObject)
                                {
                                    value = ((EdmEnumObject)value).Value;
                                }

                                Information.SetPropValueByName(obj, dataObjectPropName, value);
                            }
                        }
                    }
                }
            }

            return(obj);
        }