/// <summary> /// Selects the service operation to call. /// </summary> /// <param name="message">The Message object sent to invoke a service operation.</param> /// <param name="uriMatched">A value that specifies whether the URI matched a specific service operation.</param> /// <returns>The name of the service operation to call.</returns> protected override string SelectOperation(ref Message message, out bool uriMatched) { uriMatched = false; string[] segments = UriUtils.EnumerateSegments(message.Properties.Via, this.baseUri); Debug.Assert(segments != null, "We should be getting a non-null segments collection."); object property; HttpRequestMessageProperty httpRequestMessageProperty = null; if (message.Properties.TryGetValue(HttpRequestMessageProperty.Name, out property)) { httpRequestMessageProperty = (HttpRequestMessageProperty)property; } if (httpRequestMessageProperty == null) { return(base.SelectOperation(ref message, out uriMatched)); } // Dis-allow query options. DomainDataServiceOperationSelector.DisallowQueryOptions(message.Properties.Via); string identifier = null; if (segments.Length > 0 && UriUtils.ExtractSegmentIdentifier(segments[0], out identifier)) { // Disallow selection of entries within response sets. DomainDataServiceOperationSelector.DisallowEntrySelection(identifier, segments[0]); } // Service description or metadata request. if (0 == segments.Length || (1 == segments.Length && identifier == ServiceUtils.MetadataOperationName)) { DomainDataServiceOperationSelector.DisallowNonGetRequests(httpRequestMessageProperty.Method); // Metadata requests only available through GET. uriMatched = true; Collection <UriTemplateMatch> matches = DomainDataServiceOperationSelector.CreateAstoriaTemplate(this.baseUri).Match(message.Properties.Via); if (matches.Count > 0) { message.Properties.Add( ServiceUtils.UriTemplateMatchResultsPropertyName, matches[0]); // Dis-allow json requests for metadata documents. DomainDataServiceOperationSelector.DisallowJsonRequests( identifier != null ? RequestKind.MetadataDocument : RequestKind.ServiceDocument, httpRequestMessageProperty.Headers[HttpRequestHeader.Accept]); return(identifier ?? ServiceUtils.ServiceDocumentOperationName); } else { // Let the base error with Endpoint not found. return(base.SelectOperation(ref message, out uriMatched)); } } else { if (segments.Length > 1) { // More than 1 segments e.g. navigation is not supported. throw new DomainDataServiceException((int)HttpStatusCode.BadRequest, Resource.DomainDataService_MultipleSegments_NotAllowed); } // Remove the trailing parentheses from the URI. message.Headers.To = UriUtils.ReplaceLastSegment(message.Headers.To, identifier); string operationName; if (this.serviceRootQueryOperations.TryGetValue(identifier, out operationName)) { // Only allow GETs on resource sets. DomainDataServiceOperationSelector.DisallowNonGetRequests(httpRequestMessageProperty.Method); // Check if a resource set request matches current request. uriMatched = true; message.Properties.Add( ServiceUtils.UriTemplateMatchResultsPropertyName, DomainDataServiceOperationSelector.CreateAstoriaTemplate(this.baseUri).Match(message.Properties.Via)[0]); // Dis-allow json requests for resource sets. DomainDataServiceOperationSelector.DisallowJsonRequests(RequestKind.ResourceSet, httpRequestMessageProperty.Headers[HttpRequestHeader.Accept]); return(operationName); } } string result; try { // Delegate to base for all non-root query operations. result = base.SelectOperation(ref message, out uriMatched); } catch (Exception innerException) { if (innerException.IsFatal()) { throw; } else { throw new DomainDataServiceException((int)HttpStatusCode.NotFound, Resource.DomainDataService_Selection_Error, innerException); } } if (uriMatched == false) { throw new DomainDataServiceException((int)HttpStatusCode.NotFound, Resource.DomainDataService_Operation_NotFound); } else if (String.IsNullOrEmpty(result)) { DomainDataServiceException e = new DomainDataServiceException((int)HttpStatusCode.MethodNotAllowed, Resource.DomainDataService_Operation_Method_NotAllowed); e.ResponseAllowHeader = httpRequestMessageProperty.Method == ServiceUtils.HttpGetMethodName ? ServiceUtils.HttpPostMethodName : ServiceUtils.HttpGetMethodName; throw e; } // Dis-allow json returning service operation requests. DomainDataServiceOperationSelector.DisallowJsonRequests(RequestKind.ServiceOperation, httpRequestMessageProperty.Headers[HttpRequestHeader.Accept]); return(result); }