/// <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); } } } }