我不知道 C# 中有什么可以做到这一点,但你可以使用 jQuery 来做这个客户端。
var data = @Html.Raw(Json.Encode(Model));
var query = $.param(data);
更新
我没有注意到您刚刚决定使用 JSON。当然,如果 API 端点支持它,那是最简单和最好的选择(但真的有什么不支持的吗?)。尽管如此,我对如何在 C# 中将对象实际序列化为 x-www-form-urlecoded 很感兴趣,并且对我找不到任何内置方式感到非常惊讶。即使使用 Web API 中的FormUrlEncodedMediaTypeFormatter,他们通过将其设为只读格式化程序(即它可以将 x-www-form-urlencoded 读取到对象中,但反之不行)来回避问题。所以,我写了这种又快又脏的方法。 (注意:它使用反射,所以在这里插入火焰,但我不确定你还能如何实现这样的效果。)
public void BuildFormUrlEncodedDataString(Type type, object obj, StringBuilder builder, string prefix = "")
{
var props = type.GetProperties();
foreach (var prop in props)
{
if (prop.CanRead)
{
if (typeof(IEnumerable).IsAssignableFrom(prop.PropertyType) && prop.PropertyType.IsGenericType)
{
IEnumerable list = (IEnumerable)prop.GetValue(obj);
if (list != null)
{
var i = 0;
foreach (var item in list)
{
if (item != null)
{
prefix += string.Format("{0}[{1}].", HttpUtility.UrlEncode(prop.Name), i);
BuildFormUrlEncodedDataString(item.GetType(), item, builder, prefix);
i++;
}
}
}
}
else if (prop.PropertyType.IsPrimitive || prop.PropertyType.Equals(typeof(String)))
{
var item = prop.GetValue(obj);
if (item != null)
{
builder.AppendFormat("{0}{1}{2}={3}",
builder.Length == 0 ? string.Empty : "&",
prefix,
prop.Name,
HttpUtility.UrlEncode(item.ToString())
);
}
}
else
{
var item = prop.GetValue(obj);
if (item != null)
{
prefix += string.Format("{0}.", HttpUtility.UrlEncode(prop.Name));
BuildFormUrlEncodedDataString(item.GetType(), item, builder, prefix);
}
}
}
}
}
你会像这样使用它:
var builder = new StringBuilder();
BuildFormUrlEncodedDataString(myObject.GetType(), myObject, builder)
var queryString = builder.ToString();
此时它更像是一种智力练习,因为您不再需要它,但它是一种有趣的消遣。也许它会对其他人派上用场。