如何使用带有 C# HttpClient 的 Get 发送复杂对象
How to send a complex object using Get with c# HttpClient
我有一个 c# 项目并希望使用 api。如果感兴趣,可以在此处查看文档:link
当我想获得 api 中所有“客户”的列表时,它具有一些必需的属性:
attention.self, currency, customerContact.self, customerGroup,
customerGroup.self, defaultDeliveryLocation.self, invoices.self,
layout.self, name, paymentTerms, paymentTerms.self, salesPerson.self,
self, templates.self, totals.self, vatZone, vatZone.self
我有一个自定义对象,其命名与所需属性相同。该对象很复杂,因为它引用了“attention、customerContact、customerGroup、paymentTerms..”之类的对象,正如文档所述。
现在我必须使用的端点是带有 Get 的“\customers”,所以我必须参数化属性。
我一直在寻找将复杂对象转换为 uri 之类的解决方案
“?name=Mike¤cy=USD&..”,但不幸的是我只找到了一个解决方案,它可以将只有简单类型的自定义对象制作成格式化参数字符串。
所以我暂时放弃并尝试编写自己的硬编码 url 字符串,但是如何将复杂的对象添加到 url 查询中,例如“attention.self”?
“?attention.self=Something&..”会让 api 翻译它以便它知道“注意力”是另一个对象而“自我”是那个对象上的 属性 ?
任何有关如何更优化地执行此操作的建议都会很棒。
您可以使用 Reflection
:
public IEnumerable<string> ToQueryStringItem<T>(T entity)
{
foreach(var pi in typeof(T).GetProperties())
yield return $"{pi.Name}={pi.GetValue(entity)}";
}
public IEnumerable<string> ToQueryString<T>(T entity)
=> $"?{string.Join("&", ToQueryString(entity).ToList())}";
现在您可以像这样操作:
string qs = ToQueryString(someClassInstance);
请注意,如果 class 属性不是原始类型,您将需要更复杂的反射代码。
而且如果你想要一些自定义值,它也是可行的,例如让我们说而不是 true
和 false
,你想要 1
和 0
:
foreach(var pi in typeof(T).GetProperties())
{
switch(pi.PropertyType.ToString())
{
case "Boolean":
yield return $"{pi.Name}={(pi.GetValue(entity)?1:0)};
//....
default:
yield return $"{pi.Name}={pi.GetValue(entity)}";
}
}
您可能还想隐藏一些属性以防止在查询字符串中使用,为此您可以创建一个属性:
public class IgnoreInQueryStringAttribute: Attribute {}
并将其用于您不想出现在查询字符串中的任何 属性:
public class Customer
{
[IgnoreInQueryString]
public int Id { get; set; }
public string Firstname { get; set; }
}
然后:
foreach(var pi in typeof(T).GetProperties())
{
if(pi.GetCustomAttributes(typeof(IgnoreInQueryString), false).Length == 0)
{
//....
}
}
我有一个 c# 项目并希望使用 api。如果感兴趣,可以在此处查看文档:link
当我想获得 api 中所有“客户”的列表时,它具有一些必需的属性:
attention.self, currency, customerContact.self, customerGroup, customerGroup.self, defaultDeliveryLocation.self, invoices.self, layout.self, name, paymentTerms, paymentTerms.self, salesPerson.self, self, templates.self, totals.self, vatZone, vatZone.self
我有一个自定义对象,其命名与所需属性相同。该对象很复杂,因为它引用了“attention、customerContact、customerGroup、paymentTerms..”之类的对象,正如文档所述。
现在我必须使用的端点是带有 Get 的“\customers”,所以我必须参数化属性。
我一直在寻找将复杂对象转换为 uri 之类的解决方案 “?name=Mike¤cy=USD&..”,但不幸的是我只找到了一个解决方案,它可以将只有简单类型的自定义对象制作成格式化参数字符串。
所以我暂时放弃并尝试编写自己的硬编码 url 字符串,但是如何将复杂的对象添加到 url 查询中,例如“attention.self”?
“?attention.self=Something&..”会让 api 翻译它以便它知道“注意力”是另一个对象而“自我”是那个对象上的 属性 ?
任何有关如何更优化地执行此操作的建议都会很棒。
您可以使用 Reflection
:
public IEnumerable<string> ToQueryStringItem<T>(T entity)
{
foreach(var pi in typeof(T).GetProperties())
yield return $"{pi.Name}={pi.GetValue(entity)}";
}
public IEnumerable<string> ToQueryString<T>(T entity)
=> $"?{string.Join("&", ToQueryString(entity).ToList())}";
现在您可以像这样操作:
string qs = ToQueryString(someClassInstance);
请注意,如果 class 属性不是原始类型,您将需要更复杂的反射代码。
而且如果你想要一些自定义值,它也是可行的,例如让我们说而不是 true
和 false
,你想要 1
和 0
:
foreach(var pi in typeof(T).GetProperties())
{
switch(pi.PropertyType.ToString())
{
case "Boolean":
yield return $"{pi.Name}={(pi.GetValue(entity)?1:0)};
//....
default:
yield return $"{pi.Name}={pi.GetValue(entity)}";
}
}
您可能还想隐藏一些属性以防止在查询字符串中使用,为此您可以创建一个属性:
public class IgnoreInQueryStringAttribute: Attribute {}
并将其用于您不想出现在查询字符串中的任何 属性:
public class Customer
{
[IgnoreInQueryString]
public int Id { get; set; }
public string Firstname { get; set; }
}
然后:
foreach(var pi in typeof(T).GetProperties())
{
if(pi.GetCustomAttributes(typeof(IgnoreInQueryString), false).Length == 0)
{
//....
}
}