Ich versuche, Google Firebase Dynamic Link auf meinem .NET-Kernprojekt zum Laufen zu bringen. Mein Code ist wie folgt
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);
}
}
aber wenn ich den Code google laufen lasse, wirft Ausnahme
Google.Apis.Requests.RequestError Interner Fehler. [500] Fehler [Meldung [Interner Fehler aufgetreten.] Speicherort [-] Grund [backendError] Domäne [global]]
was war das Problem?
Ich bin ein bisschen überrascht, dass du so weit gekommen bist wie du. Derzeit gibt es in dieser Bibliothek zwei Probleme:
ETag
-Mitglieder sind nicht dekoriert und werden wie sie sind serialisiert. Sie werden einen Fehler wie folgt sehen: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]
Ich habe keinen Weg gefunden, um ManagedShortLinks zu umgehen. ShortLinks
funktioniert jedoch. Ich zeige dir, wie ich es gemacht habe.
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;
}
Dies hängt von CreateShortDynamicLinkRequestConverter
ab:
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;
}
was wiederum von RemoveFields
abhängt:
// 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;
}
Letztendlich ist das große Problem hier die fehlende Dekoration der ETag
-Mitglieder. Wir müssen das umgehen. Ich glaube, dass das Anpassen von BaseClientService.Initializer.Serializer
, wenn der Dienst mit dem Konstruktor public NewtonsoftJsonSerializer(JsonSerializerSettings settings)
instanziiert wird, es Ihnen ermöglicht, das zu verwendende Converters
anzugeben, aber ich habe aufgehört, als es funktioniert. Die eigentliche Lösung besteht darin, die ETag-Mitglieder einfach so zu dekorieren, dass sie nicht an der Serialisierung teilnehmen (vorausgesetzt, dass nichts anderes kaputt geht!).