WCF Service - HTTP Request and Response - c#

I have 2 WCF services:
1. Inbound - the client calls this service.
2. Outbound - we send information to client.
We now know that the response from client will be in default http response for outbound, and they want us to send a default http response for inbound.
Right now, I have specified the response object as a class. How do I implement http response?, how can I manage my services to send a http response?.
I have tried to search around but I am not getting any starter links for this.
Could you please guide me in the right direction?
What should my response object look like in this case?

I solved my issue with this:
To set the response object with the value:
WebOperationContext ctx = WebOperationContext.Current;
ctx.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.OK;
To retrieve the value I used this:
int statuscode = HttpContext.Current.Response.StatusCode;
string description = HttpContext.Current.Response.StatusDescription;

Related

Why is postman sending form data in an HTTP GET?

I received a Postman json collection from an API vendor that works perfectly, but has something mystifying to me: The request is in a GET format, yet there is an x-www-form-urlencoded body.
URL: https://login.microsoftonline.com/d1e<secret>9563/oauth2/token
And when I look at the postman-generated c# code, the mystery continues:
var client = new RestClient("https://login.microsoftonline.com/d1e...d3/oauth2/token");
client.Timeout = -1;
var request = new RestRequest(Method.GET);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("grant_type", "client_credentials");
request.AddParameter("client_id", "c06bb...79");
request.AddParameter("client_secret", "7~u...D");
request.AddParameter("resource", "https://vault.azure.net");
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
Note the AddParameter constructions for a GET call. To me, this must be a slight-of-hand for merely adding those values to the querystring. But when I look at the postman console I see:
In the postman console I would have expected to see those params appended to the url as a querystring, and then everything would have made sense. But you can see that it's a bonafide Request Body.
When I make GET calls in my c# code I like to use the simple yet solid WebClient object to call the DownloadString() method. But this method is only for GETs and there's no way to send a form-post style body, understandably.
Is postman truly sending a GET with all those values being appended to the url as a querystring? And should I do the same in my DownloadString() call? Or is there something else going on here? Should I instead, in my c#, be calling the UploadString() method and sending a form post BODY as a GET??
Http protocol supports adding a body to a request, but the WebClient class you use doesn't. Presumably because it isn't considered the norm.
I'm sure there's good reasons for Microsoft using it in the OAuth flow though. Those guys normally do things right!
HTTP GET with request body
API is just an abstraction , you can send what ever you want to the API . It depends on the implementation , how the server handles these data.
Some services considers only what it requires and ignores other information
some services considers the entire requests and validates that it has only the allowed data. what should be allowed depends on the service
Postman is just a client that sends data to server , its upto you to decide what all information it should send . If you dont need any body then keep it as none. if you need some thing then add it.

How do I get RestSharp not to add oauth_callback parameters to the Authentication header

I'm trying to connect to a finicky API using RestSharp. The API uses OAuth1.0 and on the initial Request Token requires oauth_callback parameter ONLY in the query and not in the Authentication Header (I have confirmed this with Postman).
When I construct the request this way:
var Authenticator = OAuth1Authenticator.ForRequestToken(mc_apiKey, mc_appsecret);
Authenticator.ParameterHandling = OAuthParameterHandling.HttpAuthorizationHeader;
Authenticator.SignatureMethod = OAuthSignatureMethod.PlainText;
client.Authenticator = Authenticator;
var request = new RestRequest(RequestToken, Method.POST);
string AuthorizationCallBackURL = string.Format(LoopbackCallback);
request.AddParameter(_oauthCallback, AuthorizationCallBackURL, ParameterType.QueryStringWithoutEncode);
and look at the logs on the server I see the query string in the Http call,
http://192.168.0.187:8080/xxxx/ws/oauth/initiate?oauth_callback=http://192.168.0.187:8080/provider_emailer/callback.jsp
but it is also in the Authentication header:
Headers:
{Accept=[application/json, text/json, text/x-json, text/javascript, application/xml, text/xml],
accept-encoding=[gzip, deflate],
Authorization=[OAuth oauth_callback="http://192.168.0.187:8080/provider_emailer/callback.jsp",
oauth_consumer_key="XXXXXXXXXXXX",
oauth_nonce="cei09xm04qetk2ce",
oauth_signature="XXXXXXXXXXXXXXXX",
oauth_signature_method="PLAINTEXT",
oauth_timestamp="1591197088",
oauth_version="1.0"],
Content-Length=[0], Content-Type=[null],
cookie=[JSESSIONID=C8C8DB501382F7D1E52FE436600094C0],
host=[192.168.0.187:8080], user-agent=[RestSharp/106.11.4.0]}
This causes a "NotAcceptable" response. The same request done with Postman without the callback parameter in the Authentication header works.
Am I doing something wrong? Is there a way to only get the callback in the query string?
That's tricky. I looked at the code and we don't set the callback URL to the workflow object when you use the overload without this parameter. So, you're doing it conceptually correct.
However, we must collect all the parameters (default and request parameters) plus OAuth parameters to build the OAuth signature. We then use the parameters collection and extract all of them that have a name starting with oauth_ or xauth_ to the request headers (in case you use HttpAuthorizationHeader) and by doing so, we put your query parameter to the header.
Apparently, that's not ideal and it looks like a bug, so I can suggest opening an issue in RestSharp repository. Should not be hard to fix.

