none
Notification Hub Rest API - create Registration Bad Request

    Frage

  • Hallo,

    ich habe ein Cross Platform APP für Android, iOS, Win 8.1 und Win10. Alle melden sich beim selben Notification Hub mit lokalisierbaren Templates an. Jetzt kommt noch eine Mac OS Version dazu, programmiert wird in Xamarin.Mac .NET 4.5 und C#. Da es keine funktionierende SDK für diese Platform gibt, um mich an meinem Notification Hub anzumelden, möchte ich gerne die REST API verwenden. https://msdn.microsoft.com/de-de/library/azure/dn495827.aspx

    Ich kann erfolgreich eine RegistrierungsID erstellen und müsste mich jetzt nur noch am Notification Hub anmelden. https://msdn.microsoft.com/de-de/library/azure/dn223265.aspx

    leider erhalte ich immer die Antwort (400), Ungültiger Anfragetext. Die Registrierung konnte nicht erstellt werden, weil die Anforderung falsch formatiert war.

    hier den Code den ich verwende, der Einfachheit halber ohne Template sondern als einfache Registrierung:

    string payload = @"<?xml version=""1.0"" encoding=""utf-8""?><entry xmlns=""http://www.w3.org/2005/Atom""><content type=""application/xml""><AppleRegistrationDescription xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"" xmlns=""http://schemas.microsoft.com/netservices/2010/10/servicebus/connect""><Tags>myTag</Tags><DeviceToken>ABCDEFGHIJKLMNOPQRSTUVWXYZ</DeviceToken></AppleRegistrationDescription></content></entry>";
    payload = payload.Replace("ABCDEFGHIJKLMNOPQRSTUVWXYZ", deviceToken);
    
    var client = new HttpClient();
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Add("Authorization", SasToken);
    client.DefaultRequestHeaders.Add("Accept", "application/atom+xml");
    client.DefaultRequestHeaders.Add("x-ms-version", "2015-01");
    HttpResponseMessage response = await client.PostAsync("https://" + HUB_NotificationHubNameSapce + ".servicebus.windows.net/" + HUB_NotificationHubPath + "/registrations/?api-version=2015-01", new StringContent(payload, Encoding.UTF8, "application/atom+xml"));

    egal welchen Payload ich verwende, mit oder ohne Template, das Ergebnis bleibt gleich. ich glaube es muss am HTTPClient selbst liegen, irgendwas mache ich da falsch oder es fehlt etwas.

    Samstag, 18. Februar 2017 01:42

Antworten

Alle Antworten

  • Hallo,

    hast Du das mal versucht? Link

    Edit:

    Schau Dir auch mal das an unter Punkt 10 Link Da ist der gesamt Vorgang beschrieben

    Dein Accept ist falsch:

    private const string ContentType = "application/atom+xml;type=entry;charset=utf-8";


    Gruß, Thomas

    Sage nie, ich kann es nicht - sage nur, ich kann es noch nicht!

    Icon für UWP



    Samstag, 18. Februar 2017 03:00
  • Hi,

    danke für die links. habe jetzt eine klasse wie in dem von Dir vorgeschlagenen Link erstellt. Leider bekomme ich immer noch die selbe Antwort, 400 bad Request.

    using System;
    using System.Diagnostics;
    using System.Text;
    using System.Net;
    using System.Security.Cryptography;
    using System.IO;
    using Foundation;
    
    namespace ROIDU
    {
        public class NotificationHub
        {
            private const string ApiVersion = "?api-version=2015-01";
            private const string AuthHeader = "Authorization";
            private const string ContentType = "application/atom+xml;type=entry;charset=utf-8";
    
            static string HubName { get; set; }
            static string ConnectionString { get; set; }
            static string Endpoint { get; set; }
            static string SasKeyName { get; set; }
            static string SasKeyValue { get; set; }
            static string Payload { get; set; }
    
            public NotificationHub(string hubName, string connectionString)
            {
                HubName = hubName;
                ConnectionString = connectionString;
            }
    
            public void Register(NSData deviceToken, string locale)
            {
                ParseConnectionInfo();
                SendNHRegistrationRequest(deviceToken, locale);
            }
    
            // From http://msdn.microsoft.com/en-us/library/dn495627.aspx 
            private static void ParseConnectionInfo()
            {
                if (string.IsNullOrWhiteSpace(HubName))
                {
                    throw new InvalidOperationException("Hub name is empty");
                }
    
                var parts = ConnectionString.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
    
                if (parts.Length != 3)
                {
                    throw new InvalidOperationException("Error parsing connection string: " + ConnectionString);
                }
    
                foreach (var part in parts)
                {
                    if (part.StartsWith("Endpoint"))
                    {
                        Endpoint = "https" + part.Substring(11);
                    }
                    else if (part.StartsWith("SharedAccessKeyName"))
                    {
                        SasKeyName = part.Substring(20);
                    }
                    else if (part.StartsWith("SharedAccessKey"))
                    {
                        SasKeyValue = part.Substring(16);
                    }
                }
            }
            private static string GenerateSaSToken(Uri uri)
            {
                var targetUri = WebUtility.UrlEncode(uri.ToString().ToLower()).ToLower();
    
                var expiresOnDate = Convert.ToInt64(DateTime.UtcNow.Subtract
                    (new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds) + 60 * 60;
                var toSign = targetUri + "\n" + expiresOnDate;
    
                var keyBytes = Encoding.UTF8.GetBytes(SasKeyValue);
                var mac = new HMACSHA256(keyBytes);
                mac.Initialize();
                var rawHmac = mac.ComputeHash(Encoding.UTF8.GetBytes(toSign));
                var signature = WebUtility.UrlEncode(Convert.ToBase64String(rawHmac));
    
                var token = "SharedAccessSignature sr=" + targetUri + "&sig="
                        + signature + "&se=" + expiresOnDate + "&skn=" + SasKeyName;
                return token;
            }
    
            private static void SendNHRegistrationRequest(NSData deviceToken, string locale)
            {
                Payload =
                @"<?xml version=""1.0"" encoding=""utf-8""?>
                <entry xmlns=""http://www.w3.org/2005/Atom"">
                    <content type=""application/xml"">
                        <AppleRegistrationDescription xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"" xmlns=""http://schemas.microsoft.com/netservices/2010/10/servicebus/connect"">
                            <Tags>green-star-aaf03, Roidu_player</Tags>
                            <DeviceToken>97f7deed 1de67d75 82345e57 499b0050 d108adc4 00af6de3 7407adc8 5cedc39d</DeviceToken>
                        </AppleRegistrationDescription>
                    </content>
                </entry>";
    
                var uri = new Uri(Endpoint + HubName + "/registrations/" + ApiVersion);
                var sendRequest = WebRequest.CreateHttp(uri);
                sendRequest.Method = "POST";
                sendRequest.ContentType = ContentType;
                sendRequest.Headers[AuthHeader] = GenerateSaSToken(uri);
                sendRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), sendRequest);
            }
    
            static void GetRequestStreamCallback(IAsyncResult asynchronousResult)
            {
                HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
                // End the stream request operation
                Stream postStream = request.EndGetRequestStream(asynchronousResult);
    
                byte[] byteArray = Encoding.UTF8.GetBytes(Payload);
    
                postStream.Write(byteArray, 0, byteArray.Length);
                postStream.Close();
    
                //Start the web request
                request.BeginGetResponse(new AsyncCallback(GetResponceStreamCallback), request);
            }
    
            static void GetResponceStreamCallback(IAsyncResult callbackResult)
            {
                try
                {
                    HttpWebRequest request = (HttpWebRequest)callbackResult.AsyncState;
                    HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(callbackResult);
                    using (StreamReader httpWebStreamReader = new StreamReader(response.GetResponseStream()))
                    {
                        string result = httpWebStreamReader.ReadToEnd();
                        //For debug: show results
                        Debug.WriteLine(result);
                    }
                }
                catch (Exception ex)
                {
                    string responseerror = ex.Message;
                }
            }
        }
    }

    Samstag, 18. Februar 2017 15:18
  • Hallo,

    ich habe die Klasse so übernommen wie sie ist und auch nicht die api-version geändert.

    Mein Aufruf sieht so aus

    string notificationHubName = "TWyTecTest";
                string connectionString = "[zu finden unter > HubName - Zugriffsrichtlinien]";
    
                var channel = await Windows.Networking.PushNotifications.PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
    
                TWyTec.NotificationHub hub = new TWyTec.NotificationHub(notificationHubName, connectionString);
                hub.Register(channel.Uri);

    In einem Win 10 Projekt geht es so. Muss also an etwas anderem liegt als an der Klasse


    Gruß, Thomas

    Sage nie, ich kann es nicht - sage nur, ich kann es noch nicht!

    Icon für UWP

    Samstag, 18. Februar 2017 17:12
  • es hat sich herausgestellt das die Tags das Problem sind.

    sobald ein "-" Zeichen im Tag ist wird es abgelehnt. funktioniert komischer weise mit SDKs auf allen anderen Plattformen ohne Probleme.

    Danke trotzdem

    Samstag, 18. Februar 2017 20:17