使用HttpClient的c# application/x-www-form-urlencoded OAuth和HTTP
本文关键字:x-www-form-urlencoded OAuth HTTP application HttpClient 使用 | 更新日期: 2023-09-27 18:16:53
所以我试图把一些非常简单和优雅的代码样本放在一起,以帮助人们使用我的API。我正在学习的最新语言是c#。
我认为我读到的IETF OAuth2.0标准意味着HTTP请求的Content-Type必须是"application/x-www-form-urlencoded"。我使用的Django API服务器目前似乎只支持这种Content-Type(用于OAuth资源)。其他语言默认情况下以这种方式发布内容!
经过广泛的研究和几次实验后,我想知道我是否错过了一些基本的东西。肯定会有一个有用的库或技术来创建…urlencoded字符串或至少有人必须遇到这个??
我将在下面列出我目前为止的一些最佳解决方案,但这似乎是错误的。
也从一堆互联网浏览,我认为我会使用HttpClient库。我喜欢它使用异步模型的事实,这可能对任何使用WPF或XAML或Windows 8应用程序的开发人员更有用。它也适用于控制台和表单。
我使用Newtonsoft Json。序列化的。Net库。首先,我创建一个授权字符串的POCO。然后我将其序列化为JSON,然后是键/值对,然后迭代键/值对,使用所需的'='和'&'字符,然后是UTF-8,然后转义空格等。
//Setup HTTP request
HttpClient httpRequest = new HttpClient();
httpRequest.DefaultRequestHeaders.Add("Accept", "application/json");
string urlBase = "https://__secret__/api/v1/";
HttpResponseMessage msg = new HttpResponseMessage();
//POST to oauth to get token (must be sent as "application/x-www-form-urlencoded")
OAuthConfig oAuthCredentials = new OAuthConfig { client_id = client_id, client_secret = secret, username = "__secret__", password = "__secret__", grant_type = "__secret__" };
string jsonString = JsonConvert.SerializeObject(oAuthCredentials); //convert to JSON
Dictionary<string, string> values = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonString); //convert to key/value pairs
string urlEncodedData = ConvertToFormUrlEncodedFormat(values);
HttpContent payload = new StringContent(urlEncodedData, Encoding.UTF8, "application/x-www-form-urlencoded");
msg = httpRequest.PostAsync(urlBase + "oauth/access_token/", payload).Result;
string responseBodyAsText = msg.Content.ReadAsStringAsync().Result;
Console.WriteLine(responseBodyAsText);
我能想到的其他选项是…
反射,然而在代码示例中深入研究反射似乎有点狂躁。
事实证明,除了OAuth设置之外,API的其余部分都支持JSON类型的post。所以我想我可以写一个函数来遍历oAuthConfig模型并生成一个字符串,因为POCO模型不太可能改变,并且是唯一需要我可以预期的urlEncoding的模型。这样我们就不会对词典的用法感到困惑了。使用字典然后迭代是更通用的,但可能有点太过了。
我想大多数时候人们会使用JSON,所以展示这可能是有用的。
一般来说,将POCO模型序列化为字符串和/或urlEncoded字符串似乎相当困难。
问题- OAuth授权url编码,你可以转换服务器端吗?
- 是HttpClient的最佳选择,异步重要吗?
- 有一个更好的更简单的方法来序列化POCO到…form-urlencoded?
感谢您的宝贵意见。
var model = new LoginModel { Username = "patient@gmail.com", Password = "123456", DeviceId = "123456789", RoleId = 1 };
url.Append("/Login");
string data = JsonConvert.SerializeObject(model);// "{'"username'":'"dscdemo0@gmail.com'",'"password'":'"vipin123'"}";
NameValueCollection inputs = new NameValueCollection();
inputs.Add("json", data);
WebClient client = new WebClient();
var reply = client.UploadValues(url.ToString(), inputs);
string temp = Encoding.ASCII.GetString(reply);
var result = JsonConvert.DeserializeObject<MessageTemplateModel>
(temp);
Api调用
public async Task<IHttpActionResult> Login(HttpRequestMessage request)//(LoginModel modelN)
{
try
{
var form = request.Content.ReadAsFormDataAsync().Result;
var modelN = JsonConvert.DeserializeObject<LoginModel>(form["json"].ToString());
// token = JsonConvert.DeserializeObject<string>(form["token"].ToString());
bool istoken = _appdevice.GettokenID(modelN.DeviceId);
if (!istoken)
{
statuscode = 0;
message = ErrorMessage.TockenNotvalid;
goto invalidtoken;
}
User model = new User();
// var session = HttpContext.Current.Session;
// session.Add("UserRole", GetProfileId.UserRole);
var user = await _userManager.FindAsync(modelN.Username, modelN.Password);}}
我可以从设备和web应用程序调用url编码器请求。
//I disclaimer everything and note that I haven't re-checked if this posted code works.
using System;
using System.Text;
using System.Collections.Generic;
using Newtonsoft.Json; //install with Nuget package installer- "json.Net"
using System.Net.Http; //install with Nuget package installer- "...Web API client libraries"
using System.Net;
using System.IO;
using System.Runtime.Serialization.Json; //security risk till certificate fixed
namespace CSharpDemoCodeConsole
{
class Program
{
const string api_key = "your_api_key"; //set your api_key here
const string user_auth = "your_username" + ":" + "your_password"; // set your user credentials here
const string urlBase = "https://@SECRET.com@/api/v1";
static void Main(string[] args)
{
Console.WriteLine("Making call to webserver asynchronously");
MakeCallAsynchronously();
Console.WriteLine("**************************************");
Console.WriteLine("Making call to webserver synchronously");
MakeCallSynchronously();
Console.WriteLine("**************************************");
Console.WriteLine("Making call to webserver synchronously without Newtonsoft serialization");
MakeCallSynchronouslyWithoutNewtonSoft();
Console.WriteLine("Press spacebar to close the application");
Console.ReadKey();
}
private static void MakeCallAsynchronously()
{
//Always accept untrusted certificates - don't use in production
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
//Setup request
string authorizeString = Convert.ToBase64String(Encoding.ASCII.GetBytes(user_auth));
HttpClient httpRequest = new HttpClient();
httpRequest.DefaultRequestHeaders.Add("Authorization", "Basic " + authorizeString);
httpRequest.DefaultRequestHeaders.Add("Accept", "application/json");
//GET from places resource
try
{
var requestTask = httpRequest.GetAsync(urlBase + "places/" + "?api_key=" + api_key,
System.Net.Http.HttpCompletionOption.ResponseContentRead);
//Update UI while waiting for task to complete
while (requestTask.Status != System.Threading.Tasks.TaskStatus.RanToCompletion)
{
Console.Write(".");
System.Threading.Thread.Sleep(30);
}
if (requestTask.Result.StatusCode != HttpStatusCode.OK)
{
Console.WriteLine("Unexpected response from server: {0}", requestTask.Result);
return;
}
var places = JsonConvert.DeserializeObject<Page<Place>>(requestTask.Result.Content.ReadAsStringAsync().Result);
Console.WriteLine("GET places response " + requestTask.Result.Content.ReadAsStringAsync().Result);
}
catch (WebException ex)
{
Console.WriteLine(ex.ToString());
return;
}
//POST to places resource
try
{
string jsonString = JsonConvert.SerializeObject(new Place { name = "test place", latitude = 0, longitude = 0 });
HttpContent payload = new StringContent(jsonString, Encoding.UTF8, "application/json");
var requestTask = httpRequest.PostAsync(urlBase + "places/" + "?api_key=" + api_key, payload);
//Update UI while waiting for task to complete
while (requestTask.Status != System.Threading.Tasks.TaskStatus.RanToCompletion)
{
Console.Write(".");
System.Threading.Thread.Sleep(30);
}
if (requestTask.Result.StatusCode != HttpStatusCode.Created)
{
Console.WriteLine("Unexpected response from server: {0}", requestTask.Result);
return;
}
Console.WriteLine("POST places response " + requestTask.Result.Content.ReadAsStringAsync().Result);
}
catch (WebException ex)
{
Console.WriteLine(ex.ToString());
return;
}
}
private static void MakeCallSynchronously()
{
//Always accept untrusted certificates - don't use in production
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
//Setup Request
string authorizeString = Convert.ToBase64String(Encoding.ASCII.GetBytes(user_auth));
var client = new WebClient();
client.Headers.Add("Authorization", "Basic " + authorizeString);
client.Headers.Add("Accept", "application/json");
//GET from places resource
try
{
var responseStream = client.OpenRead(urlBase + "places/" + "?api_key=" + api_key);
var response = (new StreamReader(responseStream).ReadToEnd());
var places = JsonConvert.DeserializeObject<Page<Place>>(response);
Console.WriteLine("GET places response " + response);
}
catch (WebException ex)
{
Console.WriteLine(ex.ToString());
}
//POST to places resource
try
{
client.Headers.Add("Accept", "application/json");
client.Headers.Add("Content-Type", "application/json");
string jsonString = JsonConvert.SerializeObject(new Place { name = "test place", latitude = 0, longitude = 0 });
client.Encoding = System.Text.Encoding.UTF8;
string response = client.UploadString(urlBase + "places/" + "?api_key=" + api_key, jsonString);
Console.WriteLine("POST places response " + response);
}
catch (WebException ex)
{
Console.WriteLine(ex.ToString());
return;
}
}
private static void MakeCallSynchronouslyWithoutNewtonSoft()
{
//Always accept untrusted certificates - don't use in production
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
//Setup Request
string authorizeString = Convert.ToBase64String(Encoding.ASCII.GetBytes(user_auth));
var client = new WebClient();
client.Headers.Add("Authorization", "Basic " + authorizeString);
client.Headers.Add("Accept", "application/json");
//GET from places resource
try
{
var responseStream = client.OpenRead(urlBase + "places/" + "?api_key=" + api_key);
MemoryStream ms = new MemoryStream();
responseStream.CopyTo(ms);
ms.Position = 0;
var placesDeserializer = new DataContractJsonSerializer(typeof(Page<Place>));
var places = (Page<Place>)placesDeserializer.ReadObject(ms);
ms.Position = 0;
string response = (new StreamReader(ms).ReadToEnd());
ms.Close();
Console.WriteLine("GET places response " + response);
}
catch (WebException ex)
{
Console.WriteLine(ex.ToString());
return;
}
//POST to places resource
try
{
client.Headers.Add("Accept", "application/json");
client.Headers.Add("Content-Type", "application/json");
DataContractJsonSerializer placesSerializer = new DataContractJsonSerializer(typeof(Place));
Place place = new Place { name = "test place", latitude = 0, longitude = 0 };
MemoryStream ms = new MemoryStream();
placesSerializer.WriteObject(ms, place);
byte[] json = ms.ToArray();
ms.Close();
string jsonString = Encoding.UTF8.GetString(json, 0, json.Length);
client.Encoding = System.Text.Encoding.UTF8;
string response = client.UploadString(urlBase + "places/" + "?api_key=" + api_key, jsonString);
Console.WriteLine("POST places response " + response);
}
catch (WebException ex)
{
Console.WriteLine(ex.ToString());
return;
}
}
}
public class Place
{
[JsonProperty("url")]
public string url { get; set; }
[JsonProperty("name")]
public string name { get; set; }
[JsonProperty("latitude")]
public float latitude { get; set; }
[JsonProperty("longitude")]
public float longitude { get; set; }
}
public class Page<T>
{
[JsonProperty("count")]
public int count { get; set; }
[JsonProperty("next")]
public string next { get; set; }
[JsonProperty("previous")]
public string previous { get; set; }
[JsonProperty("results")]
public List<T> results { get; set; }
}
}