Read GRPC headers - c#

I'm sending data via GRPC to, let's call it, IntegrationApi, calling a method Foo. I need to read header values from the response (the API I'm communicating with sends rate-limiting headers).
I'm using https://www.nuget.org/packages/Grpc.Core/
var metaData = new Metadata();
metadata.Add(new Metadata.Entry("Authorization", $"Bearer {apiKey}"));
var channel = new Channel("url to endpoint", new SslCredentials());
var client = new IntegrationApi(channel);
var callOptions = new CallOptions()
.WithHeaders(metadata)
.WithDeadline(DateTime.UtcNow.AddSeconds(15))
.WithWaitForReady(false);
var response = client.Foo(req, options);
but the response only gives me the properties based on the Foo.proto file.
How do I do this?

You are using the synchronous version of "Foo" method, and that one uses a simplified version of the API (=only allows access to the response and throws RpcExceptions in case of an error).
If you call the asynchronous version of the same method ("FooAsync"), you'll get back a call object that can access all the call details (such as response headers).
https://github.com/grpc/grpc/blob/044a8e29df4c5c2716c7e8250c6b2585e1c425ff/src/csharp/Grpc.Core.Api/AsyncUnaryCall.cs#L73

Related

C# http request add json object in the content

I'm making an http request post to an external api. I am constructing a json object to add to the request body. How can I check if the added body/content is correct before it is sent.
public async void TestAuthentication()
{
var client = new HttpClient();
var request = new HttpRequestMessage()
{
RequestUri = new Uri("http://test"),
Method = HttpMethod.Post
};
var jsonObj = new
{
data = "eneAZDnJP/5B6r/X6RyAlP3J",
};
request.Content = new StringContent(JsonConvert.SerializeObject(jsonObj), Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
}
If you are not sure whether the serialization works as intended, you could give it a shot in LINQpad or dotnetfiddle.net. See my example that returns the JSON on the console. These tools are great for quick prototyping a method or a snippet, if you are not sure if a piece of code works as intended.
You could also check in Wireshark, but that could be a bit of an overkill and works best if your connection if not encrypted (no HTTPS).
I personally tend to test code that calls some API the following way:
Make the called URL parameterizable (via the classes constructor)
If there is any variable data this data should be passed as the methods parameter(s)
For your test start an HTTP server from your test fixture (read on testing with xUnit or NUnit if you don't know what this means)
I use PeanutButter.SimpleHTTPServer for that
Pass the local IP to the class that accesses the API
Check whether the HTTP server received the expected data
Whether or not this kind of code shall be tested (this way) may be debatable, but I found this way to work kind of good. I used to abstract the HttpClient class away, but IMHO I would not recommend this anymore, because if the class accesses the API (and does not do anything else, which is important), the HTTP access is the crucial part that shall be tested and not mocked.

How do I set up HttpClient PostAsync to call a new web browser

I am using HttpClient PostAsync to send data to a URI. However, the following code doesn't behave as expected:
using (var client = new HttpClient())
{
var values = new Dictionary<string, string>
{
{"cpm_site_id",TOKEN},
{"apikey",API_KEY},
{"cpm_amount",input.Amount},
{"cpm_currency",input.Currency},
{"cpm_trans_id",input.Id},
{"cpm_custom",input.Custom},
};
// Get the parameters in the url encoded format
var content = new FormUrlEncodedContent(values);
//Send request
var response = await client.PostAsync(new Uri(Urls.GetUrl(Methods.Pay, IS_PRODUCTION_SITE)), content);
When the client closes their browser, I want to receive an event notification to call this code, send the above data to the client, and open a new browser instance to perform additional actions. However, this code doesn't accomplish this and I'm not sure exactly why.
I think you'll need to use something like Selenium to automate a web browser. The HttpClient can perform HTTP functions, but does not work like a web browser does.
See this SO post for a 'hello world' example
See this SO post for an example of capturing the browser close event. I've not done this with C#, but I'd imagine it'll be similar to this JAVA example.

How to upload data with Microsoft.Net.Http?

In the past I made a class that shunk the request on an endpoint. Now, I create a dll that include this method, this is the code that I'm trying to convert on this library:
using (var client = new HttpClient())
{
string requestJson = JsonConvert.SerializeObject(data);
client.DefaultRequestHeaders.Add("token", token);
byte[] responseArray = client. 'there is no upload data method
// the bottom code is of the old method
byte[] responseArray = client.UploadData(requestURI, method, Encoding.UTF8.GetBytes(requestJson));
return Encoding.ASCII.GetString(responseArray);
}
In the not portable library System.Net I can call client.UploadData, but here I see only : postAsync and putAsync, there is a method that independent from the put or post request allow me to send the data from the client to the server? Thanks in advance.
In your old code you used some method passed in method parameter to send data with UploadData method, and it was probably POST or PUT. If you do not specify the method for UploadData, POST is being used. So you should use PostAsyncor PutAsync, based on you current code and the value of method parameter you pass to UploadData.
The simplest way would be to use something like this:
using(var client = new HttpClient())
{
var response = await client.PostAsJsonAsync(requestUrl, data);
return await response.Content.ReadAsStringAsync();
}
The code for PUT would be the same, but with PutAsJsonAsync
In an HTTP request PUT and POST are the correct ways to transmit data to a server, it does not make sense to send data independently of these methods. When you are using a client such as that available in System.Net this is merely being abstracted away from you.

Modify request headers per request C# HttpClient PCL

I'm currently using the System.Net.Http.HttpClient for cross platform support.
I read that it is not a good practice to instantiate a HttpClient object for each request and that you should reuse it whenever possible.
Now I have a problem while writing a client library for a service. Some API calls need to have a specific header, some MUST not include this specific header.
It seems that I can only manipulate the "DefaultRequestHeaders" which will be send with each request.
Is there an option when actually making the request with e.g. "client.PostAsync()" to modify the headers only for the specific request?
(Info: Requests can be multi threaded).
Thanks in advance!
Yes, you can create a new HttpRequestMessage, set all the properties you need to, and then pass it to SendAsync.
var request = new HttpRequestMessage() {
RequestUri = new Uri("http://example.org"),
Method = HttpMethod.Post,
Content = new StringContent("Here is my content")
}
request.Headers.Accept.Add(...); // Set whatever headers you need to
var response = await client.SendAsync(request);
Use HttpContent.Headers. Simply create HttpContent instance with required headers and pass it to PostAsync method.

how to call webservicemethod in windows service

Basically my idea is to develop a proxy which will run in windows
I have created windows service application which running successfully and i have integrated a web service code in the windows service application running in windows service.
How to call that web service method when the client hits my url?
How to form the url which can call web service method to get the method return value?
OK, I'll try to answer.
Let's assume you want to call REST web service. What do you need? A HttpClient and (probably) JSON/XML Serializer. You can use built-in .NET classes, or a library like RestSharp
Sample calling REST web service using RestSharp
var client = new RestClient("http://example.com");
// client.Authenticator = new HttpBasicAuthenticator(username, password);
var request = new RestRequest("resource/{id}", Method.POST);
request.AddParameter("name", "value"); // adds to POST or URL querystring based on Method
request.AddUrlSegment("id", 123); // replaces matching token in request.Resource
// easily add HTTP Headers
request.AddHeader("header", "value");
// add files to upload (works with compatible verbs)
request.AddFile(path);
// execute the request
RestResponse response = client.Execute(request);
var content = response.Content; // raw content as string
// or automatically deserialize result
// return content type is sniffed but can be explicitly set via RestClient.AddHandler();
RestResponse<Person> response2 = client.Execute<Person>(request);
var name = response2.Data.Name;
// easy async support
client.ExecuteAsync(request, response => {
Console.WriteLine(response.Content);
});
// async with deserialization
var asyncHandle = client.ExecuteAsync<Person>(request, response => {
Console.WriteLine(response.Data.Name);
});
// abort the request on demand
asyncHandle.Abort();
You are not required to use RestSharp, no. For simple cases HttpWebRequest (+DataContractJsonSerializaer or Xml analogue) will be just perfect
Having SOAP web service?
Follow the instructions provided here

Categories