Google Dynamic Links with .NET
I'm trying to get google firebase dynamic link work on my .net core project my code is as below
public static async Task<string> GetShortLink(string longLink)
var service = AuthenticateServiceAccount("gayan@empite.com", "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
else
throw new Exception("Unsupported Service accounts credentials.");
catch (Exception ex)
throw new Exception("CreateServiceAccountFirebasedynamiclinksFailed", ex);
but when i run the code google throws exception
Google.Apis.Requests.RequestError Internal error encountered. [500]
Errors [ Message[Internal error encountered.] Location[ - ]
Reason[backendError] Domain[global] ]

what was the issue ?
c# firebase .net-core firebase-dynamic-links
add a comment |
I'm trying to get google firebase dynamic link work on my .net core project my code is as below
public static async Task<string> GetShortLink(string longLink)
var service = AuthenticateServiceAccount("gayan@empite.com", "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
else
throw new Exception("Unsupported Service accounts credentials.");
catch (Exception ex)
throw new Exception("CreateServiceAccountFirebasedynamiclinksFailed", ex);
but when i run the code google throws exception
Google.Apis.Requests.RequestError Internal error encountered. [500]
Errors [ Message[Internal error encountered.] Location[ - ]
Reason[backendError] Domain[global] ]

what was the issue ?
c# firebase .net-core firebase-dynamic-links
add a comment |
I'm trying to get google firebase dynamic link work on my .net core project my code is as below
public static async Task<string> GetShortLink(string longLink)
var service = AuthenticateServiceAccount("gayan@empite.com", "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
else
throw new Exception("Unsupported Service accounts credentials.");
catch (Exception ex)
throw new Exception("CreateServiceAccountFirebasedynamiclinksFailed", ex);
but when i run the code google throws exception
Google.Apis.Requests.RequestError Internal error encountered. [500]
Errors [ Message[Internal error encountered.] Location[ - ]
Reason[backendError] Domain[global] ]

what was the issue ?
c# firebase .net-core firebase-dynamic-links
I'm trying to get google firebase dynamic link work on my .net core project my code is as below
public static async Task<string> GetShortLink(string longLink)
var service = AuthenticateServiceAccount("gayan@empite.com", "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
else
throw new Exception("Unsupported Service accounts credentials.");
catch (Exception ex)
throw new Exception("CreateServiceAccountFirebasedynamiclinksFailed", ex);
but when i run the code google throws exception
Google.Apis.Requests.RequestError Internal error encountered. [500]
Errors [ Message[Internal error encountered.] Location[ - ]
Reason[backendError] Domain[global] ]

what was the issue ?
c# firebase .net-core firebase-dynamic-links
c# firebase .net-core firebase-dynamic-links
edited Nov 12 '18 at 11:47
KENdi
5,8192821
5,8192821
asked Nov 12 '18 at 4:59
GayanGayan
1,15632762
1,15632762
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
I'm a little surprised you got as far as you did. Currently, this library has two issues:
- When using ManagedShortLinks, it blows up as described. It only gets so far if you deal with the second issue, however.
- The
ETagmembers are undecorated, and get serialized as is. You will see an error like so:
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]
I haven't found a way around ManagedShortLinks. However, ShortLinks will work. I'll show you how I did it.
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;
This depends upon 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;
which in turn depends upon 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;
At the end of the day, the big problem here is the lack of decoration of the ETag members. We need to work around that. I believe that customizing BaseClientService.Initializer.Serializer when the service is instantiated with the public NewtonsoftJsonSerializer(JsonSerializerSettings settings) constructor will allow you to specify the Converters to use, but I stopped when I got it working. The real fix for this is to simply decorate the ETag members to not participate in serialization (providing that doesn't break anything else!).
thanks for the answer i will run the code and check ..
– Gayan
Jan 28 at 9:33
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53256178%2fgoogle-dynamic-links-with-net%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
I'm a little surprised you got as far as you did. Currently, this library has two issues:
- When using ManagedShortLinks, it blows up as described. It only gets so far if you deal with the second issue, however.
- The
ETagmembers are undecorated, and get serialized as is. You will see an error like so:
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]
I haven't found a way around ManagedShortLinks. However, ShortLinks will work. I'll show you how I did it.
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;
This depends upon 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;
which in turn depends upon 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;
At the end of the day, the big problem here is the lack of decoration of the ETag members. We need to work around that. I believe that customizing BaseClientService.Initializer.Serializer when the service is instantiated with the public NewtonsoftJsonSerializer(JsonSerializerSettings settings) constructor will allow you to specify the Converters to use, but I stopped when I got it working. The real fix for this is to simply decorate the ETag members to not participate in serialization (providing that doesn't break anything else!).
thanks for the answer i will run the code and check ..
– Gayan
Jan 28 at 9:33
add a comment |
I'm a little surprised you got as far as you did. Currently, this library has two issues:
- When using ManagedShortLinks, it blows up as described. It only gets so far if you deal with the second issue, however.
- The
ETagmembers are undecorated, and get serialized as is. You will see an error like so:
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]
I haven't found a way around ManagedShortLinks. However, ShortLinks will work. I'll show you how I did it.
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;
This depends upon 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;
which in turn depends upon 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;
At the end of the day, the big problem here is the lack of decoration of the ETag members. We need to work around that. I believe that customizing BaseClientService.Initializer.Serializer when the service is instantiated with the public NewtonsoftJsonSerializer(JsonSerializerSettings settings) constructor will allow you to specify the Converters to use, but I stopped when I got it working. The real fix for this is to simply decorate the ETag members to not participate in serialization (providing that doesn't break anything else!).
thanks for the answer i will run the code and check ..
– Gayan
Jan 28 at 9:33
add a comment |
I'm a little surprised you got as far as you did. Currently, this library has two issues:
- When using ManagedShortLinks, it blows up as described. It only gets so far if you deal with the second issue, however.
- The
ETagmembers are undecorated, and get serialized as is. You will see an error like so:
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]
I haven't found a way around ManagedShortLinks. However, ShortLinks will work. I'll show you how I did it.
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;
This depends upon 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;
which in turn depends upon 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;
At the end of the day, the big problem here is the lack of decoration of the ETag members. We need to work around that. I believe that customizing BaseClientService.Initializer.Serializer when the service is instantiated with the public NewtonsoftJsonSerializer(JsonSerializerSettings settings) constructor will allow you to specify the Converters to use, but I stopped when I got it working. The real fix for this is to simply decorate the ETag members to not participate in serialization (providing that doesn't break anything else!).
I'm a little surprised you got as far as you did. Currently, this library has two issues:
- When using ManagedShortLinks, it blows up as described. It only gets so far if you deal with the second issue, however.
- The
ETagmembers are undecorated, and get serialized as is. You will see an error like so:
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]
I haven't found a way around ManagedShortLinks. However, ShortLinks will work. I'll show you how I did it.
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;
This depends upon 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;
which in turn depends upon 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;
At the end of the day, the big problem here is the lack of decoration of the ETag members. We need to work around that. I believe that customizing BaseClientService.Initializer.Serializer when the service is instantiated with the public NewtonsoftJsonSerializer(JsonSerializerSettings settings) constructor will allow you to specify the Converters to use, but I stopped when I got it working. The real fix for this is to simply decorate the ETag members to not participate in serialization (providing that doesn't break anything else!).
answered Jan 23 at 17:04
Adam SkinnerAdam Skinner
39047
39047
thanks for the answer i will run the code and check ..
– Gayan
Jan 28 at 9:33
add a comment |
thanks for the answer i will run the code and check ..
– Gayan
Jan 28 at 9:33
thanks for the answer i will run the code and check ..
– Gayan
Jan 28 at 9:33
thanks for the answer i will run the code and check ..
– Gayan
Jan 28 at 9:33
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53256178%2fgoogle-dynamic-links-with-net%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown