web-dev-qa-db-fra.com

Liens dynamiques Google avec .NET

J'essaie de faire fonctionner le lien dynamique de Google Firebase sur mon projet .net principal. 

public static async Task<string> GetShortLink(string longLink)
{
    var service = AuthenticateServiceAccount("[email protected]", "Opt/Keys/quallogi-keys.json", new[] { "https://www.googleapis.com/auth/firebase" });
    var request = service.ManagedShortLinks.Create(new CreateManagedShortLinkRequest
    {
        DynamicLinkInfo = new DynamicLinkInfo
        {
            //DynamicLinkDomain = "https://quallogi.page.link",
            DomainUriPrefix = "quallogi.page.link",
            AnalyticsInfo = new AnalyticsInfo(),
            IosInfo = new IosInfo(),
            Link = "https://github.com/distriqt/ANE-Firebase/wiki/DynamicLinks---Create-Dynamic-Links",

        },

        Suffix = new Suffix { Option = "SHORT" },
        Name = "shortlink",


    });
    var response = await request.ExecuteAsync();
    return response.PreviewLink;
}

public static FirebaseDynamicLinksService AuthenticateServiceAccount(string serviceAccountEmail, string serviceAccountCredentialFilePath, string[] scopes)
{
    try
    {
        if (string.IsNullOrEmpty(serviceAccountCredentialFilePath))
            throw new Exception("Path to the service account credentials file is required.");
        if (!File.Exists(serviceAccountCredentialFilePath))
            throw new Exception("The service account credentials file does not exist at: " + serviceAccountCredentialFilePath);
        if (string.IsNullOrEmpty(serviceAccountEmail))
            throw new Exception("ServiceAccountEmail is required.");

        if (Path.GetExtension(serviceAccountCredentialFilePath).ToLower() == ".json")
        {
            GoogleCredential credential;
            using (var stream = new FileStream(serviceAccountCredentialFilePath, FileMode.Open, FileAccess.Read))
            {
                credential = GoogleCredential.FromStream(stream)
                     .CreateScoped(scopes);
            }

            return new FirebaseDynamicLinksService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = "Firebasedynamiclinks Service account Authentication Sample",
            });
        }
        else if (Path.GetExtension(serviceAccountCredentialFilePath).ToLower() == ".p12")
        {

            var certificate = new X509Certificate2(serviceAccountCredentialFilePath, "notasecret", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
            var credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(serviceAccountEmail)
            {
                Scopes = scopes
            }.FromCertificate(certificate));

            return new FirebaseDynamicLinksService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = "Firebasedynamiclinks Authentication Sample",
            });
        }
        else
        {
            throw new Exception("Unsupported Service accounts credentials.");
        }

    }
    catch (Exception ex)
    {
        throw new Exception("CreateServiceAccountFirebasedynamiclinksFailed", ex);
    }
}

mais quand je lance le code google lève l'exception 

Google.Apis.Requests.RequestError Une erreur interne s'est produite. [500] Erreurs [Message [Erreur interne rencontrée.] Emplacement [-] Reason [backendError] Domaine [global]]

 enter image description here

quel était le problème?

7
Gayan

Je suis un peu surpris que tu sois aussi loin que toi. Actuellement, cette bibliothèque a deux problèmes:

  1. Lorsque vous utilisez ManagedShortLinks, il explose comme décrit. Cela ne va que si loin si vous abordez le deuxième problème, cependant.
  2. Les membres ETag ne sont pas décorés et sont sérialisés tels quels. Vous verrez une erreur comme ceci:
Google.Apis.Requests.RequestError
Invalid JSON payload received. Unknown name "ETag" at 'dynamic_link_info.Android_info': Cannot find field.
Invalid JSON payload received. Unknown name "ETag" at 'dynamic_link_info.ios_info': Cannot find field.
Invalid JSON payload received. Unknown name "ETag" at 'dynamic_link_info': Cannot find field.
Invalid JSON payload received. Unknown name "ETag" at 'suffix': Cannot find field.
Invalid JSON payload received. Unknown name "ETag": Cannot find field. [400]

Je n'ai pas trouvé de moyen de contourner ManagedShortLinks. Cependant, ShortLinks fonctionnera. Je vais vous montrer comment je l'ai fait.

       public async Task<string> GetDeepLink(Invitation inv)
       {
           var playId = _configurationProvider.GetSetting(AppSettingNames.GooglePlayAppId);
           var iosId = _configurationProvider.GetSetting(AppSettingNames.AppleAppStoreAppId);
           var domain = _configurationProvider.GetSetting(AppSettingNames.GoogleFirebaseDynamicLinkDomain);

           NameValueCollection queryString = System.Web.HttpUtility.ParseQueryString(string.Empty);

           queryString["Key1"] = "value1";

           var mslReq = new CreateShortDynamicLinkRequest();
           mslReq.DynamicLinkInfo = new DynamicLinkInfo();
           mslReq.DynamicLinkInfo.AndroidInfo = new AndroidInfo() { AndroidPackageName = playId };
           mslReq.DynamicLinkInfo.IosInfo = new IosInfo() { IosAppStoreId = iosId, IosBundleId = playId };
           mslReq.DynamicLinkInfo.DomainUriPrefix = $"https://{domain}";
           mslReq.DynamicLinkInfo.Link = $"https://www.example.com/?{queryString}";
           mslReq.Suffix = new Suffix() { Option = "SHORT" };
           var json = JsonConvert.SerializeObject(mslReq, Formatting.Indented, new CreateShortDynamicLinkRequestConverter());

           var request = _firebaseDynamicLinksService.ShortLinks.Create(new CreateShortDynamicLinkRequest());

           request.ModifyRequest = message =>
               message.Content = new StringContent(json, Encoding.UTF8, "application/json");

           var res = await request.ExecuteAsync();
           return res.ShortLink;
       }

Cela dépend de CreateShortDynamicLinkRequestConverter:

    public class CreateShortDynamicLinkRequestConverter : JsonConverter
    {
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            serializer.NullValueHandling = NullValueHandling.Ignore;
            var t = JToken.FromObject(value);
            var modified = t.RemoveFields("ETag");

            modified.WriteTo(writer);
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }

        public override bool CanConvert(Type objectType)
        {
            return true;
        }

        public override bool CanRead => false;
    }

qui dépend à son tour de RemoveFields

        // source: https://stackoverflow.com/a/31581951/773673
        public static JToken RemoveFields(this JToken token, params string[] fields)
        {
            JContainer container = token as JContainer;
            if (container == null) return token;

            List<JToken> removeList = new List<JToken>();
            foreach (JToken el in container.Children())
            {
                JProperty p = el as JProperty;
                if (p != null && (fields.Contains(p.Name)))
                {
                    removeList.Add(el);
                }
                el.RemoveFields(fields);
            }

            foreach (JToken el in removeList)
            {
                el.Remove();
            }

            return token;
        }

Au bout du compte, le gros problème ici est le manque de décoration des membres ETag. Nous devons travailler autour de cela. Je crois que la personnalisation de BaseClientService.Initializer.Serializer lorsque le service est instancié avec le constructeur public NewtonsoftJsonSerializer(JsonSerializerSettings settings) vous permettra de spécifier la variable Converters à utiliser, mais j’ai arrêté de le faire fonctionner. La vraie solution est simplement de décorer les membres de l’ETag pour ne pas participer à la sérialisation (à condition que cela ne casse rien d’autre!).

1
Adam Skinner