示例#1
0
        /// <summary>
        /// Override in a derived class to extened or modify the behavior of the service across an endpoint.
        /// </summary>
        /// <remarks>
        /// This base implementation sets up the proper operation dispatcher, formatter, and effor handler.
        /// Derived implementations shyould always call the base.
        /// </remarks>
        /// <param name="endpoint">The endpoint that exposes the contract.</param>
        /// <param name="endpointDispatcher">The endpoint dispatcher to be modified or extended.</param>
        protected virtual void OnApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
            if (endpoint == null)
            {
                throw Fx.Exception.ArgumentNull("endpoint");
            }

            if (endpointDispatcher == null)
            {
                throw Fx.Exception.ArgumentNull("endpointDispatcher");
            }

            Uri helpUri = null;

            OperationDescription[] helpOperations = null;
            if (this.HelpEnabled)
            {
                helpUri        = new UriTemplate(HelpPage.OperationListHelpPageUriTemplate).BindByPosition(endpoint.ListenUri);
                helpOperations = HelpPage.AddHelpOperations(endpoint.Contract, endpointDispatcher.DispatchRuntime);
            }

            List <HttpOperationDescription> httpOperations = new List <HttpOperationDescription>();

            foreach (OperationDescription operationDescription in endpoint.Contract.Operations)
            {
                HttpOperationDescription httpOperationDescription = operationDescription.ToHttpOperationDescription();
                httpOperations.Add(httpOperationDescription);
            }

            // endpoint filter
            endpointDispatcher.AddressFilter  = new PrefixEndpointAddressMessageFilter(endpoint.Address);
            endpointDispatcher.ContractFilter = new MatchAllMessageFilter();

            // operation selector
            endpointDispatcher.DispatchRuntime.OperationSelector = this.OnGetOperationSelector(endpoint, httpOperations);
            UriAndMethodOperationSelector httpOperationSelector = endpointDispatcher.DispatchRuntime.OperationSelector as UriAndMethodOperationSelector;

            if (httpOperationSelector != null)
            {
                httpOperationSelector.HelpPageUri = helpUri;
            }

            // unhandled operation
            string actionStarOperationName = null;

            foreach (OperationDescription operation in endpoint.Contract.Operations)
            {
                if (operation.Messages[0].Direction == MessageDirection.Input &&
                    operation.Messages[0].Action == WildcardAction)
                {
                    actionStarOperationName = operation.Name;
                    break;
                }
            }

            if (actionStarOperationName != null)
            {
                endpointDispatcher.DispatchRuntime.Operations.Add(
                    endpointDispatcher.DispatchRuntime.UnhandledDispatchOperation);
            }

            // message formatter
            foreach (HttpOperationDescription httpOperationDescription in httpOperations)
            {
                DispatchOperation dispatchOperation = null;
                if (endpointDispatcher.DispatchRuntime.Operations.Contains(httpOperationDescription.Name))
                {
                    dispatchOperation = endpointDispatcher.DispatchRuntime.Operations[httpOperationDescription.Name];
                }
                else if (endpointDispatcher.DispatchRuntime.UnhandledDispatchOperation.Name == httpOperationDescription.Name)
                {
                    dispatchOperation = endpointDispatcher.DispatchRuntime.UnhandledDispatchOperation;
                }

                if (dispatchOperation != null)
                {
                    dispatchOperation.Formatter          = this.OnGetMessageFormatter(endpoint, httpOperationDescription);
                    dispatchOperation.DeserializeRequest = true;
                    dispatchOperation.SerializeReply     = !dispatchOperation.IsOneWay;
                }

                //FIX: GB - IQueryable
                if (httpOperationDescription.ReturnValue != null)
                {
                    var returnType = httpOperationDescription.ReturnValue.Type;
                    if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(IQueryable <>))
                    {
                        httpOperationDescription.Behaviors.Add(new QueryCompositionAttribute());
                    }
                }
            }

            // add any user error handlers
            IEnumerable <HttpErrorHandler> errorHandlers = this.OnGetHttpErrorHandlers(endpoint, httpOperations);

            if (errorHandlers != null)
            {
                foreach (HttpErrorHandler errorHandler in errorHandlers)
                {
                    endpointDispatcher.ChannelDispatcher.ErrorHandlers.Add(errorHandler);
                }
            }

            // add the default error handler
            HttpErrorHandler defaultErrorHandler = new HttpResponseErrorHandler(
                this.OperationHandlerFactory.Formatters,
                helpUri,
                endpointDispatcher.DispatchRuntime.ChannelDispatcher.IncludeExceptionDetailInFaults);

            endpointDispatcher.ChannelDispatcher.ErrorHandlers.Add(defaultErrorHandler);

            // remove the help operations from the contract if they were added
            if (helpOperations != null)
            {
                foreach (OperationDescription helpOperation in helpOperations)
                {
                    if (endpoint.Contract.Operations.Contains(helpOperation))
                    {
                        endpoint.Contract.Operations.Remove(helpOperation);
                    }
                }
            }
        }