1

所以我试图整理一些非常简单和优雅的代码示例来帮助人们使用我的 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 的模型。这将使我们免于对字典的稍微混乱的使用。使用字典然后迭代更通用,但可能有点 OTT。

我认为大多数时候人们会使用 JSON,所以展示它是如何发生的很有用。

一般来说,将 POCO 模型序列化为字符串和/或 urlEncoded 字符串似乎非常困难。

问题

  • OAuth 要求 urlencoded,你能转换服务器端吗?
  • HttpClient 是最佳选择,异步重要吗?
  • 有没有更好更简单的方法将 POCO 序列化为 ...form-urlencoded?

感谢您提出的任何有用的意见。

4

2 回答 2

1
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);}}

我可以从设备和网络应用程序调用 url-encoder 请求。

于 2015-10-17T06:58:39.420 回答
0
//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; }
    }
}
于 2014-01-30T22:45:00.177 回答