我來自iOS(Swift)背景。在我的一個Swift應用程序中,我有這個調用API的類。我試圖將它移植到C#(Windows Form應用程序),但我遇到了一些障礙。首先是Swift代碼。沒有什麼花哨。一種方法是POST請求登錄到API,另一個函數執行GET方法來檢索用戶配置文件的JSON響應。這兩種方法都是異步的。異步調用API並解析JSON
import Foundation
class API {
private let session = NSURLSession.sharedSession()
private let baseURL = "https://www.example.com/api/"
func login(userID userID: String, password: String, completion: (error: NSError?) ->()) {
let url = NSURL(string: baseURL + "login")!
let params = ["username": userID, "password": password]
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
request.encodeParameters(params) // encodeParameters is an extension method
session.dataTaskWithRequest(request, completionHandler: { data, response, error in
if let httpResponse = response as? NSHTTPURLResponse {
if httpResponse.statusCode != 200 {
completion(error: error)
} else {
completion(error: nil)
}
}
}).resume()
}
func fetchUser(completion: (user: User?, error: NSError?) ->()) {
let url = NSURL(string: baseURL + "profile")!
let request = NSURLRequest(URL: url)
session.dataTaskWithRequest(request, completionHandler: { data, response, error in
if let error = error {
completion(user: nil, error: error)
} else {
// Parsing JSON
var jsonDict = [String: AnyObject]()
do {
jsonDict = try NSJSONSerialization.JSONObjectWithData(data, options: []) as! [String: AnyObject]
} catch {
print("Error occurred parsing data: \(error)")
completion(user: nil, error: error)
}
let user = User()
user.name = jsonDict["name"] as! String
user.age = jsonDict["age"] as! Int
completion(user: user, error: nil)
}
}).resume()
}
}
這是我的嘗試將其轉換爲C#。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.Http;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Xml.Linq;
using System.Xml.XPath;
namespace MyTrayApp
{
public partial class Form1 : Form
{
private string baseURL = "https://www.example.com/api/";
public Form1()
{
InitializeComponent();
}
private async void Form1_Load(object sender, EventArgs e)
{
await login("myusername", "mypassword");
await fetchUser();
}
async Task login(string userID, string password)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(baseURL);
var parameters = new Dictionary<string, string>
{
{ "username", userID },
{ "password", password }
};
var encodedParameters = new FormUrlEncodedContent(parameters);
var response = await client.PostAsync("login", encodedParameters);
string responseString = await response.Content.ReadAsStringAsync();
//Console.WriteLine(responseString);
}
}
async Task fetchUser()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(baseURL);
var response = await client.GetAsync("profile");
response.EnsureSuccessStatusCode();
var responseString = await response.Content.ReadAsStringAsync();
var jsonReader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(responseString.ToCharArray()), new System.Xml.XmlDictionaryReaderQuotas());
var root = XElement.Load(jsonReader);
Console.WriteLine(root.XPathSelectElement("//name").Value);
//Console.WriteLine(responseString);
}
}
}
}
這些都是我遇到的問題。
- 在我的Swift方法中,它們有完成處理程序。我怎樣才能在C#中做同樣的事情?
- 在Swift中,您會得到一個
NSData
對象,您可以將它傳遞給NSJSONSerialization
以創建JSON對象。在我目前的實現中,我在XElement.Load(jsonReader);
處得到一個XML異常。我不確定這是否是正確的做法。我在這裏發現了大量不同的解決方案。但有些是針對Metro應用程序的,有些針對網絡,這一切都非常令人難以置信。此外,大多數解決方案都使用第三方庫,如JSON.NET。我試圖在沒有第三方庫的情況下實現這一點。
爲了說明Todd說的話,大多數人只是使用JSON.NET作爲事實上的.net解析器。但是,如果第三方依賴關係實際上是阻止者,那麼有些人只是從SimpleJSON內聯源代碼http://simplejson.codeplex.com/SourceControl/latest –
另外,建議重用HttpClient的實例,所以只需聲明它作爲一個領域,並在你完成之後進行處理。這將提供更好的性能,因爲它可以讓您重用HTTP連接。 –