/// <summary> /// Sets the metadata builder for this operation. /// </summary> /// <param name="builder">The metadata builder used to compute values from model annotations.</param> /// <param name="metadataDocumentUri">The metadata document Uri.</param> internal void SetMetadataBuilder(ODataEntityMetadataBuilder builder, Uri metadataDocumentUri) { Debug.Assert(metadataDocumentUri != null, "metadataDocumentUri != null"); Debug.Assert(metadataDocumentUri.IsAbsoluteUri, "metadataDocumentUri.IsAbsoluteUri"); ODataJsonLightValidationUtils.ValidateOperation(metadataDocumentUri, this); this.metadataBuilder = builder; this.operationFullName = ODataJsonLightUtils.GetFullyQualifiedOperationName(metadataDocumentUri, UriUtils.UriToString(this.Metadata), out this.parameterNames); this.computedTitle = null; this.computedTarget = null; }
internal static IEdmNavigationProperty ValidateNavigationLink( ODataNavigationLink navigationLink, IEdmEntityType declaringEntityType, ODataPayloadKind?expandedPayloadKind, bool bypassValidation = false) { Debug.Assert(navigationLink != null, "navigationLink != null"); Debug.Assert( !expandedPayloadKind.HasValue || expandedPayloadKind.Value == ODataPayloadKind.EntityReferenceLink || expandedPayloadKind.Value == ODataPayloadKind.Entry || expandedPayloadKind.Value == ODataPayloadKind.Feed, "If an expanded payload kind is specified it must be entry, feed or entity reference link."); if (bypassValidation) { return(declaringEntityType == null ? null : declaringEntityType.FindProperty(navigationLink.Name) as IEdmNavigationProperty); } // Navigation link must have a non-empty name if (string.IsNullOrEmpty(navigationLink.Name)) { throw new ODataException(Strings.ValidationUtils_LinkMustSpecifyName); } // If we write an entity reference link, don't validate the multiplicity of the IsCollection // property if it is 'false' (since we allow writing a singleton navigation link for // a collection navigation property in requests) nor the consistency of payload kind and metadata // (which is done separately in ODataWriterCore.CheckForNavigationLinkWithContent). bool isEntityReferenceLinkPayload = expandedPayloadKind == ODataPayloadKind.EntityReferenceLink; // true only if the expandedPayloadKind has a value and the value is 'Feed' bool isFeedPayload = expandedPayloadKind == ODataPayloadKind.Feed; // Make sure the IsCollection property agrees with the payload kind for entry and feed payloads Func <object, string> errorTemplate = null; if (!isEntityReferenceLinkPayload && navigationLink.IsCollection.HasValue && expandedPayloadKind.HasValue) { // For feed/entry make sure the IsCollection property is set correctly. if (isFeedPayload != navigationLink.IsCollection.Value) { errorTemplate = expandedPayloadKind.Value == ODataPayloadKind.Feed ? (Func <object, string>)Strings.WriterValidationUtils_ExpandedLinkIsCollectionFalseWithFeedContent : Strings.WriterValidationUtils_ExpandedLinkIsCollectionTrueWithEntryContent; } } IEdmNavigationProperty navigationProperty = null; if (errorTemplate == null && declaringEntityType != null) { navigationProperty = WriterValidationUtils.ValidateNavigationPropertyDefined(navigationLink.Name, declaringEntityType); Debug.Assert(navigationProperty != null, "If we have a declaring type we expect a non-null navigation property since open nav props are not allowed."); bool isCollectionType = navigationProperty.Type.TypeKind() == EdmTypeKind.Collection; // Make sure the IsCollection property agrees with the metadata type for entry and feed payloads if (navigationLink.IsCollection.HasValue && isCollectionType != navigationLink.IsCollection) { // Ignore the case where IsCollection is 'false' and we are writing an entity reference link // (see comment above) if (!(navigationLink.IsCollection == false && isEntityReferenceLinkPayload)) { errorTemplate = isCollectionType ? (Func <object, string>)Strings.WriterValidationUtils_ExpandedLinkIsCollectionFalseWithFeedMetadata : Strings.WriterValidationUtils_ExpandedLinkIsCollectionTrueWithEntryMetadata; } } // Make sure that the payload kind agrees with the metadata. // For entity reference links we check separately in ODataWriterCore.CheckForNavigationLinkWithContent. if (!isEntityReferenceLinkPayload && expandedPayloadKind.HasValue && isCollectionType != isFeedPayload) { errorTemplate = isCollectionType ? (Func <object, string>)Strings.WriterValidationUtils_ExpandedLinkWithEntryPayloadAndFeedMetadata : Strings.WriterValidationUtils_ExpandedLinkWithFeedPayloadAndEntryMetadata; } } if (errorTemplate != null) { string uri = navigationLink.Url == null ? "null" : UriUtils.UriToString(navigationLink.Url); throw new ODataException(errorTemplate(uri)); } return(navigationProperty); }
/// <summary> /// Creates the URI for a batch request operation. /// </summary> /// <param name="uri">The uri to process.</param> /// <param name="baseUri">The base Uri to use.</param> /// <param name="urlResolver">An optional custom URL resolver to resolve URLs for writing them into the payload.</param> /// <returns>An URI to be used in the request line of a batch request operation. It uses the <paramref name="urlResolver"/> /// first and falls back to the defaullt URI building schema if the no URL resolver is specified or the URL resolver /// returns null. In the default scheme, the method either returns the specified <paramref name="uri"/> if it was absolute, /// or it's combination with the <paramref name="baseUri"/> if it was relative.</returns> /// <remarks> /// This method will fail if no custom resolution is implemented and the specified <paramref name="uri"/> is /// relative and there's no base URI available. /// </remarks> internal static Uri CreateOperationRequestUri(Uri uri, Uri baseUri, IODataUrlResolver urlResolver) { Debug.Assert(uri != null, "uri != null"); Uri resultUri; if (urlResolver != null) { // The resolver returns 'null' if no custom resolution is desired. resultUri = urlResolver.ResolveUrl(baseUri, uri); if (resultUri != null) { return(resultUri); } } if (uri.IsAbsoluteUri) { resultUri = uri; } else { if (baseUri == null) { string errorMessage = UriUtils.UriToString(uri).StartsWith("$", StringComparison.Ordinal) ? Strings.ODataBatchUtils_RelativeUriStartingWithDollarUsedWithoutBaseUriSpecified(UriUtils.UriToString(uri)) : Strings.ODataBatchUtils_RelativeUriUsedWithoutBaseUriSpecified(UriUtils.UriToString(uri)); throw new ODataException(errorMessage); } resultUri = UriUtils.UriToAbsoluteUri(baseUri, uri); } return(resultUri); }
/// <summary> /// Validates that message writer settings are correct. /// </summary> /// <param name="messageWriterSettings">The message writer settings to validate.</param> /// <param name="writingResponse">True if we are writing a response.</param> internal static void ValidateMessageWriterSettings(ODataMessageWriterSettings messageWriterSettings, bool writingResponse) { Debug.Assert(messageWriterSettings != null, "messageWriterSettings != null"); if (messageWriterSettings.PayloadBaseUri != null && !messageWriterSettings.PayloadBaseUri.IsAbsoluteUri) { throw new ODataException(Strings.WriterValidationUtils_MessageWriterSettingsBaseUriMustBeNullOrAbsolute(UriUtils.UriToString(messageWriterSettings.PayloadBaseUri))); } if (messageWriterSettings.HasJsonPaddingFunction() && !writingResponse) { throw new ODataException(Strings.WriterValidationUtils_MessageWriterSettingsJsonPaddingOnRequestMessage); } }