从远程服务器向通用Windows应用程序发送推送通知的示例代码?

时间:2017-08-21 10:11:30

标签: c# push-notification win-universal-app windows-10-universal

我正在尝试用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开发人员仪表板中创建的应用。 有人可以帮帮我吗?

1 个答案:

答案 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));