/// <summary> /// Handles a POST request to create an entity. /// </summary> /// <param name="edmEntityObject">The entity object to create.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The task object that contains the creation result.</returns> public async Task <IActionResult> Post(EdmEntityObject edmEntityObject, CancellationToken cancellationToken) { if (edmEntityObject == null) { throw new ArgumentNullException(nameof(edmEntityObject)); } EnsureInitialized(); CheckModelState(); var path = GetPath(); if (!(path.NavigationSource is IEdmEntitySet entitySet)) { throw new NotImplementedException(Resources.InsertOnlySupportedOnEntitySet); } // In case of type inheritance, the actual type will be different from entity type var expectedEntityType = path.EdmType; var actualEntityType = path.EdmType as IEdmStructuredType; if (edmEntityObject.ActualEdmType != null) { expectedEntityType = edmEntityObject.ExpectedEdmType; actualEntityType = edmEntityObject.ActualEdmType; } var model = api.GetModel(); var postItem = new DataModificationItem( entitySet.Name, expectedEntityType.GetClrType(model), actualEntityType.GetClrType(model), RestierEntitySetOperation.Insert, null, null, edmEntityObject.CreatePropertyDictionary(actualEntityType, api, true)); var changeSetProperty = HttpContext.GetChangeSet(); if (changeSetProperty == null) { var changeSet = new ChangeSet(); changeSet.Entries.Add(postItem); var result = await api.SubmitAsync(changeSet, cancellationToken).ConfigureAwait(false); } else { changeSetProperty.ChangeSet.Entries.Add(postItem); await changeSetProperty.OnChangeSetCompleted().ConfigureAwait(false); } return(CreateCreatedODataResult(postItem.Resource)); }
/// <summary> /// Gets all the attributes for all properties on an Edm type. /// </summary> /// <param name="edmType">The Edm type.</param> /// <param name="api">The api.</param> /// <returns>A dictionary of property attributes.</returns> public static IDictionary <string, PropertyAttributes> RetrievePropertiesAttributes( IEdmStructuredType edmType, ApiBase api) { if (TypePropertiesAttributes.TryGetValue(edmType, out var propertiesAttributes)) { return(propertiesAttributes); } var model = api.GetModel(); foreach (var property in edmType.DeclaredProperties) { var annotations = model.FindVocabularyAnnotations(property); var attributes = PropertyAttributes.None; foreach (var annotation in annotations) { if (!(annotation is EdmVocabularyAnnotation valueAnnotation)) { continue; } if (valueAnnotation.Term.IsSameTerm(CoreVocabularyModel.ImmutableTerm)) { if (valueAnnotation.Value is EdmBooleanConstant value && value.Value) { attributes |= PropertyAttributes.IgnoreForUpdate; } } if (valueAnnotation.Term.IsSameTerm(CoreVocabularyModel.ComputedTerm)) { if (valueAnnotation.Value is EdmBooleanConstant value && value.Value) { attributes |= PropertyAttributes.IgnoreForUpdate; attributes |= PropertyAttributes.IgnoreForCreation; } } // TODO add permission annotation check // CoreVocabularyModel has no permission yet, will add with #480 } // Add property attributes to the dictionary if (attributes != PropertyAttributes.None) { if (propertiesAttributes == null) { propertiesAttributes = new Dictionary <string, PropertyAttributes>(); TypePropertiesAttributes[edmType] = propertiesAttributes; } propertiesAttributes.Add(property.Name, attributes); } } return(propertiesAttributes); }
/// <summary> /// An extension method that generates a Markdown table of all of the possible Restier methods for the given API in the first column, and a boolean /// indicating whether or not the method was found in the second column. /// </summary> /// <param name="api">The <see cref="ApiBase"/> instance to process, typically inheriting from <see cref="EntityFrameworkApi{T}"/>.</param> /// <returns>A string containing the Markdown table of results.</returns> public static string GenerateVisibilityMatrix(this ApiBase api) { if (api == null) { throw new ArgumentNullException(nameof(api)); } var sb = new StringBuilder(); var model = (EdmModel)api.GetModel(); var apiType = api.GetType(); var conventions = model.GenerateConventionDefinitions(); var entitySetMatrix = conventions.OfType <RestierConventionEntitySetDefinition>().ToDictionary(c => c, c => false); var methodMatrix = conventions.OfType <RestierConventionMethodDefinition>().ToDictionary(c => c, c => false); foreach (var definition in entitySetMatrix.ToList()) { var value = false; switch (definition.Key.PipelineState) { case RestierPipelineState.Authorization: value = IsAuthorizerMethodAccessible(apiType, definition.Key.Name); break; default: if (definition.Key.EntitySetOperation == RestierEntitySetOperation.Filter) { value = IsFilterMethodAccessible(apiType, definition.Key.Name); } else { value = IsInterceptorMethodAccessible(apiType, definition.Key.Name); } break; } entitySetMatrix[definition.Key] = value; } foreach (var definition in methodMatrix.ToList()) { var value = false; switch (definition.Key.PipelineState) { case RestierPipelineState.Authorization: value = IsAuthorizerMethodAccessible(apiType, definition.Key.Name); break; default: value = IsInterceptorMethodAccessible(apiType, definition.Key.Name); break; } methodMatrix[definition.Key] = value; } sb.AppendLine(separator); sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "{0,-50} | {1,7}", "Function Name", "Found?")); sb.AppendLine(separator); foreach (var result in entitySetMatrix) { sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "{0,-50} | {1,7}", result.Key.Name, result.Value)); } foreach (var result in methodMatrix) { sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "{0,-50} | {1,7}", result.Key.Name, result.Value)); } sb.AppendLine(separator); return(sb.ToString()); }