Search code examples
wcfmicrosoft-graph-apimicrosoft-graph-webhooks

Webhook Subscription for Teams Conversation not working with WCF Relay


Can someone please help me to fix this Issue. I am not able to debug from where it is going wrong. Basically I have created a WCF Rest API WebService using WCF Relay in Azure to have hybrid connection between on-premise and Azure. Also if I am ignoring any certificate validation, that endpoint is for on-premise as it is self-signed certificate but when making API call, I am using the base64 encoded public key provided by WCF Relay when publishing it in Azure.

WCF Contract And Implementation:

Contract Interface

Implementation

I am successfully able to get the "validationToken" in the WCF service and also returning the same validationToken immediately below 5 seconds. After returning, it always error out showing this message.

Postman Client For Sending HTTP Request

Error Response and no subscription created

EDIT

WCF Contract

[OperationContract]
        [WebInvoke(Method = "POST", UriTemplate = "webhookForConservation?validationToken={validationToken}", 
            BodyStyle = WebMessageBodyStyle.Bare)]
        string webhookForConservation(WebhookPayload data, string validationToken);

WCF Implementation:

1st approach to return 200 OK status code:

public string webhookForConservation(WebhookPayload data, string validationToken = "")
        {
            ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) => true;
            var client = new HttpClient();
            client.DefaultRequestHeaders.Add("Accept", "text/plain");
            client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json");
            HttpResponseMessage response = null;
            WebOperationContext ctx = WebOperationContext.Current;
            if (validationToken != null && validationToken != "")
            {
                response = client.PostAsync("http://localhost:8080/conversationWebHook/conversationSubscription?validationToken=" + validationToken, null).Result;
                var apiContent = response.Content.ReadAsStringAsync().Result;
                ctx.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.OK;
                ctx.OutgoingResponse.ContentType = "text/plain";
                return apiContent;
            }
            else
            {
                StringContent strContent = new StringContent(DataContractJsonSerializerHelper.SerializeJson(data));
                strContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
                response = client.PostAsync("http://localhost:8080/conversationWebHook/conversationSubscription", strContent).Result;
            }
            var result = (response != null) ? response.Content.ReadAsStringAsync().Result : "";
            ctx.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.OK;
            return result;
        }

2nd Approach to return 200 status code:

public WebFaultException<string> webhookForConservation(WebhookPayload data, string validationToken="")
        {
            ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) => true;
            var client = new HttpClient();
            client.DefaultRequestHeaders.Add("Accept", "text/plain");
            client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json");
            HttpResponseMessage response = null;
            if (validationToken != null && validationToken != "")
            {
                response = client.PostAsync("http://localhost:8080/conversationWebHook/conversationSubscription?validationToken=" + validationToken, null).Result;
                var apiContent = response.Content.ReadAsStringAsync().Result;
                return new WebFaultException<string>(apiContent, HttpStatusCode.OK);
            }
            else
            {
                StringContent strContent = new StringContent(DataContractJsonSerializerHelper.SerializeJson(data));
                strContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
                response = client.PostAsync("http://localhost:8080/conversationWebHook/conversationSubscription", strContent).Result;
            }
            var result = (response != null) ? response.Content.ReadAsStringAsync().Result : "";
            return new WebFaultException<string>(result, HttpStatusCode.OK); ;
        }

Same error seen after returning 200 OK response code from WCF Service

Postman Client Throws Error

Calling Relay WCF API directly with Postman:

WCF API Call From Postman

Headers:

WCF API Call Headers From Postman

Thank you in advance for all the help.


Solution

  • Two problems were preventing the WCF relay to work properly:

    • The relay wasn't setting the response content type to text/plain, this was fixed with ctx.OutgoingResponse.ContentType = "text/plain"
    • The relay was adding an XML wrapper to the required response body, this was addressed by changing the return value to Stream