繁体   English   中英

使用HttpClient的C#application / x-www-form-urlencoded OAuth和HTTP REST请求

[英]C# application/x-www-form-urlencoded OAuth and HTTP REST requests using HttpClient

因此,我试图将一些非常简单而优雅的代码示例放在一起,以帮助人们使用我的API。 我要处理的最新语言是C#。

我认为我阅读的IETF OAuth2.0标准暗示HTTP请求Content-Type必须为“ application / x-www-form-urlencoded”。 我拥有的Django API服务器目前似乎仅支持此Content-Type(用于OAuth资源)。 其他语言默认以这种方式发布内容!

经过大量研究和几次实验,我想知道我是否错过了一些基本知识。 肯定会有一种有用的库OR技术来创建... 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的模型。 这将使我们免于对《词典》的使用感到有些困惑。 使用字典然后进行迭代更为通用,不过可能有点OTT。

我认为大多数时候人们会使用JSON,因此显示这种情况是很有用的。

通常,将POCO模型序列化为字符串和/或urlEncoded字符串似乎很困难。

问题

  • OAuth强制使用urlencoded,可以转换服务器端吗?
  • 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);}}

我能够从设备和网络应用调用网址编码器请求。

//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; }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM