/// <summary> /// Populates a contract description from a domain service description. /// </summary> /// <param name="contractDesc">Contract description to populate.</param> /// <param name="domainServiceDescription">Domain service description.</param> private void LoadContractDescription(ContractDescription contractDesc, DomainServiceDescription domainServiceDescription) { OperationDescription operationDesc; Debug.Assert(this.domainDataServiceMetadata != null, "this.domainDataServiceMetadata != null"); // Create contract operations by inferring them from the [Query] & [Invoke] methods on the domain service. foreach (DomainOperationEntry operation in domainServiceDescription.DomainOperationEntries) { if (this.domainDataServiceMetadata.Sets.ContainsKey(operation.Name) || this.domainDataServiceMetadata.ServiceOperations.ContainsKey(operation.Name)) { switch (operation.Operation) { case DomainOperation.Query: operationDesc = ODataEndpointFactory.CreateQueryOperationDescription(contractDesc, operation); Type queryOperationType = typeof(DomainDataServiceQueryOperationBehavior <>).MakeGenericType(operation.AssociatedType); // Add as first behavior such that our operation invoker is the first in the chain. operationDesc.Behaviors.Insert(0, (IOperationBehavior)Activator.CreateInstance(queryOperationType, operation)); contractDesc.Operations.Add(operationDesc); break; case DomainOperation.Invoke: operationDesc = ODataEndpointFactory.CreateOperationDescription(contractDesc, operation); // Add as first behavior such that our operation invoker is the first in the chain. operationDesc.Behaviors.Insert(0, new DomainDataServiceInvokeOperationBehavior(operation)); contractDesc.Operations.Add(operationDesc); break; default: break; } } } }
/// <summary> /// Create operation corresponding to given DomainService query operation. /// </summary> /// <param name="declaringContract">Contract to which operation will belong.</param> /// <param name="operation">DomainService query operation.</param> /// <returns>Created operation.</returns> private static OperationDescription CreateQueryOperationDescription(ContractDescription declaringContract, DomainOperationEntry operation) { OperationDescription operationDesc = ODataEndpointFactory.CreateOperationDescription(declaringContract, operation); // Change the return type to QueryResult<TEntity>. operationDesc.Messages[1].Body.ReturnValue.Type = typeof(IEnumerable <>).MakeGenericType(operation.AssociatedType); return(operationDesc); }
/// <summary> /// Create operation corresponding to given DomainService operation. /// </summary> /// <param name="declaringContract">Contract to which operation will belong.</param> /// <param name="operation">DomainService operation.</param> /// <returns>Created operation.</returns> private static OperationDescription CreateOperationDescription(ContractDescription declaringContract, DomainOperationEntry operation) { OperationDescription operationDesc = new OperationDescription(operation.Name, declaringContract); // Propagate behaviors. foreach (IOperationBehavior behavior in operation.Attributes.OfType <IOperationBehavior>()) { operationDesc.Behaviors.Add(behavior); } // Add standard web behaviors. if ((operation.Operation == DomainOperation.Query && ((QueryAttribute)operation.OperationAttribute).HasSideEffects) || (operation.Operation == DomainOperation.Invoke && ((InvokeAttribute)operation.OperationAttribute).HasSideEffects)) { // For operations with side-effects i.e. with WebInvoke attribute, we need to build a default GET like // URI template so that, the parameter processing is taken care of by the WebHttpBehavior selector. WebInvokeAttribute attrib = ServiceUtils.EnsureBehavior <WebInvokeAttribute>(operationDesc); if (attrib.UriTemplate == null) { attrib.UriTemplate = ODataEndpointFactory.BuildDefaultUriTemplate(operation); } } else { ServiceUtils.EnsureBehavior <WebGetAttribute>(operationDesc); } string action = ServiceUtils.GetRequestMessageAction(declaringContract, operationDesc.Name, null); // Define operation input. MessageDescription inputMessageDesc = new MessageDescription(action, MessageDirection.Input); inputMessageDesc.Body.WrapperName = operationDesc.Name; inputMessageDesc.Body.WrapperNamespace = ServiceUtils.DefaultNamespace; for (int i = 0; i < operation.Parameters.Count; i++) { DomainOperationParameter parameter = operation.Parameters[i]; MessagePartDescription parameterPartDesc = new MessagePartDescription(parameter.Name, ServiceUtils.DefaultNamespace) { Index = i, Type = TypeUtils.GetClientType(parameter.ParameterType) }; inputMessageDesc.Body.Parts.Add(parameterPartDesc); } operationDesc.Messages.Add(inputMessageDesc); // Define operation output. string responseAction = ServiceUtils.GetResponseMessageAction(declaringContract, operationDesc.Name, null); MessageDescription outputMessageDesc = new MessageDescription(responseAction, MessageDirection.Output); outputMessageDesc.Body.WrapperName = operationDesc.Name + "Response"; outputMessageDesc.Body.WrapperNamespace = ServiceUtils.DefaultNamespace; if (operation.ReturnType != typeof(void)) { outputMessageDesc.Body.ReturnValue = new MessagePartDescription(operationDesc.Name + "Result", ServiceUtils.DefaultNamespace) { Type = TypeUtils.GetClientType(operation.ReturnType) }; } operationDesc.Messages.Add(outputMessageDesc); return(operationDesc); }