/// <summary> /// Helper method to find the service document of the OData service this context refers to /// </summary> /// <param name="maximumPayloadSize">maximum payload size in byte</param> /// <param name="uri">uri hint, which is used to derive various possible uris in hope one of them is the service base endpoint</param> /// <param name="acceptHeaderValue">value of header of Accept that will be used in request getting the response</param> /// <param name="IgnoreInputUri">if true, the given uri is known other than service base</param> /// <param name="serviceBaseUri">out parameter: the service base uri if one shall be found</param> /// <param name="responseServiceDocument">out parameter: the response object including payload, headers and status code</param> /// <param name="reqHeaders">Http headers to be sent out to server</param> /// <returns>true if a valid service document is found; otherwise false</returns> private static bool TryGetServiceDocument(int maximumPayloadSize, Uri uri, string acceptHeaderValue, bool IgnoreInputUri, out Uri serviceBaseUri, out Response responseServiceDocument, IEnumerable <KeyValuePair <string, string> > reqHeaders) { if (!IgnoreInputUri) { try { var response = WebHelper.Get(uri, acceptHeaderValue, maximumPayloadSize, reqHeaders); if (response.IsServiceDocument()) { serviceBaseUri = uri; responseServiceDocument = response; return(true); } } catch (OversizedPayloadException) { // does nothing } } var segments = uri.Segments; if (segments != null && segments.Length > 0) { Uri uriParent; if (Uri.TryCreate(uri.GetLeftPart(UriPartial.Authority) + string.Join("", segments.Take(segments.Length - 1).ToArray()), UriKind.Absolute, out uriParent)) { if (uri != uriParent) { return(ServiceContextFactory.TryGetServiceDocument(maximumPayloadSize, uriParent, acceptHeaderValue, false, out serviceBaseUri, out responseServiceDocument, reqHeaders)); } } } serviceBaseUri = null; responseServiceDocument = null; return(false); }
/// <summary> /// Factory method to set up the OData Interop context based on uri, desired format and job id /// </summary> /// <param name="destination">uri string pointing to a OData service endpoint</param> /// <param name="format">format preference, could be either "atom" or "json" - default and falling back to atom</param> /// <param name="jobId">unique identifier to tag this context</param> /// <param name="maximumPayloadSize">the maximum number of bytes rule engine is willing to retrieve from the Uri provided</param> /// <param name="reqHeaders">Http headers sent as part of request</param> /// <returns>context object representing the interop request session</returns> public static ServiceContext Create(string destination, string format, Guid jobId, int maximumPayloadSize, IEnumerable <KeyValuePair <string, string> > reqHeaders, string category = "core") { Uri inputUri; Uri serviceBaseUri = null; string serviceDocument = null; string metadataDocument = null; string entityType = null; string jsonFullMetadataPayload = null; var serviceStatus = ServiceStatus.GetInstance(); if (string.IsNullOrEmpty(format)) { throw new ArgumentException(Resource.ArgumentNotNullOrEmpty, "format"); } try { if (destination.EndsWith(@"/")) { destination = destination.TrimEnd('/'); } inputUri = new Uri(destination); } catch (UriFormatException) { if (!destination.StartsWith(@"http://") && !destination.StartsWith(@"https://")) { inputUri = new Uri(SupportedScheme.SchemeHttp + "://" + destination); } else { inputUri = new Uri(Uri.EscapeUriString(destination)); } } if (!SupportedScheme.Instance.Contains(inputUri.Scheme)) { throw new ArgumentException( string.Format(CultureInfo.CurrentCulture, Resource.formatSchemeNotSupported, inputUri.Scheme), "destination"); } string acceptHeader = ServiceContextFactory.MapFormatToAcceptValue(format); ODataMetadataType odataMetadata = ServiceContextFactory.MapFormatToMetadataType(format); Response response = WebHelper.Get(inputUri, acceptHeader, maximumPayloadSize, reqHeaders); if (response.StatusCode == HttpStatusCode.NotFound) { return(null); } var payloadFormat = response.ResponsePayload.GetFormatFromPayload(); var payloadType = ContextHelper.GetPayloadType(response.ResponsePayload, payloadFormat, response.ResponseHeaders); switch (payloadType) { case PayloadType.ServiceDoc: serviceBaseUri = inputUri; serviceDocument = response.ResponsePayload; break; case PayloadType.Metadata: if (inputUri.AbsoluteUri.EndsWith(Constants.OptionMetadata, StringComparison.Ordinal)) { if (payloadFormat == PayloadFormat.JsonLight) { serviceBaseUri = new Uri(serviceStatus.RootURL); serviceDocument = serviceStatus.ServiceDocument; } else { serviceBaseUri = new Uri(inputUri.AbsoluteUri.Substring(0, inputUri.AbsoluteUri.Length - Constants.OptionMetadata.Length)); var respSvcDoc = WebHelper.Get(serviceBaseUri, acceptHeader, maximumPayloadSize, reqHeaders); serviceDocument = respSvcDoc.ResponsePayload; } } break; default: if (payloadType.IsValidPayload()) { string fullPath = inputUri.GetLeftPart(UriPartial.Path).TrimEnd('/'); var uriPath = new Uri(fullPath); Uri baseUri; Response serviceDoc; if (ServiceContextFactory.TryGetServiceDocument(maximumPayloadSize, uriPath, acceptHeader, uriPath.AbsoluteUri == fullPath, out baseUri, out serviceDoc, reqHeaders)) { serviceBaseUri = baseUri; serviceDocument = serviceDoc.ResponsePayload; } } break; } if (payloadType == PayloadType.Metadata) { metadataDocument = response.ResponsePayload; } else { if (serviceBaseUri != null) { if (payloadFormat == PayloadFormat.JsonLight && payloadType == PayloadType.ServiceDoc) { metadataDocument = serviceStatus.MetadataDocument; } else { try { string metadataURL = serviceBaseUri.AbsoluteUri.EndsWith(@"/") ? Constants.OptionMetadata.TrimStart('/') : Constants.OptionMetadata; var responseMetadata = WebHelper.Get(new Uri(serviceBaseUri.AbsoluteUri + metadataURL), null, maximumPayloadSize, reqHeaders); if (responseMetadata != null) { metadataDocument = responseMetadata.ResponsePayload; } } catch (OversizedPayloadException) { // do nothing } } } } if (payloadFormat == PayloadFormat.JsonLight) { try { // Specify full metadata accept header string acceptHeaderOfFullMetadata = string.Empty; if (acceptHeader.Equals(Constants.V3AcceptHeaderJsonFullMetadata) || acceptHeader.Equals(Constants.V3AcceptHeaderJsonMinimalMetadata) || acceptHeader.Equals(Constants.V3AcceptHeaderJsonNoMetadata)) { acceptHeaderOfFullMetadata = Constants.V3AcceptHeaderJsonFullMetadata; } else { acceptHeaderOfFullMetadata = Constants.V4AcceptHeaderJsonFullMetadata; } // Send full metadata request and get full metadata response. var responseFullMetadata = WebHelper.Get(inputUri, acceptHeaderOfFullMetadata, maximumPayloadSize, reqHeaders); if (responseFullMetadata != null) { jsonFullMetadataPayload = responseFullMetadata.ResponsePayload; entityType = jsonFullMetadataPayload.GetFullEntityType(payloadType, payloadFormat, metadataDocument); } } catch (OversizedPayloadException) { // do nothing } } else { entityType = response.ResponsePayload.GetFullEntityType(payloadType, payloadFormat, metadataDocument); } return(new ServiceContext(inputUri, jobId, response.StatusCode, response.ResponseHeaders, response.ResponsePayload, entityType, serviceBaseUri, serviceDocument, metadataDocument, false, reqHeaders, odataMetadata, jsonFullMetadataPayload, category)); }