public SingleResource CreateResourceRepresentation(object objectGraph, IResourceMapping resourceMapping, Context context) { var urlBuilder = new UrlBuilder { RoutePrefix = context.RoutePrefix }; var result = new SingleResource(); result.Id = resourceMapping.IdGetter(objectGraph).ToString(); result.Type = resourceMapping.ResourceType; result.Attributes = resourceMapping.PropertyGetters.ToDictionary(kvp => kvp.Key, kvp => kvp.Value(objectGraph)); if (resourceMapping.UrlTemplate != null) { result.Links = CreateLinks(resourceMapping, urlBuilder, result); } if (resourceMapping.Relationships.Any()) { result.Relationships = CreateRelationships(objectGraph, result.Id, resourceMapping, context); } return(result); }
public ILink RelationshipSelfLink(Context context, string resourceId, IResourceMapping resourceMapping, IRelationshipMapping linkMapping) { var selfLink = FindResourceSelfLink(context, resourceId, resourceMapping).Href; var completeLink = $"{selfLink}/relationships/{linkMapping.RelationshipName}"; return(new SimpleLink(new Uri(completeLink))); }
public ILink RelationshipRelatedLink(Context context, string resourceId, IResourceMapping resourceMapping, IRelationshipMapping linkMapping) { var selfLink = FindResourceSelfLink(context, resourceId, resourceMapping).Href; var completeLink = $"{selfLink}/{linkMapping.RelationshipName}"; return new SimpleLink(new Uri(completeLink)); }
public Delta(IConfiguration configuration) { _mapping = configuration.GetMapping(typeof(T)); ObjectPropertyValues = new Dictionary <string, object>(StringComparer.OrdinalIgnoreCase); CollectionDeltas = new Dictionary <string, ICollectionDelta>(); TopLevelMetaData = null; ObjectMetaData = null; }
private static Dictionary <string, ILink> CreateLinks(IResourceMapping resourceMapping, Context context, SingleResource result) { return(new Dictionary <string, ILink>() { { SelfLinkKey, new SimpleLink { Href = context.GetFullyQualifiedUrl(resourceMapping.UrlTemplate.Replace(IdPlaceholder, result.Id)) } } }); }
public List<SingleResource> CreateIncludedRepresentations(List<object> primaryResourceList, IResourceMapping resourceMapping, Context context) { var includedList = new List<SingleResource>(); var alreadyVisitedObjects = new HashSet<object>(primaryResourceList); foreach (var resource in primaryResourceList) AppendIncludedRepresentationRecursive(resource, resourceMapping, includedList, alreadyVisitedObjects, context); return includedList; }
public ISimpleLink FindResourceSelfLink(Context context, string resourceId, IResourceMapping resourceMapping) { var actions = descriptionProvider.From(resourceMapping.Controller); var action = actions.Single(a => a.HttpMethod.Method == "GET" && a.ParameterDescriptions.Count(p => p.Name == "id") == 1); var formattedUri = action.RelativePath.Replace("{id}", resourceId); return(new SimpleLink(new Uri(context.BaseUri, formattedUri))); }
public ILink FindResourceSelfLink(Context context, string resourceId, IResourceMapping resourceMapping) { var actions = descriptionProvider.From(resourceMapping.Controller).Items; var action = actions.Single(a => a.HttpMethod == "GET" && a.ParameterDescriptions.Count(p => p.Name == "id") == 1); var values = new Dictionary<string, object>(); values.Add("id", resourceId); return ToUrl(context, action, values); }
public ILink FindResourceSelfLink(Context context, string resourceId, IResourceMapping resourceMapping) { var actions = descriptionProvider.From(resourceMapping.Controller).Items; var action = actions.Single(a => a.HttpMethod == "GET" && a.ParameterDescriptions.Count(p => p.Name == "id") == 1); var values = new Dictionary <string, object>(); values.Add("id", resourceId); return(ToUrl(context, action, values)); }
private List <SingleResource> AppendIncludedRepresentationRecursive( object resource, IResourceMapping resourceMapping, HashSet <SingleResourceIdentifier> alreadyVisitedObjects, Context context, string parentRelationshipPath = "") { var includedResources = new List <SingleResource>(); foreach (var relationship in resourceMapping.Relationships) { if (relationship.InclusionRule == ResourceInclusionRules.ForceOmit) { continue; } var relatedResources = UnifyObjectsToList(relationship.RelatedResource(resource)); string relationshipPath = BuildRelationshipPath(parentRelationshipPath, relationship); if (!context.IncludedResources.Any(x => x.Contains(relationshipPath))) { continue; } foreach (var relatedResource in relatedResources) { var relatedResourceId = new SingleResourceIdentifier { Id = relationship.ResourceMapping.IdGetter(relatedResource).ToString(), Type = relationship.ResourceMapping.ResourceType, MetaData = GetRelationshipMetadata(relatedResource) }; if (alreadyVisitedObjects.Contains(relatedResourceId)) { continue; } alreadyVisitedObjects.Add(relatedResourceId); includedResources.Add( CreateResourceRepresentation(relatedResource, relationship.ResourceMapping, context)); includedResources.AddRange( AppendIncludedRepresentationRecursive(relatedResource, relationship.ResourceMapping, alreadyVisitedObjects, context, relationshipPath)); } } return(includedResources); }
public static void AppendIncludedRepresentationRecursive(object resource, IResourceMapping resourceMapping, List <SingleResource> includedList, HashSet <object> alreadyVisitedObjects, Context context) { resourceMapping.Relationships .Where(rm => rm.InclusionRule != ResourceInclusionRules.ForceOmit) .SelectMany(rm => UnifyObjectsToList(rm.RelatedResource(resource)), (rm, o) => new { Mapping = rm, RelatedResourceInstance = o, }) .Where(x => !alreadyVisitedObjects.Contains(x.RelatedResourceInstance)) .ToList() .ForEach(x => { alreadyVisitedObjects.Add(x.RelatedResourceInstance); includedList.Add(CreateResourceRepresentation(x.RelatedResourceInstance, x.Mapping.ResourceMapping, context)); AppendIncludedRepresentationRecursive(x.RelatedResourceInstance, x.Mapping.ResourceMapping, includedList, alreadyVisitedObjects, context); }); }
public override void WriteResponseHeaders(OutputFormatterWriteContext context) { base.WriteResponseHeaders(context); this.configuration.OverrideResponseHeaders(new OverrideResponseHeadersContext() { HttpContext = context.HttpContext, Type = context.ObjectType, Value = context.Object }); IResourceMapping mapping = this.configuration.GetMapping(context.ObjectType); if (mapping != null && !string.IsNullOrEmpty(mapping.OutputContentType)) { context.HttpContext.Response.ContentType = mapping.OutputContentType; } }
public void AppendIncludedRepresentationRecursive(object resource, IResourceMapping resourceMapping, List<SingleResource> includedList, HashSet<object> alreadyVisitedObjects, Context context) { resourceMapping.Relationships .Where(rm => rm.InclusionRule != ResourceInclusionRules.ForceOmit) .SelectMany(rm => UnifyObjectsToList(rm.RelatedResource(resource)), (rm, o) => new { Mapping = rm, RelatedResourceInstance = o, }) .Where(x => !alreadyVisitedObjects.Contains(x.RelatedResourceInstance)) .ToList() .ForEach(x => { alreadyVisitedObjects.Add(x.RelatedResourceInstance); includedList.Add(CreateResourceRepresentation(x.RelatedResourceInstance, x.Mapping.ResourceMapping, context, true, resource.GetType())); AppendIncludedRepresentationRecursive(x.RelatedResourceInstance, x.Mapping.ResourceMapping, includedList, alreadyVisitedObjects, context); }); }
private IDictionary <string, object> GenerateAttributes(object instance, IResourceMapping mapping) { var attributeNames = mapping.GetAttributeNames().ToList(); if (!attributeNames.Any()) { return(null); } var attributes = new Dictionary <string, object>(); foreach (var attributeName in attributeNames) { var value = mapping.GetAttributeValue(instance, attributeName); attributes.Add(attributeName, value); } return(attributes); }
private List<SingleResource> AppendIncludedRepresentationRecursive( object resource, IResourceMapping resourceMapping, HashSet<object> alreadyVisitedObjects, Context context, string parentRelationshipPath = "") { var includedResources = new List<SingleResource>(); foreach(var relationship in resourceMapping.Relationships) { if (relationship.InclusionRule == ResourceInclusionRules.ForceOmit) { continue; } var relatedResources = UnifyObjectsToList(relationship.RelatedResource(resource)); string relationshipPath = BuildRelationshipPath(parentRelationshipPath, relationship); if (!context.IncludedResources.Any(x => x.Contains(relationshipPath))) { continue; } foreach (var relatedResource in relatedResources) { if (alreadyVisitedObjects.Contains(relatedResource)) { continue; } alreadyVisitedObjects.Add(relatedResource); includedResources.Add( CreateResourceRepresentation(relatedResource, relationship.ResourceMapping, context)); includedResources.AddRange( AppendIncludedRepresentationRecursive(relatedResource, relationship.ResourceMapping, alreadyVisitedObjects, context, relationshipPath)); } } return includedResources; }
public List<SingleResource> CreateIncludedRepresentations(List<object> primaryResourceList, IResourceMapping resourceMapping, Context context) { var includedList = new List<SingleResource>(); var alreadyVisitedObjects = new HashSet<object>(primaryResourceList); foreach (var resource in primaryResourceList) { try { _parentId = resourceMapping.IdGetter(resource).ToString(); } catch (Exception) { _parentId = string.Empty; } AppendIncludedRepresentationRecursive(resource, resourceMapping, includedList, alreadyVisitedObjects, context); } return includedList; }
public bool ValidateIncludedRelationshipPaths(string[] includedPaths) { foreach (var relationshipPath in includedPaths) { IResourceMapping currentMapping = this; var parts = relationshipPath.Split('.'); foreach (var part in parts) { var relationship = currentMapping.Relationships.SingleOrDefault(x => x.RelationshipName == part); if (relationship == null) { return(false); } currentMapping = relationship.ResourceMapping; } } return(true); }
public SingleResource CreateResourceRepresentation( object objectGraph, IResourceMapping resourceMapping, Context context) { var result = new SingleResource(); result.Id = resourceMapping.IdGetter(objectGraph).ToString(); result.Type = resourceMapping.ResourceType; result.Attributes = resourceMapping.GetAttributes(objectGraph, configuration.GetJsonSerializerSettings()); result.Links = GetObjectLinkData(objectGraph); result.Links.Add("self", linkBuilder.FindResourceSelfLink(context, result.Id, resourceMapping)); result.MetaData = GetObjectMetadata(objectGraph); if (resourceMapping.Relationships.Any()) { result.Relationships = CreateRelationships(objectGraph, result.Id, resourceMapping, context); } return(result); }
public SingleResource CreateResourceRepresentation( object objectGraph, IResourceMapping resourceMapping, Context context) { var result = new SingleResource(); result.Id = resourceMapping.IdGetter(objectGraph).ToString(); result.Type = resourceMapping.ResourceType; result.Attributes = resourceMapping.GetAttributes(objectGraph); result.Links = new Dictionary <string, ILink>() { { "self", linkBuilder.FindResourceSelfLink(context, result.Id, resourceMapping) } }; if (resourceMapping.Relationships.Any()) { result.Relationships = CreateRelationships(objectGraph, result.Id, resourceMapping, context); } return(result); }
public SingleResource CreateResourceRepresentation( object objectGraph, IResourceMapping resourceMapping, Context context) { var result = new SingleResource(); result.Id = resourceMapping.IdGetter(objectGraph).ToString(); result.Type = resourceMapping.ResourceType; result.Attributes = resourceMapping.PropertyGetters.ToDictionary(kvp => kvp.Key, kvp => kvp.Value(objectGraph)); result.Links = new Dictionary<string, ILink>() { { "self", linkBuilder.FindResourceSelfLink(context, result.Id, resourceMapping) } }; if (resourceMapping.Relationships.Any()) { result.Relationships = CreateRelationships(objectGraph, result.Id, resourceMapping, context); } return result; }
public ILink RelationshipSelfLink(Context context, string resourceId, IResourceMapping resourceMapping, IRelationshipMapping linkMapping) { return new SimpleLink(new Uri("http://example.com")); }
public ILink FindResourceSelfLink(Context context, string id, IResourceMapping resourceMapping) { return new SimpleLink(new Uri("http://example.com")); }
public ILink RelationshipSelfLink(Context context, string resourceId, IResourceMapping resourceMapping, IRelationshipMapping linkMapping) { return(new SimpleLink(new Uri("http://example.com"))); }
public ILink FindResourceSelfLink(Context context, string id, IResourceMapping resourceMapping) { return(new SimpleLink(new Uri("http://example.com"))); }
public Changes <TResource> BuildChanges <TResource>(DocumentData data, IResourceMapping mapping) { var changes = new Changes <TResource>(); if (data.Id.HasValue) { changes.AddChange(resource => mapping.SetId(resource, data.Id.Value)); } if (data.Attributes != null) { foreach (var attribute in data.Attributes) { var attributeType = mapping.GetAttributeType(attribute.Key); if (attributeType == null) { continue; } var value = attribute.Value.ParseAs(attributeType, _jsonSerializer); changes.AddChange(resource => mapping.SetAttributeValue(resource, attribute.Key, value)); } } if (data.Relationships != null) { foreach (var relation in data.Relationships) { var relationResourceType = mapping.GetResourceTypeOfRelation(relation.Key); if (relationResourceType == null) { throw new JsonApiException(CausedBy.Client, $"Unknown relation {relation.Key}"); } var relationResourceTypeName = GetResourceTypeName(relationResourceType); if (mapping.IsHasManyRelation(relation.Key)) { var relationData = relation.Value.Data.ParseAs <IEnumerable <RelationData> >(_jsonSerializer); if (relationData != null) { if (relationData.Any(x => !x.Type.Equals(relationResourceTypeName))) { throw new JsonApiFormatException(CausedBy.Client, $"Not all relations specified for {relation.Key} are of the type {relationResourceTypeName}"); } var relationIds = relationData.Select(x => x.Id); changes.AddChange(resource => mapping.SetRelationValue(resource, relation.Key, relationIds)); } } else { var relationData = relation.Value.Data.ParseAs <RelationData>(_jsonSerializer); if (relationData != null) { if (!relationData.Type.Equals(relationResourceTypeName)) { throw new JsonApiFormatException(CausedBy.Client, $"Relation type specified for {relation.Key} must be {relationResourceTypeName} instead of {relationData.Type}"); } var relationId = relationData.Id; changes.AddChange(resource => mapping.SetRelationValue(resource, relation.Key, relationId)); } } } } return(changes); }
public Dictionary<string, IRelationship> CreateRelationships(object objectGraph, string parentId, IResourceMapping resourceMapping, Context context) { var relationships = new Dictionary<string, IRelationship>(); foreach (var linkMapping in resourceMapping.Relationships) { var relationshipName = linkMapping.RelationshipName; var rel = new Relationship(); var relLinks = new RelationshipLinks(); relLinks.Self = linkBuilder.RelationshipSelfLink(context, parentId, resourceMapping, linkMapping); relLinks.Related = linkBuilder.RelationshipRelatedLink(context, parentId, resourceMapping, linkMapping); if (!linkMapping.IsCollection) { string relatedId = null; object relatedInstance = null; if (linkMapping.RelatedResource != null) { relatedInstance = linkMapping.RelatedResource(objectGraph); if (relatedInstance != null) relatedId = linkMapping.ResourceMapping.IdGetter(relatedInstance).ToString(); } if (linkMapping.RelatedResourceId != null && relatedId == null) { var id = linkMapping.RelatedResourceId(objectGraph); if (id != null) relatedId = id.ToString(); } if (linkMapping.InclusionRule != ResourceInclusionRules.ForceOmit) { // Generating resource linkage for to-one relationships if (relatedInstance != null) rel.Data = new SingleResourceIdentifier { Id = relatedId, Type = configuration.GetMapping(relatedInstance.GetType()).ResourceType // This allows polymorphic (subtyped) resources to be fully represented }; else if (relatedId == null || linkMapping.InclusionRule == ResourceInclusionRules.ForceInclude) rel.Data = new NullResourceIdentifier(); // two-state null case, see NullResourceIdentifier summary } } else { IEnumerable relatedInstance = null; if (linkMapping.RelatedResource != null) relatedInstance = (IEnumerable)linkMapping.RelatedResource(objectGraph); // Generating resource linkage for to-many relationships if (linkMapping.InclusionRule == ResourceInclusionRules.ForceInclude && relatedInstance == null) rel.Data = new MultipleResourceIdentifiers(); if (linkMapping.InclusionRule != ResourceInclusionRules.ForceOmit && relatedInstance != null) { var idGetter = linkMapping.ResourceMapping.IdGetter; var identifiers = relatedInstance .Cast<object>() .Select(o => new SingleResourceIdentifier { Id = idGetter(o).ToString(), Type = configuration.GetMapping(o.GetType()).ResourceType // This allows polymorphic (subtyped) resources to be fully represented }); rel.Data = new MultipleResourceIdentifiers(identifiers); } // If data is present, count meta attribute is added for convenience if (rel.Data != null) rel.Meta = new Dictionary<string, string> { { MetaCountAttribute, ((MultipleResourceIdentifiers)rel.Data).Count.ToString() } }; } if (relLinks.Self != null || relLinks.Related != null) rel.Links = relLinks; if (rel.Data != null || rel.Links != null) relationships.Add(relationshipName, rel); } return relationships.Any() ? relationships : null; }
public List <SingleResource> CreateIncludedRepresentations(List <object> primaryResourceList, IResourceMapping resourceMapping, Context context) { var includedList = new List <SingleResource>(); var primaryResourceIdentifiers = primaryResourceList.Select(x => { var id = new SingleResourceIdentifier { Id = resourceMapping.IdGetter(x).ToString(), Type = resourceMapping.ResourceType, MetaData = GetRelationshipMetadata(x) }; return(id); }); var alreadyVisitedObjects = new HashSet <SingleResourceIdentifier>(primaryResourceIdentifiers, new SingleResourceIdentifierComparer()); foreach (var resource in primaryResourceList) { includedList.AddRange( AppendIncludedRepresentationRecursive( resource, resourceMapping, alreadyVisitedObjects, context)); } if (includedList.Any()) { return(includedList); } return(null); }
public static List <SingleResource> CreateIncludedRepresentations(List <object> primaryResourceList, IResourceMapping resourceMapping, Context context) { var includedList = new List <SingleResource>(); var alreadyVisitedObjects = new HashSet <object>(primaryResourceList); foreach (var resource in primaryResourceList) { AppendIncludedRepresentationRecursive(resource, resourceMapping, includedList, alreadyVisitedObjects, context); } return(includedList); }
public SingleResource CreateResourceRepresentation(object objectGraph, IResourceMapping resourceMapping, Context context, bool isIncludedResource = false, Type ownerType = null) { var urlBuilder = new UrlBuilder { RoutePrefix = context.RoutePrefix }; var result = new SingleResource(); result.Id = resourceMapping.IdGetter(objectGraph).ToString(); result.Type = resourceMapping.ResourceType; result.Attributes = resourceMapping.PropertyGetters.ToDictionary(kvp => kvp.Key, kvp => kvp.Value(objectGraph)); if (resourceMapping.UrlTemplate != null) { result.Links = CreateLinks(resourceMapping, urlBuilder, result, _parentId); } if (resourceMapping.Relationships.Any()) result.Relationships = CreateRelationships(objectGraph, result.Id, resourceMapping, context, result.Type); if (resourceMapping.PipelineModule != null) { resourceMapping.PipelineModule.Run(resourceMapping.ResourceRepresentationType, result, isIncludedResource, resourceMapping.RequestedFields); } result.OwnerType = ownerType; return result; }
private IDictionary <string, Relationship> GenerateRelationships(object instance, IResourceMapping mapping) { var relationNames = mapping.GetRelationNames().ToList(); if (!relationNames.Any()) { return(null); } var relationships = new Dictionary <string, Relationship>(); foreach (var relationName in relationNames) { var relationTypeName = _configuration.ResourceConfigurations[mapping.GetResourceTypeOfRelation(relationName)]?.TypeName; if (relationTypeName == null) { throw new JsonApiException(CausedBy.Server, $"Resource type for relation {relationName} is not configured"); } var value = mapping.GetRelationValue(instance, relationName); if (value == null) { return(null); } if (value is Guid) { relationships.Add(relationName, new Relationship(relationTypeName, (Guid)value)); } else if (value is IEnumerable <Guid> ) { relationships.Add(relationName, new Relationship(relationTypeName, (IEnumerable <Guid>)value)); } } return(relationships); }
public void AddMapping(IResourceMapping resourceMapping) { resourcesMappingsByResourceType[resourceMapping.ResourceType] = resourceMapping; resourcesMappingsByType[resourceMapping.ResourceRepresentationType] = resourceMapping; }
public static Dictionary <string, IRelationship> CreateRelationships(object objectGraph, string parentId, IResourceMapping resourceMapping, Context context) { var relationships = new Dictionary <string, IRelationship>(); foreach (var linkMapping in resourceMapping.Relationships) { var relationshipName = linkMapping.RelationshipName; var rel = new Relationship(); var relLinks = new RelationshipLinks(); // Generating "self" link if (linkMapping.SelfUrlTemplate != null) { relLinks.Self = GetUrlFromTemplate(context, linkMapping.SelfUrlTemplate, parentId); } if (!linkMapping.IsCollection) { string relatedId = null; object relatedInstance = null; if (linkMapping.RelatedResource != null) { relatedInstance = linkMapping.RelatedResource(objectGraph); if (relatedInstance != null) { relatedId = linkMapping.ResourceMapping.IdGetter(relatedInstance).ToString(); } } if (linkMapping.RelatedResourceId != null && relatedId == null) { var id = linkMapping.RelatedResourceId(objectGraph); if (id != null) { relatedId = id.ToString(); } } // Generating "related" link for to-one relationships if (linkMapping.RelatedUrlTemplate != null && relatedId != null) { relLinks.Related = GetUrlFromTemplate(context, linkMapping.RelatedUrlTemplate, parentId, relatedId.ToString()); } if (linkMapping.InclusionRule != ResourceInclusionRules.ForceOmit) { // Generating resource linkage for to-one relationships if (relatedInstance != null) { rel.Data = new SingleResourceIdentifier { Id = relatedId, Type = context.Configuration.GetMapping(relatedInstance.GetType()).ResourceType // This allows polymorphic (subtyped) resources to be fully represented } } ; else if (relatedId == null || linkMapping.InclusionRule == ResourceInclusionRules.ForceInclude) { rel.Data = new NullResourceIdentifier(); // two-state null case, see NullResourceIdentifier summary } } } else { // Generating "related" link for to-many relationships if (linkMapping.RelatedUrlTemplate != null) { relLinks.Related = GetUrlFromTemplate(context, linkMapping.RelatedUrlTemplate, parentId); } IEnumerable relatedInstance = null; if (linkMapping.RelatedResource != null) { relatedInstance = (IEnumerable)linkMapping.RelatedResource(objectGraph); } // Generating resource linkage for to-many relationships if (linkMapping.InclusionRule == ResourceInclusionRules.ForceInclude && relatedInstance == null) { rel.Data = new MultipleResourceIdentifiers(); } if (linkMapping.InclusionRule != ResourceInclusionRules.ForceOmit && relatedInstance != null) { var idGetter = linkMapping.ResourceMapping.IdGetter; var identifiers = relatedInstance .Cast <object>() .Select(o => new SingleResourceIdentifier { Id = idGetter(o).ToString(), Type = context.Configuration.GetMapping(o.GetType()).ResourceType // This allows polymorphic (subtyped) resources to be fully represented }); rel.Data = new MultipleResourceIdentifiers(identifiers); } // If data is present, count meta attribute is added for convenience if (rel.Data != null) { rel.Meta = new Dictionary <string, string> { { MetaCountAttribute, ((MultipleResourceIdentifiers)rel.Data).Count.ToString() } } } ; } if (relLinks.Self != null || relLinks.Related != null) { rel.Links = relLinks; } if (rel.Data != null || rel.Links != null) { relationships.Add(relationshipName, rel); } } return(relationships.Any() ? relationships : null); }
private static Dictionary<string, ILink> CreateLinks(IResourceMapping resourceMapping, UrlBuilder urlBuilder, SingleResource result, string parentId = null) { return new Dictionary<string, ILink>() { { SelfLinkKey, new SimpleLink { Href = urlBuilder.GetFullyQualifiedUrl(resourceMapping.UrlTemplate.Replace(TypePlaceholder, result.Type).Replace(IdPlaceholder, result.Id).Replace(ParentIdPlaceholder, parentId)) } } }; }
public SingleResource CreateResourceRepresentation(object objectGraph, IResourceMapping resourceMapping, Context context) { var urlBuilder = new UrlBuilder { RoutePrefix = context.RoutePrefix }; var result = new SingleResource(); result.Id = resourceMapping.IdGetter(objectGraph).ToString(); result.Type = resourceMapping.ResourceType; result.Attributes = resourceMapping.PropertyGetters.ToDictionary(kvp => kvp.Key, kvp => kvp.Value(objectGraph)); if (resourceMapping.UrlTemplate != null) result.Links = CreateLinks(resourceMapping, urlBuilder, result); if (resourceMapping.Relationships.Any()) result.Relationships = CreateRelationships(objectGraph, result.Id, resourceMapping, context); return result; }