Webhook Subscription for Teams Conversation not working with WCF Relay - wcf

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
Calling Relay WCF API directly with Postman:
Headers:
Thank you in advance for all the help.

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

Related

PostAsync request with Array parameter on MVC Web API

I have Xamarin application that has POST request with array list of parameter and on my MVC WEB API we used code first Entity framework. Both was separated project solutions (.sln).
On my Xamarin project, I have PostAsync request which supplies List of array values.
using (var client = new HttpClient())
{
Parameter = string.Format("type={0}&param={1}",type, param[]);
var data = JsonConvert.SerializeObject(parameters);
var content = new StringContent(data, Encoding.UTF8, "application/json");
using (var response = await client.PostAsync(url, content))
{
using (var responseContent = response.Content)
{
result = await responseContent.ReadAsStringAsync();
}
}
}
Then In my Web API controller I have same parameter with my client side also.
[System.Web.Http.AcceptVerbs("GET", "POST")]
[System.Web.Http.HttpPost]
[Route("type={type}&param={param}")]
public BasicResponse applog([FromUri] ProfilingType type , List<string> param)
{
if (ModelState.IsValid == false)
{
throw new ModelValidationException("Model state is invalid.");
}
try
{
if(type == ProfilingType.Login)
{
var command = new SendDataProfilingCommand(param);
CommandHandler.Execute(command);
}
else
{
var command = new UpdateDataProfilingCommand(type,param);
CommandHandler.Execute(command);
}
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return new BasicResponse
{
Status = true,
Message = Ok().ToString()
};
}
Since I'm not with the API, I want to test it first on Postman or even in the URL. but my problem was when i Try to test it using this url below
http://localhost:59828/api/users/applog?type=1&param=[1,Caloocan,Metro Manila,Philippines,0,0]
I received this message : No HTTP resource was found that matches the request URI ......
My Question is, How can I test my Web API with List Parameter on URL or in the Postman ? and What Format I can use when sending a post request into my Xamarin PostAsync request?
You don't need to send as Content.
using (var client = new HttpClient())
{
Parameter = string.Format("type={0}&param={1}",type, param[]);
url = url + "?" + Parameter;
using (var response = await client.PostAsync(url))
{
using (var responseContent = response.Content)
{
result = await responseContent.ReadAsStringAsync();
}
}
}

WCF client restsharp sending raw format

I'm trying to send some data to wcf server using restsharp and xamarine and get return value.Here's code on server side:
public interface IRestService
{
[OperationContract(Name = "Login")]
[WebInvoke(UriTemplate = "/Login/", Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json,RequestFormat = WebMessageFormat.Json)]
Boolean Login(String username);
and implementation of Login:
Boolean IRestService.Login(string username)
{
if (string.IsNullOrEmpty(username))
return false;
else
return true;
}
here is how i'm trying to make connection on client side:
var client = new RestClient("http://192.168.0.187:9226/RestService.svc");
client.AddDefaultHeader("ContentType", "application/json");
var request = new RestRequest(String.Format("/Login/", "198440"));
request.Method = Method.POST;
request.AddParameter("username", "blabla");
request.RequestFormat = DataFormat.Json;
IRestResponse response1 = client.Execute<Boolean>(request);
When I'm tracing my wcf, i keep getting "The incoming message has an unexpected message format 'Raw'. The expected message formats for the operation are 'Xml', 'Json'."
Any help?
You should not use AddParamater. This create a form encoded body for the POST
instead:
request.RequestFormat = DataFormat.Json;
request.AddBody(new { "username" = "blabla"}));

How to return multipart/form-data in response from WCF service?

In my WCF service I need to return MIME Multipart data (a text file) back to client in the response. Althoug the response returned to the client, I don't see the data being returned. As a matter of fact, I don't see anything I setup on the server side being returned to the client. Could someone shed some light on this? Here is what I have in my code for building and returning response:
MultipartFormDataContent formData = new MultipartFormDataContent("myboundary");
HttpResponseMessage responseMsg = new HttpResponseMessage();
try
{
using (Stream fs = File.OpenRead("C;\\mydata.txt"))
{
formData.Add(new StreamContent(fs), "Payload", "mydata.txt");
}
}
catch (Exception ex)
{
ServiceUtil.LogMessage(ex.Message);
}
responseMsg.StatusCode = System.Net.HttpStatusCode.OK;
responseMsg.Content = formData;
WebOperationContext.Current.OutgoingResponse.ContentLength = 2048;
WebOperationContext.Current.OutgoingResponse.ContentType = "multipart/form-data";
WebOperationContext.Current.OutgoingResponse.Headers["Accept"] = "multipart/form-data";
}

I can't send byte array as parameter in REST service ? ( code attached )

I'm using WCF to create some REST service.
One of the Rest Service method need to get byte array as parameter ( picture as byte array ) and return some object.
I run this service using IIS.
But this is not working.
The code that i wrote :
[ServiceContract]
public interface IPicService
{
[OperationContract, WebInvoke(Method="POST", UriTemplate = "GetPicReport/{imageName}")]
Report GetPicReport( string imageName, Stream image );
}
[ServiceBehavior( AddressFilterMode = AddressFilterMode.Any )]
public class PicService: IPicService
{
public Report GetPicReport( string imageName, Stream image )
{
return new Report ();
}
}
I checking this code using explorer - but i get an error about missing parameter ( the image stream )
How can i test it ?
I can't use the WCF Test Client - so i wrote simple application that create http call - and this method return error 404 ( server not found )
Can you try the below code:
var request = WebRequest.Create(string.Concat(serviceUrl, resourceUrl)) as HttpWebRequest;
if (request != null)
{
request.ContentType = "text/xml";
request.Method = method;
}
//var objContent = HttpContentExtensions.CreateDataContract(requestBody);
if(method == "POST" && requestBody != null)
{
//byte[] requestBodyBytes = ToByteArrayUsingXmlSer(requestBody, "http://schemas.datacontract.org/2004/07/XMLService");
byte[] requestBodyBytes = ToByteArrayUsingDataContractSer(requestBody);
request.ContentLength = requestBodyBytes.Length;
using (Stream postStream = request.GetRequestStream())
postStream.Write(requestBodyBytes, 0, requestBodyBytes.Length);
//request.Timeout = 60000;
}
if (request != null)
{
var response = request.GetResponse() as HttpWebResponse;
if(response.StatusCode == HttpStatusCode.OK)
{
Stream responseStream = response.GetResponseStream();
if (responseStream != null)
{
var reader = new StreamReader(responseStream);
responseMessage = reader.ReadToEnd();
}
}
else
{
responseMessage = response.StatusDescription;
}
}
The post here shows how to implement a service just like yours, along with a test client (using HttpWebRequest). Another thing you can do is to enable tracing at the server, it may tell you why the request is being rejected.

forbidden:403 error while using wcf restful service

I am trying to consume wcf restful service. The code is as follows:
private static string SendRequest(string uri, string method, string contentType, string body)
{
string responseBody = null;
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(uri);
req.Method = method;
if (!String.IsNullOrEmpty(contentType))
{
req.ContentType = contentType;
}
if (body != null)
{
byte[] bodyBytes = Encoding.UTF8.GetBytes(body);
req.GetRequestStream().Write(bodyBytes, 0, bodyBytes.Length);
req.GetRequestStream().Close();
}
req.Accept = "*/*";
HttpWebResponse resp;
resp = (HttpWebResponse)req.GetResponse();
return responseBody;
}
Now the issue is, sometimes it works fine and sometimes i get the error
"the remote server returned an error 403 forbidden."
I cannot figure out why it fails. Any idea???