How to pass http header value to WCF rest service operation? - c#

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];

Related

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?

WCF Service - HTTP Request and Response

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;

Is it possible or necessary to set the content type of a ServiceStack client delete request?

I have the following code.
public T SendUpdateRequest(string url)
{
using (JsonServiceClient client = new JsonServiceClient())
{
T response = client.Put<T>(url);
return response;
}
}
I have similar methods for create and delete requests, calling the JsonServiceClient Post and Delete methods respectively.
When calling my update or create methods, the call to the external API works fine. Delete does not. I can see that the API's delete method does indeed work if I fire a request to it via REST console.
When I compare my non-working delete with the working one's request/response in Fiddler, I can see the main difference is my request is not setting content-type to application/json (all these methods return JSON).
My question is, is it possible (or even necessary) to explicitly set the content-type of my delete request to application/json in order to successfully call my API method?
The ServiceStack clients do not set the content-type header on requests where there is no request body, as the content-type only applies to the body, and is therefore redundant.
This can be seen here in the code that prepares the client request.
if (httpMethod.HasRequestBody())
{
client.ContentType = ContentType;
...
A correctly implemented RESTful service should be happy with a DELETE request without content-type being specified where there is no body.
DELETE /User/123 HTTP/1.1
If the service you are calling is not happy with your request without this type being specified (which is unusual), then you can manually enforce the sending of the type using this filter:
var client = new JsonServiceClient("https://service/");
client.RequestFilter += (httpReq) => {
// Force content type to be sent on all requests
httpReq.ContentType = "application/json";
};
I hope that helps.

Need help understanding this HTTP GET request

I am trying the construct a HTTP GET web request that satisfies the following criteria
GET /v1/session
Host: developer.messenger.yahooapis.com
Authorization: < Standard OAuth credentials >
From what I know about get requests is that they are something like this :
https://someaddress.com/&parameterA=valA&parameterB=valB
where parameterA and parameterB are the parameters that are required.
Now I want to construct a similar address for the above mentioned criteria. How can I do that. I believe the address would be https://developer.messenger.yahooapis.com however I am not sure what the other requirements are for such a get request. I would appreciate it if someone could disect and specify the requirements of the above(Topmost) Get Request so that I may be able to construct a valid GET request URI.
https://developer.messenger.yahooapis.com
so your request url should be like
https://developer.messenger.yahooapis.com?parameterA=valA&parameterB=valB
you get your data in your $_GET array, just add print_r($_GET)
For a request, you need a URL like
https://developer.messenger.yahooapis.com
BUT that is only the hostname.
you need to specify a resource that you want to GET like /v1/session, so your URL is
https://developer.messenger.yahooapis.com/v1/session
If you want to pass some parameters you have to signal that the pointing part of the URL is finished. You do this with an ?. Now to add the parameters, you basically add name-value pairs, like var1=value. For multiple params use a & to seperate them. Slapping all together you get a
https://developer.messenger.yahooapis.com/v1/session?var1=value&var2=value
as URL. Now hand it to your HttpGet-method.
HttpGet will now build a request and later send it to https://developer.messenger.yahooapis.com the host/server who will return the resource to your client. To tell the host that you have the rights to access that resource, the request must contain the neccessary login informations, thats what oAuth is for. Those credentials have to be added in the request header before executing the get-request.

Categories