internal static void AddPreflightOperations(ServiceEndpoint endpoint, List <OperationDescription> corsOperations) { Dictionary <string, PreflightOperationBehavior> uriTemplates = new Dictionary <string, PreflightOperationBehavior>(StringComparer.OrdinalIgnoreCase); // foreach (OperationDescription operation in corsOperations) { if (operation.Behaviors.Find <WebGetAttribute>() != null || operation.IsOneWay == true) { // no need to add preflight operation for GET requests, no support for 1-way messages continue; } // WebInvokeAttribute originalWia = operation.Behaviors.Find <WebInvokeAttribute>(); string originalUriTemplate = ((originalWia != null && originalWia.UriTemplate != null) ? NormalizeTemplate(originalWia.UriTemplate) : operation.Name); // string originalMethod = ((originalWia != null && originalWia.Method != null) ? originalWia.Method : "POST"); if (uriTemplates.ContainsKey(originalUriTemplate) == true) { // there is already an OPTIONS operation for this URI, we can reuse it PreflightOperationBehavior operationBehavior = uriTemplates[originalUriTemplate]; operationBehavior.AddAllowedMethod(originalMethod); } else { ContractDescription contract = operation.DeclaringContract; PreflightOperationBehavior preflightOperationBehavior = null; OperationDescription preflightOperation = CreatePreflightOperation(operation, originalUriTemplate, originalMethod, out preflightOperationBehavior); uriTemplates.Add(originalUriTemplate, preflightOperationBehavior); // contract.Operations.Add(preflightOperation); } } }
internal static OperationDescription CreatePreflightOperation(OperationDescription operation, string originalUriTemplate, string originalMethod, out PreflightOperationBehavior preflightOperationBehavior) { ContractDescription contract = operation.DeclaringContract; // // create new Operation Contract for the Method="OPTIONS" OperationDescription ret = new OperationDescription(operation.Name + CORSEnabledOperationAttribute.PreflightSuffix, contract); // // configure Messages { MessageDescription inputMessage = new MessageDescription(operation.Messages[0].Action + CORSEnabledOperationAttribute.PreflightSuffix, MessageDirection.Input); inputMessage.Body.Parts.Add(new MessagePartDescription("input", contract.Namespace) { Index = 0, Type = typeof(Message) }); ret.Messages.Add(inputMessage); } { MessageDescription outputMessage = new MessageDescription(operation.Messages[1].Action + CORSEnabledOperationAttribute.PreflightSuffix, MessageDirection.Output); outputMessage.Body.ReturnValue = new MessagePartDescription(ret.Name + "Return", contract.Namespace) { Type = typeof(Message) }; ret.Messages.Add(outputMessage); } // // configure Behaviors { // configure default Behaviors ret.Behaviors.Add(new WebInvokeAttribute() { Method = "OPTIONS", UriTemplate = originalUriTemplate, }); ret.Behaviors.Add(new DataContractSerializerOperationBehavior(ret)); // // configure custom Behavior preflightOperationBehavior = new PreflightOperationBehavior(ret); preflightOperationBehavior.AddAllowedMethod(originalMethod); ret.Behaviors.Add(preflightOperationBehavior); } // return(ret); }