我正在尝试用c#中的小代码写一个推送通知,这里是代码:
public void Launch()
{
string channelUri = "channel uri";
string sid = "sid package";
string secret = "client secret";
// toast notification
var toast = @"<toast><visual><binding template=""ToastText01""><text id=""1"">Hello!</text></binding></visual></toast>";
Console.WriteLine(this.PostToWns(secret, sid, channelUri, toast));
Console.ReadLine();
}
// Post to WNS
public string PostToWns(string secret, string sid, string uri, string xml, string type = "wns/toast")
{
try
{
// You should cache this access token
var accessToken = GetAccessToken(secret, sid);
byte[] contentInBytes = Encoding.UTF8.GetBytes(xml);
HttpWebRequest request = HttpWebRequest.Create(uri) as HttpWebRequest;
request.Method = "POST";
request.Headers.Add("X-WNS-Type", type);
request.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken.AccessToken));
using (Stream requestStream = request.GetRequestStream())
requestStream.Write(contentInBytes, 0, contentInBytes.Length);
using (HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse())
return webResponse.StatusCode.ToString();
}
catch (WebException webException)
{
string exceptionDetails = webException.Response.Headers["WWW-Authenticate"] ?? string.Empty;
if (exceptionDetails.Contains("Token expired"))
{
GetAccessToken(secret, sid);
// Implement a maximum retry policy
return PostToWns(uri, xml, secret, sid, type);
}
else
{
// Log the response
return "EXCEPTION: " + webException.Message;
}
}
catch (Exception ex)
{
return "EXCEPTION: " + ex.Message;
}
}
// Authorization
[DataContract]
public class OAuthToken
{
[DataMember(Name = "access_token")]
public string AccessToken { get; set; }
[DataMember(Name = "token_type")]
public string TokenType { get; set; }
}
private OAuthToken GetOAuthTokenFromJson(string jsonString)
{
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonString)))
{
var ser = new DataContractJsonSerializer(typeof(OAuthToken));
var oAuthToken = (OAuthToken)ser.ReadObject(ms);
return oAuthToken;
}
}
protected OAuthToken GetAccessToken(string secret, string sid)
{
var urlEncodedSecret = HttpUtility.UrlEncode(secret);
var urlEncodedSid = HttpUtility.UrlEncode(sid);
var body = String.Format("grant_type=client_credentials&client_id={0}&client_secret={1}&scope=notify.windows.com",
urlEncodedSid,
urlEncodedSecret);
string response;
using (var client = new WebClient())
{
client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
response = client.UploadString("https://login.live.com/accesstoken.srf", body);
}
return GetOAuthTokenFromJson(response);
}
其中channelUri,sid和secret是我之前获得的固定变量。问题是远程服务器返回400错误(错误请求),但我不知道为什么。频道创建成功,我遵循本指南:https://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh868221.aspx和sid和秘密变量是指先前在Microsoft开发人员仪表板中创建的应用。 有人可以帮帮我吗?
答案 0 :(得分:0)
HTTP 400 error
表示错误请求,这意味着由于语法格式错误,服务器无法理解请求。换句话说,客户发送的请求并不遵循服务器的规则。
所有推送通知中必须包含四个必需的标头: X-WNS-Type ,内容类型,内容长度,和授权。
使用HttpWebResponse
时,它应该能够自动为您设置内容长度,但您仍需要手动设置内容类型。对于toast,tile和badge通知,此标头必须设置为&#34; text / xml&#34; 。有关详细信息,请参阅Send notification request。
HttpWebRequest request = HttpWebRequest.Create(uri) as HttpWebRequest;
request.Method = "POST";
request.Headers.Add("X-WNS-Type", type);
request.ContentType = "text/xml";
request.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken.AccessToken));