jQuery能做到,PHP能做到,C#也能做到


題目有些大,但文中談到的問題很小;看似表揚C#,實際不是。

這個小問題來自這樣的應用場景——以HTTP POST的方式調用第三方API,第三方API不支持JSON傳參,只能通過URL query string方式傳參(a=1&b=2)。

假設API的地址是http://www.cnblogs.com/api/say,需要傳遞的參數是username與words,只支持HTTP POST調用。

另外,加一個約束條件——不允許用字符串拼接,比如:"username="+username+"&words="+words;

jQuery中的調用示例代碼

var postData = {
    username: 'test',
    words: 'hello world'
};
$.ajax({
    url: 'http://www.cnblogs.com/api/say',
    data: postData,
    type: 'post',            
});

在上面的Javascript代碼執行時,jQuery會自動將js對象postData轉換為Url query string的形式(username=test&words=hello+world),並自動進行Url encode。

PHP中的調用示例代碼

$url = 'http://www.cnblogs.com/api/say';
$data = array('username' => 'test',
              'words'    => 'hello world');

$data = http_build_query($data);
 
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 
$response = curl_exec($ch);
curl_close($ch);

PHP內置的http_build_query()函數能自動將數組轉換為Url query string的形式(username=test&words=hello+world),並自動進行Url encode。

C#中的調用示例代碼

1、在.NET Framework 4.0中的實現(HttpWebRequest+匿名類型+反射+LINQ)

參數通過匿名類型(Anonymous Type)進行定義:

var postData = new
{
    username = "test",
    words = "hello world"
};

.NET Framework 4.0的類庫中沒有提供直接將“匿名類型實例”轉換為“Url查詢參數”的API,只能借助“反射+LINQ”自己實現。實現代碼如下:

static void Main(string[] args)
{
    var url = "http://www.cnblogs.com/api/say";

    var postData = new
    {
        username = "test",
        words = "hello world"
    };

    var webRequest = WebRequest.Create(url) as HttpWebRequest;
    webRequest.Method = "post";
    webRequest.ContentType = "application/x-www-form-urlencoded";

    var queryString = string.Join("&",
                        from p in postData.GetType().GetProperties()
                        select p.Name + "=" + HttpUtility.UrlEncode(p.GetValue(postData, null).ToString()));

    using (var sw = new StreamWriter(webRequest.GetRequestStream()))
    {
        sw.Write(queryString);
    }

    using (var response = webRequest.GetResponse())
    {
        using (var sr = new StreamReader(response.GetResponseStream()))
        {
            Console.WriteLine(sr.ReadToEnd());
        }
    }
}

2、在.NET Framework 4.5中的實現(HttpClient+FormUrlEncodedContent)

.NET Framework 4.5考慮到了這個應用場景,提供了FormUrlEncodedContent,但它不支持匿名類型(Anonymous Type),只支持字典(Dictionary)。參數需要這樣定義:

var postData = new Dictionary<string, string>
{
    { "username", "test" },
    { "words", "hello world" }
};

完整實現代碼如下(需要引用System.Net.Http):

static void Main(string[] args)
{
    var url = "http://www.cnblogs.com/api/say";

    var postData = new Dictionary<string, string>
    {
        { "username", "test" },
        { "words", "hello world" }
    };

    var urlEncodedContent = new FormUrlEncodedContent(postData);
    var httpClient = new HttpClient();
    var result = httpClient.PostAsync(url, urlEncodedContent).Result.Content.ReadAsStringAsync().Result;
    Console.WriteLine(result);
}

.NET Framework 4.5中的實現還算簡單,但是FormUrlEncodedContent只支持Dictionary,考慮還是不周到。

感想

.NET因互聯網而生,而通過URL query string傳參的需求在互聯網應用中普通存在,但.NET從4.5才開始考慮這個應用場景,實在有點說不過去。

多數開發互聯網應用多年的.NET開發者都有多年拼接字符串的經歷,但是.NET也沒考慮到這個場景,比如雙引號問題(字符串不支持單引號內直接包含雙引號)。即使拼接字符串,也沒有Javascript與PHP中操作方便。

.NET功能強大、設計領先,但是對互聯網應用場景缺少細致入微的考慮,在用.NET開發互聯網應用時經常有殺雞用牛刀的感覺。幸虧牛刀上有非常舒服的刀柄(Visual Studio),才吸引了如些多的開發者。如果互聯網應用是未來,即使刀柄再舒服,用牛刀殺雞的感覺畢竟不好,牛刀自身的改變才是解決之道。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM