Exemplo n.º 1
0
        /// <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);
        }