private static void CreatePreflightOperation(OperationDescription operation, string originalUriTemplateStr, string originalMethod, ContractDescription contract, out OperationDescription preflightOperation, out PreflightOperationBehavior preflightOperationBehavior)
        {
            var originalUriTemplate = new UriTemplate(originalUriTemplateStr);

            preflightOperation = new OperationDescription(operation.Name + "_preflight", contract);

            //First the input message
            MessageDescription inputMessage = new MessageDescription(operation.Messages[0].Action + "_preflight", MessageDirection.Input);

            preflightOperation.Messages.Add(inputMessage);

            //We need to mirror the input parameters in the URI template
            //First any variables in the path
            if (originalUriTemplate.PathSegmentVariableNames != null && originalUriTemplate.PathSegmentVariableNames.Count > 0)
            {
                foreach (string uriParameter in originalUriTemplate.PathSegmentVariableNames)
                {
                    inputMessage.Body.Parts.Add(new MessagePartDescription(uriParameter, "")
                    {
                        Type = typeof(string)
                    });
                }
            }
            //Next any in the querystring
            if (originalUriTemplate.QueryValueVariableNames != null && originalUriTemplate.QueryValueVariableNames.Count > 0)
            {
                foreach (string uriParameter in originalUriTemplate.QueryValueVariableNames)
                {
                    inputMessage.Body.Parts.Add(new MessagePartDescription(uriParameter, "")
                    {
                        Type = typeof(string)
                    });
                }
            }

            //Now the output message, we only need the CORS headers in reality
            MessageDescription outputMessage = new MessageDescription(operation.Messages[1].Action + "_preflight", 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.ToString();
            wia.Method      = "OPTIONS";

            //TODO:TEST
            //wia.BodyStyle = WebMessageBodyStyle.WrappedRequest;

            preflightOperation.Behaviors.Add(wia);
            preflightOperation.Behaviors.Add(new DataContractSerializerOperationBehavior(preflightOperation));
            preflightOperationBehavior = new PreflightOperationBehavior(preflightOperation);
            preflightOperationBehavior.AddAllowedMethod(originalMethod);
            preflightOperation.Behaviors.Add(preflightOperationBehavior);
        }
        private void AddPreflightOperation(OperationDescription operation, Dictionary <string, PreflightOperationBehavior> uriTemplates)
        {
            if (operation.Behaviors.Find <WebGetAttribute>() != null || operation.IsOneWay)//|| operation.DeclaringContract.Operations.Any(o => o.Behaviors.Find<PreflightOperationBehavior>() != null))
            {
                // no need to add preflight operation for GET requests, no support for 1-way messages
                return;
            }

            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);
                contract.Operations.Insert(0, preflightOperation);
            }
        }