使用 HttpClient PostAsync 資料時,要記得 Encode 哦!

最近將 Chatbot 透過 Webchat 的方式給公司同仁使用,在使用之前都需要透過登入可以使用請假或是訂會議室的功能。

其中有一位同事就是登入不進去,但是其他人卻沒有這個問題。於是看錯誤訊息,的確是密碼驗證不過。再詢問他的密碼是否有特別的字元,他回答其中有 “&" 這個字。

再看一下同事 Alice 寫的程式中,透過 HttpClient 去 Post 資料時,使用的是 StringContent ,將各別的欄位透過 & 去串接,內容如下,


var userInfo = "grant_type=password&username=" + usrname + "&password=" + pwd;
var postContent = new StringContent(userInfo);
var response = client.PostAsync(tokenUrl, postContent).Result;

謎題解開了,因為密碼中有 & ,而程式碼又沒加以 Encode ,所以就造成了密碼錯誤的問題。

解法就是 Encode ,

1.使用 UrlEncode 去包每個參數,如下,

var userInfo = "grant_type=password&username=" + HttpUtility.UrlEncode(usrname) + "&password=" + HttpUtility.UrlEncode(pwd);
var postContent = new StringContent(userInfo);
var response = client.PostAsync(tokenUrl, postContent).Result;

2.使用 FormUrlEncodedContent ,這樣裡面的值,它會幫我們 Encode ,如下,

var formContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair("grant_type", "password"),
new KeyValuePair("username", usrname),
new KeyValuePair("password", pwd)
});
var response = client.PostAsync(tokenUrl, formContent).Result;

註: PostAsync , ReadAsStringAsync 您也可以使用 async/await 方式哦!

.NET Call Java WebService Problem

有朋友詢問透過 .NET Call Java 的 WebService ,WSDL定義中,它的回傳值是一個物件的陣列,如下,

public myObj[] getMyObj(string token) {
object[] results = this.Invoke("getMyObj", new object[] {token});
return ((myObj[])(results[0]));
}

可是透過 .NET 去 Call 回傳的物件裡面,屬性卻都是 Null 。

透過 Fiddler 去錄資料確實有傳回來呀 ~~
猜想有可能是在轉成我們的物件時,轉不過來。
於是將 Reference.cs 中轉成程式改成轉成 object[] 的方式,如下,

public object[] getMyObj(string token) {
object[] results = this.Invoke("getMyObj", new object[] {token});
return ((object[])(results[0]));
}

再執行一次程式,裡面就有一堆 xmlNode[] 的資料傳回來,如下,

xmlnodes.png

即然只是無法轉成我們的物件,就自已將 xmlNode[] 透過 Reflection 的方式,轉成我們的物件即如,如下,
var results = new List();
var Lics = ws.getMyObj(t);
foreach (object[] lic in Lics)
{
//lic 是一堆的 xmlNode array
var result = new myObj();
var licArray = lic as XmlNode[];
foreach (var node in licArray)
{
var propName = node.Name;
var propertyInfo = result.GetType().GetProperty(propName);
var pt = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType;
object safeValue = (node.InnerText == null) ? null : Convert.ChangeType(node.InnerText, pt);
propertyInfo.SetValue(result, safeValue, null);
}
results.Add(result);
}

註:加入「服務參考」的方式為,
1.「加入服務參考」畫面按最下面的「進階(V)」按鈕
2.「服務參考設定」畫面按最下面的「加入Web參考(W)」按鈕
3.「加入Web參考」畫面,URL(U)欄位輸入 WSDL 的 URL,並按下右邊的箭頭按鈕
4.「加入Web參考」畫面,調整 「Web參考名稱(N)」,並按下「加入參考」按鈕
ws.png