private void AddPreflightOperations(ServiceEndpoint endpoint, List <OperationDescription> corsOperations) { Dictionary <string, PreflightOperationBehavior> uriTemplates = new Dictionary <string, PreflightOperationBehavior>(StringComparer.OrdinalIgnoreCase); foreach (var operation in corsOperations) { if (operation.Behaviors.Find <WebGetAttribute>() != null || operation.IsOneWay) { // no need to add preflight operation for GET requests, no support for 1-way messages continue; } string originalUriTemplate; WebInvokeAttribute originalWia = operation.Behaviors.Find <WebInvokeAttribute>(); if (originalWia != null && originalWia.UriTemplate != null) { originalUriTemplate = NormalizeTemplate(originalWia.UriTemplate); } else { originalUriTemplate = operation.Name; } string originalMethod = originalWia != null && originalWia.Method != null ? originalWia.Method : "POST"; if (uriTemplates.ContainsKey(originalUriTemplate)) { // 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; OperationDescription preflightOperation; PreflightOperationBehavior preflightOperationBehavior; CreatePreflightOperation(operation, originalUriTemplate, originalMethod, contract, out preflightOperation, out preflightOperationBehavior); uriTemplates.Add(originalUriTemplate, preflightOperationBehavior); contract.Operations.Add(preflightOperation); } } }
private static void CreatePreflightOperation(OperationDescription operation, string originalUriTemplate, string originalMethod, ContractDescription contract, out OperationDescription preflightOperation, out PreflightOperationBehavior preflightOperationBehavior) { preflightOperation = new OperationDescription(operation.Name + CorsConstants.PreflightSuffix, contract); MessageDescription inputMessage = new MessageDescription(operation.Messages[0].Action + CorsConstants.PreflightSuffix, MessageDirection.Input); inputMessage.Body.Parts.Add(new MessagePartDescription("input", contract.Namespace) { Index = 0, Type = typeof(Message) }); preflightOperation.Messages.Add(inputMessage); MessageDescription outputMessage = new MessageDescription(operation.Messages[1].Action + CorsConstants.PreflightSuffix, MessageDirection.Output); outputMessage.Body.ReturnValue = new MessagePartDescription(preflightOperation.Name + "Return", contract.Namespace) { Type = typeof(Message) }; preflightOperation.Messages.Add(outputMessage); WebInvokeAttribute wia = new WebInvokeAttribute(); wia.UriTemplate = originalUriTemplate; wia.Method = "OPTIONS"; preflightOperation.Behaviors.Add(wia); preflightOperation.Behaviors.Add(new DataContractSerializerOperationBehavior(preflightOperation)); preflightOperationBehavior = new PreflightOperationBehavior(preflightOperation); preflightOperationBehavior.AddAllowedMethod(originalMethod); preflightOperation.Behaviors.Add(preflightOperationBehavior); }