Get instance of ApiController class from a URL directly

I am looking for a way to call the appropriate method (get, post etc.) on an ApiController class based on the URL and request type etc. without making a http request.
Background: We have an API application with numerous controllers that needs to also accept requests from a remote server. Due to restrictions I cannot control there is no way to open ports between the two servers to allow the remote server to make the request directly so we decided to forward the data using websockets (SignalR). I can send (within reason) whatever information is required.
I have tried the below:
HttpRequestMessage request = new HttpRequestMessage();
var bld = new UriBuilder
{
Port = 123,
Path = "api/v1/search",
Query = "query=search_string"
};
request.RequestUri = bld.Uri;
var httpCfg = AppConfiguration.Get().HttpConfig; //this is the same config that UseWebApi was called with and contains the routes.
var route = httpCfg.Routes.GetRouteData(request);
var controllerSelector = new DefaultHttpControllerSelector(httpCfg);
var descriptor = controllerSelector.SelectController(request);
route contains the controller name (search) but the call to SelectController throws an exception with a 404 response in it (I presume this indicates I am missing something from the fake request). The same URI works when sent as a direct http request so the routes do work as best I can tell.
Is there a better way to do this, or if not what am I missing from the request that is causing the 404?

How to pass http header value to WCF rest service operation?

Is there any way to extract http header value and pass it to WCF rest service operation at global extension point, e.g. customized IParameterInspector? Thanks in advance.
Through your WCF service WebOperationContext you can access the current request's http headers like the following:
var request = WebOperationContext.Current.IncomingRequest;
string header = request.Headers[HttpRequestHeader.Cookie];

POST data to WCF Service from WP7

I am working on a WP7 application. If an error happens, I want to log the error back to my server. To handle this, I have created a WCF service operation. I want this operation to be REST ful so that I can later use it with iPhone and Android apps. Because I'm writing information to the database, I thought the POST method would be best. For this reason, I'm using WebInvoke. To do this, I'm using the following code:
[OperationContract]
[WebInvoke(UriTemplate = "/LogError/{message}/{stackTrace}", ResponseFormat = WebMessageFormat.Json)]
public void LogError(string message, string stackTrace)
{
// Write info to the database
}
From my WP7 app, I want to call this operaiton via a WebClient. My question is, how do I do that? I don't understand how to call the LogError operation and pass along the required data via the WebClient.
Thank you for your help!
If I am getting your Service method correctly, that method is not a POST method. You can just call that with a WebClient
WebClient wc = new WebClient()
Uri uri = new Uri("http://yourUri/LogError/ABC/XYZ"); //ABC is your message and XYZ is your stacktrace string.
wc.DownloadStringAsync(uri);
Or if you are thinking about real HTTP 'POST' then below might help.
You can use HttpWebRequest to do a POST on to any service which is accepting POST
This link may be helpful - WCF REST POST XML - The remote server returned an error: (400) Bad Request
Something along the lines:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://serveraddress/LogError/{message}/{stackTrace}");
If you would want to send additional information later on, you can do so with:
request.Method = "POST";
request.BeginGetRequestStream(new AsyncCallback(ExecuteAction), request);
And have a callback:
void ExecuteAction(IAsyncResult result)
{
HttpWebRequest request = (HttpWebRequest)result.AsyncState;
using (Stream s = request.EndGetRequestStream(result))
{
s.Write(data, 0, data.Length);
}
}
If there is a specific string response from the service, you might as well include the data in the WebClient and use DownloadStringAsync to get the response data.
For starters, I found a website that should help you get started with calling the service from WP7.
Try this and let me know what you think
Have a look at this post http://blog.ike.to/2011/02/02/wp7-application-crash-reporter/
It sounds like it will pretty much do what you need already, although you might want to tweak it to suit your own service interface.

Categories