/// <summary> /// Gets canonical url of current resource. /// </summary> /// <returns>The canonical url of current resource.</returns> public virtual Uri GetCanonicalUrl() { if (this.canonicalUrl != null) { return(this.canonicalUrl); } // canonicalUrl = HasNonComputedId if (this.resource.HasNonComputedId) { return(this.canonicalUrl = this.resource.NonComputedId); } // Compute canonicalUrl from parent canonicalUrl var parent = this.ParentMetadataBuilder as ODataConventionalResourceMetadataBuilder; if (this.NameAsProperty != null && parent != null && parent.GetCanonicalUrl() != null) { // If parent is collection of complex, the canonical url for this resource should be null. if (parent.IsFromCollection && !(parent is ODataConventionalEntityMetadataBuilder)) { return(this.canonicalUrl = null); } // canonicalUrl = parentCanonicalUrl[/typeCast]/propertyName // Different from edit url and read url, canonical url only needs type cast when the property is defined on derived type. this.canonicalUrl = parent.GetCanonicalUrl(); IODataResourceTypeContext typeContext = parent.ResourceMetadataContext.TypeContext; if (parent.ResourceMetadataContext.ActualResourceTypeName != typeContext.ExpectedResourceTypeName) { // Do not append type cast if we know that the navigation property is in base type, not in derived type. ODataResourceTypeContext.ODataResourceTypeContextWithModel typeContextWithModel = typeContext as ODataResourceTypeContext.ODataResourceTypeContextWithModel; if (typeContextWithModel == null || typeContextWithModel.ExpectedResourceType.FindProperty( this.NameAsProperty) == null) { this.canonicalUrl = this.UriBuilder.AppendTypeSegment(canonicalUrl, parent.ResourceMetadataContext.ActualResourceTypeName); } } this.canonicalUrl = new Uri(string.Concat(this.canonicalUrl, "/", this.NameAsProperty), UriKind.RelativeOrAbsolute); } else { if (this.ODataUri != null && this.ODataUri.Path.Count != 0) { this.canonicalUrl = this.ODataUri.BuildUri(ODataUrlKeyDelimiter.Parentheses); } } return(this.canonicalUrl); }
private bool TryComputeIdFromParent(out Uri uri) { try { ODataConventionalResourceMetadataBuilder parent = this.ParentMetadataBuilder as ODataConventionalResourceMetadataBuilder; if (parent != null && parent != this) { // Get the parent canonical url uri = parent.GetCanonicalUrl(); if (uri != null) { // And append cast (if needed). // A cast segment if the navigation property is defined on a type derived from the type expected. IODataResourceTypeContext typeContext = parent.ResourceMetadataContext.TypeContext; if (parent.ResourceMetadataContext.ActualResourceTypeName != typeContext.ExpectedResourceTypeName) { // Do not append type cast if we know that the navigation property is in base type, not in derived type. ODataResourceTypeContext.ODataResourceTypeContextWithModel typeContextWithModel = typeContext as ODataResourceTypeContext.ODataResourceTypeContextWithModel; if (typeContextWithModel == null || typeContextWithModel.ExpectedResourceType.FindProperty( this.ResourceMetadataContext.TypeContext.NavigationSourceName) == null) { uri = new Uri(UriUtils.EnsureTaillingSlash(uri), parent.ResourceMetadataContext.ActualResourceTypeName); } } return(true); } } } catch (ODataException) { } uri = null; return(false); }