public StarshipOfficersRelatedResourceMaterializer(ResourceTypeRelationship relationship, DbContext dbContext, IQueryableResourceCollectionDocumentBuilder queryableResourceCollectionDocumentBuilder, ISortExpressionExtractor sortExpressionExtractor, IResourceTypeRegistration primaryTypeRegistration) : base(relationship, dbContext, queryableResourceCollectionDocumentBuilder, sortExpressionExtractor, primaryTypeRegistration) { _dbContext = dbContext; }
public StarshipShipCounselorRelatedResourceMaterializer( ISingleResourceDocumentBuilder singleResourceDocumentBuilder, IBaseUrlService baseUrlService, IResourceTypeRegistration primaryTypeRegistration, ResourceTypeRelationship relationship, DbContext dbContext) : base(singleResourceDocumentBuilder, baseUrlService, primaryTypeRegistration, relationship, dbContext) { _dbContext = dbContext; }
/// <summary> /// Builds a new EntityFrameworkToOneRelatedResourceDocumentMaterializer /// </summary> public EntityFrameworkToOneRelatedResourceDocumentMaterializer( ISingleResourceDocumentBuilder singleResourceDocumentBuilder, IBaseUrlService baseUrlService, IResourceTypeRegistration primaryTypeRegistration, ResourceTypeRelationship relationship, DbContext dbContext) : base(singleResourceDocumentBuilder, baseUrlService) { _primaryTypeRegistration = primaryTypeRegistration; _relationship = relationship; _dbContext = dbContext; }
/// <summary> /// Builds a new EntityFrameworkToManyRelatedResourceDocumentMaterializer. /// </summary> public EntityFrameworkToManyRelatedResourceDocumentMaterializer( ResourceTypeRelationship relationship, DbContext dbContext, IQueryableResourceCollectionDocumentBuilder queryableResourceCollectionDocumentBuilder, ISortExpressionExtractor sortExpressionExtractor, IResourceTypeRegistration primaryTypeRegistration) : base(queryableResourceCollectionDocumentBuilder, sortExpressionExtractor) { _relationship = relationship; _dbContext = dbContext; _primaryTypeRegistration = primaryTypeRegistration; }
/// <summary> /// Constructs a URL for the resource(s) on the other side of the given relationship, belonging to the given resource /// </summary> /// <param name="relationshipOwner"></param> /// <param name="resourceTypeRegistry"></param> /// <param name="property"></param> /// <param name="baseUrl"></param> /// <returns></returns> protected virtual string BuildRelatedResourceUrl(object relationshipOwner, IResourceTypeRegistry resourceTypeRegistry, ResourceTypeRelationship property, string baseUrl) { var relationshipOwnerType = relationshipOwner.GetType(); var sanitizedBaseUrl = GetSanitizedBaseUrl(baseUrl); var registration = resourceTypeRegistry.GetRegistrationForType(relationshipOwnerType); var id = registration.GetIdForResource(relationshipOwner); if (property.RelatedResourceLinkTemplate != null) { var replacedString = property.RelatedResourceLinkTemplate.Replace("{1}", id); return(String.Format("{0}/{1}", sanitizedBaseUrl, replacedString)); } return(String.Format("{0}/{1}/{2}/{3}", sanitizedBaseUrl, registration.ResourceTypeName, id, property.JsonKey)); }
/// <summary> /// Generic method for getting the related resources for a to-one relationship /// </summary> protected async Task <ISingleResourceDocument> GetRelatedToOne <TRelated>(string id, ResourceTypeRelationship relationship, HttpRequestMessage request, CancellationToken cancellationToken) { var param = Expression.Parameter(typeof(T)); var accessorExpr = Expression.Property(param, relationship.Property); var lambda = Expression.Lambda <Func <T, TRelated> >(accessorExpr, param); var primaryEntityQuery = FilterById <T>(id, _resourceTypeRegistration); var primaryEntityExists = await primaryEntityQuery.AnyAsync(cancellationToken); if (!primaryEntityExists) { throw JsonApiException.CreateForNotFound(string.Format("No resource of type `{0}` exists with id `{1}`.", _resourceTypeRegistration.ResourceTypeName, id)); } var relatedResource = await primaryEntityQuery.Select(lambda).FirstOrDefaultAsync(cancellationToken); return(_singleResourceDocumentBuilder.BuildDocument(relatedResource, GetBaseUrlFromRequest(request), null, null)); }
private Expression GetPredicateBodyForRelationship(ResourceTypeRelationship resourceTypeProperty, string queryValue, ParameterExpression param) { var relatedType = resourceTypeProperty.RelatedType; PropertyInfo relatedIdProperty; try { var registration = _resourceTypeRegistry.GetRegistrationForType(relatedType); relatedIdProperty = registration.IdProperty; } catch (TypeRegistrationNotFoundException) { throw new HttpResponseException(HttpStatusCode.BadRequest); } var prop = resourceTypeProperty.Property; if (resourceTypeProperty.IsToMany) { var propertyExpr = Expression.Property(param, prop); if (string.IsNullOrWhiteSpace(queryValue)) { var leftExpr = Expression.Equal(propertyExpr, Expression.Constant(null)); var asQueryableCallExpr = Expression.Call( typeof(Queryable), "AsQueryable", new[] { relatedType }, propertyExpr); var anyCallExpr = Expression.Call( typeof(Queryable), "Any", new[] { relatedType }, asQueryableCallExpr); var rightExpr = Expression.Not(anyCallExpr); return(Expression.OrElse(leftExpr, rightExpr)); } else { var leftExpr = Expression.NotEqual(propertyExpr, Expression.Constant(null)); var idValue = queryValue.Trim(); var idExpr = Expression.Constant(idValue); var anyParam = Expression.Parameter(relatedType); var relatedIdPropertyExpr = Expression.Property(anyParam, relatedIdProperty); var relatedIdPropertyEqualsIdExpr = Expression.Equal(relatedIdPropertyExpr, idExpr); var anyPredicateExpr = Expression.Lambda(relatedIdPropertyEqualsIdExpr, anyParam); var asQueryableCallExpr = Expression.Call( typeof(Queryable), "AsQueryable", new[] { relatedType }, propertyExpr); var rightExpr = Expression.Call( typeof(Queryable), "Any", new[] { relatedType }, asQueryableCallExpr, anyPredicateExpr); return(Expression.AndAlso(leftExpr, rightExpr)); } } else { var propertyExpr = Expression.Property(param, prop); if (string.IsNullOrWhiteSpace(queryValue)) { return(Expression.Equal(propertyExpr, Expression.Constant(null))); } var leftExpr = Expression.NotEqual(propertyExpr, Expression.Constant(null)); var idValue = queryValue.Trim(); var idExpr = Expression.Constant(idValue); var relatedIdPropertyExpr = Expression.Property(propertyExpr, relatedIdProperty); var rightExpr = Expression.Equal(relatedIdPropertyExpr, idExpr); return(Expression.AndAlso(leftExpr, rightExpr)); } }
/// <summary> /// Gets a metadata object to serialize alongside the link URL for related resource links. /// </summary> /// <returns></returns> protected virtual IMetadata GetMetadataForRelatedResourceLink <TResource>(TResource relationshipOwner, ResourceTypeRelationship property) { return(null); }
public ILink GetRelatedResourceLink <TResource>(TResource relationshipOwner, IResourceTypeRegistry resourceTypeRegistry, ResourceTypeRelationship property, string baseUrl) { var url = BuildRelatedResourceUrl(relationshipOwner, resourceTypeRegistry, property, baseUrl); var metadata = GetMetadataForRelatedResourceLink(relationshipOwner, property); return(new Link(url, metadata)); }
/// <summary> /// Generic method for getting the related resources for a to-many relationship /// </summary> protected async Task <IResourceCollectionDocument> GetRelatedToMany <TRelated>(string id, ResourceTypeRelationship relationship, HttpRequestMessage request, CancellationToken cancellationToken) { var param = Expression.Parameter(typeof(T)); var accessorExpr = Expression.Property(param, relationship.Property); var lambda = Expression.Lambda <Func <T, IEnumerable <TRelated> > >(accessorExpr, param); var primaryEntityQuery = FilterById <T>(id, _resourceTypeRegistration); // We have to see if the resource even exists, so we can throw a 404 if it doesn't var relatedResource = await primaryEntityQuery.FirstOrDefaultAsync(cancellationToken); if (relatedResource == null) { throw JsonApiException.CreateForNotFound(string.Format("No resource of type `{0}` exists with id `{1}`.", _resourceTypeRegistration.ResourceTypeName, id)); } var relatedResourceQuery = primaryEntityQuery.SelectMany(lambda); var sortExpressions = _sortExpressionExtractor.ExtractSortExpressions(request); return(await _queryableResourceCollectionDocumentBuilder.BuildDocument(relatedResourceQuery, request, sortExpressions, cancellationToken)); }
/// <summary> /// Sets the value of a to-many relationship /// </summary> protected void SetToManyRelationshipValue <TRelated>(object material, IEnumerable <object> relatedObjects, ResourceTypeRelationship relationship) { var currentValue = relationship.Property.GetValue(material); var typedArray = relatedObjects.Select(o => (TRelated)o).ToArray(); if (relationship.Property.PropertyType.IsAssignableFrom(typeof(List <TRelated>))) { if (currentValue == null) { relationship.Property.SetValue(material, typedArray.ToList()); } else { var listCurrentValue = (ICollection <TRelated>)currentValue; var itemsToAdd = typedArray.Except(listCurrentValue); var itemsToRemove = listCurrentValue.Except(typedArray).ToList(); foreach (var related in itemsToAdd) { listCurrentValue.Add(related); } foreach (var related in itemsToRemove) { listCurrentValue.Remove(related); } } } else { relationship.Property.SetValue(material, typedArray); } }