I'm sending bytes[] to .net core web api method(from Windows application to web API) by using HttpClient with below code
HttpClientHandler clientHandler = new HttpClientHandler();
clientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; };
clientHandler.UseDefaultCredentials = true;
// Pass the handler to httpclient(from you are calling api)
HttpClient client2 = new HttpClient(clientHandler);
client2.DefaultRequestHeaders.Clear();
//client2.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/octet-stream"));
client2.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/octet-stream"); // octet-stream");
client2.DefaultRequestHeaders.TryAddWithoutValidation("Accept", "application/octet-stream");
client2.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:19.0) Gecko/20100101 Firefox/19.0");
//client2.DefaultRequestHeaders.Add("Accept", "application/octet-stream");
var content = new ByteArrayContent(fileData);
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
var response = client2.PostAsync("https://mywebsite.com/api/FileHandlingAPI/UploadFiles?filePath=abc", content).Result;
and web api method is
[Route("UploadFiles")]
[HttpPost]
public ActionResult PostDataHello([FromBody]byte[] rawData,string filePath)
{
try
{
System.IO.File.WriteAllBytes(#"C:\WordAutomation\home.zip", rawData);
return StatusCode(200);
}
catch (Exception ex)
{
return StatusCode(500, $"Error. msg: {ex.Message}");
}
}
above code working while development but after hosting in server it is not working as expected. var response receiving 200 Statuscode but bytes[] not receiving at web api method.
any suggestions or changes required above code ?
I think the Content-Type is set to JSON, which is invalid for uploading binary data in the payload.
Try
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
Above code working while development but after hosting in server it is
not working as expected. var response receiving 200 Statuscode but
bytes[] not receiving at web api method. any suggestions or changes
required above code?
Well, not sure how are getting data on local server becuse, you are sending MultipartFormData means your POCO object which is file path and byte array. As you may know we can send json object in FromBody but not the files as json. Thus, I am not sure how it working in local, and getting null data is logical either in server like IIS Or Azure.
My take on this, for sending both POCO object and Files as byte or stream we need to use FromForm and beside that, we need to bind our request object as MultipartFormDataContent to resolve your null data on your PostDataHello API action.
Required Change For Http Client:
Http Client Request Model:
public class HttpClientReqeustModel
{
public string FilePath { get; set; }
public string FileName { get; set; }
public byte[] MyByteData { get; set; }
}
Http Client Request:
public async Task<IActionResult> SendByteDataToAPIControllre()
{
HttpClientHandler clientHandler = new HttpClientHandler();
clientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; };
clientHandler.UseDefaultCredentials = true;
HttpClient client2 = new HttpClient(clientHandler);
client2.DefaultRequestHeaders.Clear();
//Bind Request Model
var requestMode = new HttpClientReqeustModel();
requestMode.MyByteData = System.IO.File.ReadAllBytes(#"D:\YourFile.pdf");
requestMode.FilePath = #"D:\YourFilePath.pdf";
requestMode.FileName = "YourFileNameYourWantToSet.pdf";
//Create Multipart Request
var formContent = new MultipartFormDataContent();
formContent.Add(new StringContent(requestMode.FilePath), "FilePath");
formContent.Add(new StreamContent(new MemoryStream(requestMode.MyByteData)), "MyByteData", requestMode.FileName);
var response = await client2.PostAsync("http://localhost:5094/UploadFiles", formContent);
return Ok();
}
Change For Asp.net Core Web API:
API Model:
public class APIRequestModel
{
public string FilePath { get; set; }
public IFormFile MyByteData { get; set; }
}
Controller:
[Route("UploadFiles")]
[HttpPost]
public async Task<ActionResult> PostDataHello([FromForm] APIRequestModel requestModel)
{
try
{
var path = Path.Combine(_environment.WebRootPath, "WordAutomation/",requestModel.MyByteData.FileName);
using (FileStream stream = new FileStream(path, FileMode.Create))
{
await requestModel.MyByteData.CopyToAsync(stream);
stream.Close();
}
// System.IO.File.WriteAllBytes(#"C:\WordAutomation\home.zip", rawData);
return StatusCode(200);
}
catch (Exception ex)
{
return StatusCode(500, $"Error. msg: {ex.Message}");
}
}
Output:
Update:
For WinForm and WPF App:
private async void button1_Click(object sender, EventArgs e)
{
HttpClientHandler clientHandler = new HttpClientHandler();
clientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; };
clientHandler.UseDefaultCredentials = true;
HttpClient client2 = new HttpClient(clientHandler);
client2.DefaultRequestHeaders.Clear();
//Bind Request Model
var requestMode = new HttpClientReqeustModel();
requestMode.MyByteData = System.IO.File.ReadAllBytes(#"D:\Md Farid Uddin Resume.pdf");
requestMode.FilePath = #"D:\Md Farid Uddin Resume.pdf";
requestMode.FileName = "MyFilename.pdf";
//Create Multipart Request
var formContent = new MultipartFormDataContent();
formContent.Add(new StringContent(requestMode.FilePath), "FilePath");
formContent.Add(new StreamContent(new MemoryStream(requestMode.MyByteData)), "MyByteData", requestMode.FileName);
var response = await client2.PostAsync("http://localhost:5094/UploadFiles", formContent);
}
Output:
Related
I am trying to send parameters & file in Request Body with Origin Request Header C# Console / Asp.Net (Web Form) Web Application.
I have looked around many examples but I didn't get proper solutions.
I've tried with the following code which is almost working. The only issue with couldn't get any solution to send the file in Request Body.
public class requestObj
{
public string langType { get; set; }
}
protected void CreateUser_Click(object sender, EventArgs e)
{
try
{
var requestObj = new requestObj
{
langType = "aaa"
};
var client = new RestSharp.RestClient(url);
client.Timeout = -1;
var request = new RestSharp.RestRequest(RestSharp.Method.POST);
request.AddHeader("Origin", "http://localhost:8080");
request.AddJsonBody(requestObj);
var response = client.Execute(request);
}
catch (Exception ex)
{
throw ex;
}
}
Thanks,
I have made it working following ways,
string url = requestUrl;
string filePath = #"F:\text.txt";
var client = new RestSharp.RestClient(url);
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Origin", "http://localhost:2020");
request.AddParameter("parameter", "parameterValue");
request.AddFile("file", filePath, "text/plain"); //file parameter.
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
I'm trying to POST data to a WebService with SSL Certification.
It's working fine in Emulator but the Device is keeping stuck on GetResponseAsync(). I tried it with HttpClient with and without ModernHttpClient-Library but it stuck on PostAsync(), so it doesn't work too.
One Solution i tried of another Thread is just to add
System.Net.ServicePointManager.ServerCertificateValidationCallback +=
(sender, cert, chain, sslPolicyErrors) => true;
^but it's also not working
In Manifest i added Permissions for Internet.
Thats the Code with GetResponseAsync()
public async Task<Response<V>> CallWebServiceAsync<T, V>(string ticket, string url, T requestData)
{
try
{
var request = new Request<T>
{
Ticket = ticket,
Data = requestData
};
DataContractJsonSerializer serializer = new DataContractJsonSerializer(request.GetType(), this._knownTypes);
var httpRequest = WebRequest.CreateHttp(url);
httpRequest.Method = "POST";
httpRequest.UseDefaultCredentials = true;
httpRequest.ContentType = "application/json";
var requestStream = await httpRequest.GetRequestStreamAsync().ConfigureAwait(false);
serializer.WriteObject(requestStream, request);
var response = await httpRequest.GetResponseAsync().ConfigureAwait(false);
var resultStream = response.GetResponseStream();
if (resultStream == null)
{
throw new FailedWebServiceInteractionException($"Got no response stream from request. URL:{url}");
}
var jsonResponseSerializer = new DataContractJsonSerializer(typeof(Response<V>), this._knownTypes);
Response<V> result = (Response<V>)jsonResponseSerializer.ReadObject(resultStream);
resultStream.Dispose();
return result;
}
catch (Exception e)
{
throw new FailedWebServiceInteractionException("Deserialization from json response failed", e);
}
}
Code with PostAsync() (+- ModernHttpClient)
public async Task<Response<V>> CallWebServiceAsync<T, V>(string ticket, string url, T requestData)
{
try
{
var request = new Request<T>
{
Ticket = ticket,
Data = requestData
};
var httpClientHandler = new NativeMessageHandler
{
UseDefaultCredentials = true
};
var httpRequest = new HttpClient(httpClientHandler)
{
BaseAddress = new Uri(url)
};
httpRequest.DefaultRequestHeaders.Accept.Clear();
httpRequest.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var content = JsonConvert.SerializeObject(request);
var response =
await
httpRequest.PostAsync(url, new StringContent(content, Encoding.UTF8, "application/json"))
.ConfigureAwait(false);
var jsonString = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
return JsonConvert.DeserializeObject<Response<V>>(jsonString);
}
catch (Exception e)
{
throw new FailedWebServiceInteractionException("Deserialization from json response failed", e);
}
}
I don't know if the certificates are the problem or something else.
They're not self-signed.
I found a solution. Time is gone since then. I don't know the exact solution but here is my code that works fine now:
var request = new Request<T>
{
Ticket = ticket,
Data = requestData
};
var httpClientHandler = new OkHttpClientHandler
{
UseDefaultCredentials = true,
AllowAutoRedirect = true,
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
ClientCertificateOptions = ClientCertificateOption.Automatic
};
var client = new HttpClient(httpClientHandler)
{
BaseAddress = new Uri(url),
Timeout = TimeSpan.FromSeconds(15)
};
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var jsonRequest = this.SerializeToJson(request);
var compressedRequest = StringCompressor.CompressString(jsonRequest);
var httpRequest = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = new ByteArrayContent(compressedRequest)
{
Headers = {ContentType = new MediaTypeHeaderValue("application/json")}
}
};
var httpResponse = await client.SendAsync(httpRequest, cancellationToken).ConfigureAwait(false);
client.Dispose();
httpResponse.EnsureSuccessStatusCode();
var compressedResponse = await httpResponse.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
httpResponse.Dispose();
var jsonResponse = StringCompressor.DecompressString(compressedResponse);
var jsonResponseSerializer = new DataContractJsonSerializer(typeof(Response<V>), this._knownTypes);
Response<V> result;
using (var jsonResponseStream = this.GenerateStreamFromString(jsonResponse))
{
result = (Response<V>) jsonResponseSerializer.ReadObject(jsonResponseStream);
}
return result;
I'm using a self compiled wrapper of OkHttpClient library. I think ModernHttpClient (it is referencing OkHttp too) works too. Someone needs to test it.
Important to know is any other project that references this project need the library too.
App.Base Project - Implemented the above code to connect to
Webservice
App Project - References to App.Base. Need the library
too.
I have a WebApi self hosted console server over SSL.
The server takes care of creating the SSL certificates, adding them to the certificate store and binds the certificate to the port using netsh all on the fly.
The server has a simple controller that returns the string "Hello World" through HTTP GET.
I can access it through the browser without any problems and I am quite certain there is nothing wrong with the server code so I am only going to post the troubled client code here.
private static string url = #"https://localhost:4443/WebApi/Service/HelloWorld;
private static async Task GetHelloWorldRequest(string url)
{
using (HttpClient httpClient = new HttpClient(GetSSLHandler()))
{
HttpRequestMessage request = new HttpRequestMessage();
request.Method = HttpMethod.Get;
request.RequestUri = new Uri(url);
await httpClient
.SendAsync(request)
.ContinueWith((response)
=>
{
try
{
ProcessResponse(response);
}
catch (AggregateException agException)
{
throw new Exception("Error getting response: " + agException.Message);
}
}).ConfigureAwait(false);
}
}
private static void ProcessResponse(Task<HttpResponseMessage> response)
{
Console.WriteLine(response.Result.Content.ReadAsStringAsync().Result);
}
private static void ProcessResponseHeaders(Task<HttpResponseMessage> response)
{
Console.WriteLine(response.Result.Headers.ToString());
}
private static WebRequestHandler GetSSLHandler()
{
WebRequestHandler handler = new WebRequestHandler();
X509Certificate2 certificate = GetMyX509Certificate();
handler.ClientCertificates.Add(certificate);
return handler;
}
Now in my main routine I simply call this:
Console.WriteLine("Response headers:");
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
Task task = GetHelloWorldRequest(url);
task.Wait();
Now my problem is if I try to read the response content which should give me "Hello World" it gives me an empty string instead.
So I tried looking at the response headers and this is what I get:
It seems to be it is going through the negotiation phase and I don't know what to do from here.
Please advice. Thank you in advance.
EDIT:
Sorry the problem is with the server code. Simply uncomment the section calling httpBinding.ConfigureTransportBindingElement.
class SslHttpsSelfHostConfiguration : HttpSelfHostConfiguration
{
public SslHttpsSelfHostConfiguration(string baseAddress) : base(baseAddress) { }
public SslHttpsSelfHostConfiguration(Uri baseAddress) : base(baseAddress) { }
protected override BindingParameterCollection OnConfigureBinding(HttpBinding httpBinding)
{
httpBinding.Security.Mode = HttpBindingSecurityMode.Transport;
/*
httpBinding.ConfigureTransportBindingElement = (element =>
element.AuthenticationScheme =
AuthenticationSchemes.Negotiate);
*/
return base.OnConfigureBinding(httpBinding);
}
}
Please try running this:
var client = new HttpClient
{
BaseAddress = new Uri("https://localhost:4443/")
};
var result = await client.GetAsync("WebApi/Service/HelloWorld").ConfigureAwait(false);
var data = await result.Content.ReadAsStringAsync().ConfigureAwait(false);
return data;
as your Request task.
And try changing the
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
to
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
I am building a mobile app using xamarin while the server is hosted in azure. I am uploading images in the following way:
Client:
public static async Task<string> UploadImage (string url, byte[] imageData)
{
var content = new MultipartFormDataContent();
var fileContent = new ByteArrayContent(imageData);
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = Guid.NewGuid() + ".Png"
};
content.Add(fileContent);
using (var client = new HttpClient())
{
try
{
HttpResponseMessage msg = await client.PutAsync (url, content);
if(msg.StatusCode == System.Net.HttpStatusCode.OK)
{
return msg.Headers.GetValues ("ImageUrl").First();
}
return string.Empty;
}
catch (Exception ex)
{
return string.Empty;
}
}
}
and here is the server code:
[HttpPut]
public async Task<HttpResponseMessage> PostNewDishImage(string imageID)
{
try
{
_dishImagescontainer = BlobStorageHandler.GetContainer("dishuserimages");
if (!Request.Content.IsMimeMultipartContent("form-data"))
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.UnsupportedMediaType));
}
var provider = new BlobStorageProvider(_dishImagescontainer);
await Request.Content.ReadAsMultipartAsync(provider);
IList<string> urls = provider.Urls;
if (urls.Count > 0)
{
var response = new HttpResponseMessage();
response.StatusCode = HttpStatusCode.OK;
response.Headers.Add("ImageUrl", urls[0]);
return response;
}
return new HttpResponseMessage(HttpStatusCode.InternalServerError);
}
catch (System.Exception e)
{
return new HttpResponseMessage(HttpStatusCode.InternalServerError) { ReasonPhrase = e.ToString() };
}
}
It works fine but I don't like the way I am returning the new imageurl back to the client (through the http headers) I have tried some other ways but this is the best one so far :)
Does anyone have any better ideas?
Thanks
Returning data to the client in an HTTP header like that does have a bit of a smell. How about returning a DTO serialized to JSON?
An example DTO class:
public class ImageUploadResponse
{
public string Url { get; set; }
}
Then change your server side code to something like this:
var responseDto = new ImageUploadResponse { Url = urls[0] };
var response = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(JsonConvert.SerializeObject(responseDto),
Encoding.UTF8, "application/json")
};
which will send the results back to the client in the content of the HTTP response as JSON. Then the client can parse the JSON into an object (or not) as you see fit. This approach will also be more friendly to making such a call from JavaScript in the future if you desire because the result is standard JSON.
I'm trying to call Paypal api from my code. I set up the sandbox account and it works when I use curl but my code isn't working the same way, returning 401 Unauthorized instead.
Here's the curl command as documented by Paypal
curl https://api.sandbox.paypal.com/v1/oauth2/token -H "Accept: application/json" -H "Accept-Language: en_US" -u "A****:E****" -d "grant_type=client_credentials"
UPDATE: Apparently the .Credentials doesn't do the trick, instead setting Authorization header manually works (see code)
Here's the code (trimmed to its essence):
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("https://api.sandbox.paypal.com/v1/oauth2/token");
request.Method = "POST";
request.Accept = "application/json";
request.Headers.Add("Accept-Language:en_US")
// this doesn't work:
**request.Credentials = new NetworkCredential("A****", "E****");**
// DO THIS INSTEAD
**string authInfo = Convert.ToBase64String(System.Text.Encoding.Default.GetBytes("A****:E****"));**
**request.Headers["Authorization"] = "Basic " + authInfo;**
using (StreamWriter swt = new StreamWriter(request.GetRequestStream()))
{
swt.Write("grant_type=client_credentials");
}
request.BeginGetResponse((r) =>
{
try
{
HttpWebResponse response = request.EndGetResponse(r) as HttpWebResponse; // Exception here
....
} catch (Exception x) { .... } // log the exception - 401 Unauthorized
}, null);
This is the request from code captured by Fiddler (raw), there are no authorization parameters for some reason:
POST https://api.sandbox.paypal.com/v1/oauth2/token HTTP/1.1
Accept: application/json
Accept-Language: en_US
Host: api.sandbox.paypal.com
Content-Length: 29
Expect: 100-continue
Connection: Keep-Alive
grant_type=client_credentials
Hoping the following code help to anyone who is still looking for a good piece of cake to get connected to PayPal.
As many people, I've been investing a lot of time trying to get my PayPal token access without success, until I found the following:
public class PayPalClient
{
public async Task RequestPayPalToken()
{
// Discussion about SSL secure channel
// http://stackoverflow.com/questions/32994464/could-not-create-ssl-tls-secure-channel-despite-setting-servercertificatevalida
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
try
{
// ClientId of your Paypal app API
string APIClientId = "**_[your_API_Client_Id]_**";
// secret key of you Paypal app API
string APISecret = "**_[your_API_secret]_**";
using (var client = new System.Net.Http.HttpClient())
{
var byteArray = Encoding.UTF8.GetBytes(APIClientId + ":" + APISecret);
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
var url = new Uri("https://api.sandbox.paypal.com/v1/oauth2/token", UriKind.Absolute);
client.DefaultRequestHeaders.IfModifiedSince = DateTime.UtcNow;
var requestParams = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("grant_type", "client_credentials")
};
var content = new FormUrlEncodedContent(requestParams);
var webresponse = await client.PostAsync(url, content);
var jsonString = await webresponse.Content.ReadAsStringAsync();
// response will deserialized using Jsonconver
var payPalTokenModel = JsonConvert.DeserializeObject<PayPalTokenModel>(jsonString);
}
}
catch (System.Exception ex)
{
//TODO: Log connection error
}
}
}
public class PayPalTokenModel
{
public string scope { get; set; }
public string nonce { get; set; }
public string access_token { get; set; }
public string token_type { get; set; }
public string app_id { get; set; }
public int expires_in { get; set; }
}
This code works pretty well for me, hoping for you too. The credits belong to Patel Harshal who posted his solution here.
This Works using HttpClient...
'RequestT' is a generic for the PayPal request arguments, however it is not used. The 'ResponseT' is used and it is the response from PayPal according to their documentation.
'PayPalConfig' class reads the clientid and secret from the web.config file using ConfigurationManager.
The thing to remember is to set the Authorization header to "Basic" NOT "Bearer" and if and to properly construct the 'StringContent' object with right media type (x-www-form-urlencoded).
//gets PayPal accessToken
public async Task<ResponseT> InvokePostAsync<RequestT, ResponseT>(RequestT request, string actionUrl)
{
ResponseT result;
// 'HTTP Basic Auth Post' <http://stackoverflow.com/questions/21066622/how-to-send-a-http-basic-auth-post>
string clientId = PayPalConfig.clientId;
string secret = PayPalConfig.clientSecret;
string oAuthCredentials = Convert.ToBase64String(Encoding.Default.GetBytes(clientId + ":" + secret));
//base uri to PayPAl 'live' or 'stage' based on 'productionMode'
string uriString = PayPalConfig.endpoint(PayPalConfig.productionMode) + actionUrl;
HttpClient client = new HttpClient();
//construct request message
var h_request = new HttpRequestMessage(HttpMethod.Post, uriString);
h_request.Headers.Authorization = new AuthenticationHeaderValue("Basic", oAuthCredentials);
h_request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
h_request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue("en_US"));
h_request.Content = new StringContent("grant_type=client_credentials", UTF8Encoding.UTF8, "application/x-www-form-urlencoded");
try
{
HttpResponseMessage response = await client.SendAsync(h_request);
//if call failed ErrorResponse created...simple class with response properties
if (!response.IsSuccessStatusCode)
{
var error = await response.Content.ReadAsStringAsync();
ErrorResponse errResp = JsonConvert.DeserializeObject<ErrorResponse>(error);
throw new PayPalException { error_name = errResp.name, details = errResp.details, message = errResp.message };
}
var success = await response.Content.ReadAsStringAsync();
result = JsonConvert.DeserializeObject<ResponseT>(success);
}
catch (Exception)
{
throw new HttpRequestException("Request to PayPal Service failed.");
}
return result;
}
IMPORTANT: use Task.WhenAll() to ensure you have a result.
// gets access token with HttpClient call..and ensures there is a Result before continuing
// so you don't try to pass an empty or failed token.
public async Task<TokenResponse> AuthorizeAsync(TokenRequest req)
{
TokenResponse response;
try
{
var task = new PayPalHttpClient().InvokePostAsync<TokenRequest, TokenResponse>(req, req.actionUrl);
await Task.WhenAll(task);
response = task.Result;
}
catch (PayPalException ex)
{
response = new TokenResponse { access_token = "error", Error = ex };
}
return response;
}
Paypal has deprecated TLS 1.1, and only accepts 1.2 now. Unfortunately .NET (prior to version 4.7) uses 1.1 by default, unless you configure it otherwise.
You can turn on TLS 1.2 with this line. I recomend placing it Application_Start or global.asax.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
I too suffered from a lack of example code and various issues with response errors and codes.
I am a big fan of RestClient as it helps a lot with integrations and the growing number of RESTful API calls.
I hope this small snippet of code using RestSharp helps someone: -
if (ServicePointManager.SecurityProtocol != SecurityProtocolType.Tls12) ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; // forced to modern day SSL protocols
var client = new RestClient(payPalUrl) { Encoding = Encoding.UTF8 };
var authRequest = new RestRequest("oauth2/token", Method.POST) {RequestFormat = DataFormat.Json};
client.Authenticator = new HttpBasicAuthenticator(clientId, secret);
authRequest.AddParameter("grant_type","client_credentials");
var authResponse = client.Execute(authRequest);
// You can now deserialise the response to get the token as per the answer from #ryuzaki
var payPalTokenModel = JsonConvert.DeserializeObject<PayPalTokenModel>(authResponse.Content);