Exemplo n.º 1
0
        /// <summary>Constructs the operation selector for runtime.</summary>
        /// <param name="endpoint">End point.</param>
        /// <param name="metadata">Domain data service metadata.</param>
        public DomainDataServiceOperationSelector(
            ServiceEndpoint endpoint,
            DomainDataServiceMetadata metadata)
            : base(DomainDataServiceOperationSelector.ExtractNonRootQueryServiceOperations(endpoint, metadata))
        {
            this.baseUri = endpoint.ListenUri;
            this.serviceRootQueryOperations = new Dictionary <string, string>();

            // Collect all the query operations, since they are to be handled by selector in this class.
            foreach (var od in endpoint.Contract.Operations)
            {
                string resourceSetName = DomainDataServiceOperationSelector.GetRootQueryOperation(od, metadata);
                if (!String.IsNullOrEmpty(resourceSetName))
                {
                    Debug.Assert(!this.serviceRootQueryOperations.ContainsKey(resourceSetName), "There should only be 1 default query operation per set.");

                    // Note the fact that requests on resourceSet correspond to the given operation.
                    this.serviceRootQueryOperations.Add(resourceSetName, od.Name);
                }
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Obtains the service operations available on the model and hands over all those
        /// operations to the base class for processing. The root query operations are
        /// handled by this class itself.
        /// </summary>
        /// <param name="endpoint">Endpoint on which operations are defined.</param>
        /// <param name="metadata">Metadata of the domain service.</param>
        /// <returns>Endpoint that contains all the operations that base class needs to process.</returns>
        private static ServiceEndpoint ExtractNonRootQueryServiceOperations(ServiceEndpoint endpoint, DomainDataServiceMetadata metadata)
        {
            ContractDescription cd = new ContractDescription(endpoint.Contract.Name);

            // Provide all the non-root query operations to the base class, only provide those operations that
            // have some representation on the domain data service.
            foreach (OperationDescription od in endpoint.Contract.Operations)
            {
                if (metadata.ServiceOperations.Keys.Contains(od.Name))
                {
                    Debug.Assert(
                        String.IsNullOrEmpty(DomainDataServiceOperationSelector.GetRootQueryOperation(od, metadata)),
                        "Service operation must not be a root query operation.");
                    cd.Operations.Add(od);
                }
            }

            return(new ServiceEndpoint(cd, endpoint.Binding, endpoint.Address)
            {
                ListenUri = endpoint.ListenUri
            });
        }
Exemplo n.º 3
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);
        }