【问题标题】:.NET equivalent of JQuery.param().NET 等效于 JQuery.param()
【发布时间】:2014-11-23 11:56:00
【问题描述】:

我想改进我的 Web API 测试并寻找一种更好地格式化 url 的方法。

var filter = new {
    State = new[] {"A", "C"},
    MaxAge = 60,
    POI = new { Lat = 40, Long = -130 }
};

我应该调用什么来像JQuery.param() 函数一样格式化查询字符串?

【问题讨论】:

标签: jquery .net url asp.net-web-api query-string


【解决方案1】:

There你可以找到一个扩展方法,它可以帮助你将对象转换为查询字符串

public static class UrlHelpers
{
    public static string ToQueryString(this object request, string separator = ",")
    {
        if (request == null)
            throw new ArgumentNullException("request");

        // Get all properties on the object
        var properties = request.GetType().GetProperties()
            .Where(x => x.CanRead)
            .Where(x => x.GetValue(request, null) != null)
            .ToDictionary(x => x.Name, x => x.GetValue(request, null));

        // Get names for all IEnumerable properties (excl. string)
        var propertyNames = properties
            .Where(x => !(x.Value is string) && x.Value is IEnumerable)
            .Select(x => x.Key)
            .ToList();

        // Concat all IEnumerable properties into a comma separated string
        foreach (var key in propertyNames)
        {
            var valueType = properties[key].GetType();
            var valueElemType = valueType.IsGenericType
                                    ? valueType.GetGenericArguments()[0]
                                    : valueType.GetElementType();
            if (valueElemType.IsPrimitive || valueElemType == typeof (string))
            {
                var enumerable = properties[key] as IEnumerable;
                properties[key] = string.Join(separator, enumerable.Cast<object>());
            }
        }

        // Concat all key/value pairs into a string separated by ampersand
        return string.Join("&", properties
            .Select(x => string.Concat(
                Uri.EscapeDataString(x.Key), "=",
                Uri.EscapeDataString(x.Value.ToString()))));
    }
}

并将其用作string querystring = example.ToQueryString();

【讨论】:

  • 在这种情况下,我认为仅链接问题更好,但我能做什么
  • 谢谢!虽然代码并不是 JQuery.param() 所做的(至少是数组/日期时间格式)。
  • 如果您不仅需要这个 js 功能和/或不担心繁重的解决方案,您可以将 js 引擎嵌入到您的应用程序中(例如 javascriptdotnet.codeplex.com ) - 我在一个项目中使用它,所以如果你也决定使用它,我可以在我的解决方案中测试JQuery.param()
  • 这个不支持嵌套!
  • @VladoPandžić 你可以尝试使用 POST 的 body 来传递复杂的对象
【解决方案2】:

这是我的扩展方法。它支持嵌套。 Javascript 对象表示为 Dictionary,而 javascript 数组表示为 IEnumerable。

public static class ToQueryStringExtension
{
    public static string ToQueryString(this Dictionary<string, object> obj)
    {
        if (obj == null) return "";

        string query = "";
        bool first = true;
        Dictionary<string, List<string>> data = ToQueryStringHelper(obj);
        foreach (KeyValuePair<string, List<string>> kvp in data)
        {
            string keyUrlencoded = UpperCaseUrlEncode(kvp.Key);
            foreach (string ele in kvp.Value)
            {
                if (first) first = false;
                else query += "&";
                query += keyUrlencoded + ele;
            }
        }

        return query;
    }

    private static Dictionary<string, List<string>> ToQueryStringHelper(Dictionary<string, object> obj)
    {
        Dictionary<string, List<string>> data = new Dictionary<string, List<string>>();
        foreach (KeyValuePair<string, object> kvp in obj)
        {
            if (kvp.Value is Dictionary<string, object>)
            {
                Dictionary<string, List<string>> dataInner = ToQueryStringHelper((Dictionary<string, object>)kvp.Value);
                if (dataInner.Count < 1) continue;
                data.Add(kvp.Key, new List<string>());
                foreach (KeyValuePair<string, List<string>> kvpInner in dataInner)
                {
                    string keyUrlencoded = UpperCaseUrlEncode("[" + kvpInner.Key + "]");
                    foreach (string ele in kvpInner.Value)
                    {
                        data[kvp.Key].Add(keyUrlencoded + ele);
                    }
                }
            }
            else if ((kvp.Value is IEnumerable) && !(kvp.Value is string))
            {
                Dictionary<string, object> objInner = new Dictionary<string, object>();
                IEnumerable list = (IEnumerable)kvp.Value;
                int inx = 0;
                foreach (object ele in list)
                {
                    objInner.Add(inx.ToString(), ele);
                    inx++;
                }

                Dictionary<string, List<string>> dataInner = ToQueryStringHelper(objInner);
                if (dataInner.Count < 1) continue;
                data.Add(kvp.Key, new List<string>());
                foreach (KeyValuePair<string, List<string>> kvpInner in dataInner)
                {
                    // index key can be removed in peripheral nodes
                    string keyUrlencoded = null;
                    if (kvpInner.Value.Count == 1 && kvpInner.Value[0].StartsWith("=")) keyUrlencoded = General.UpperCaseUrlEncode("[]");
                    else keyUrlencoded = UpperCaseUrlEncode("[" + kvpInner.Key + "]");
                    foreach (string ele in kvpInner.Value)
                    {
                        data[kvp.Key].Add(keyUrlencoded + ele);
                    }
                }
            }
            else
            {
                // Optional check if peripheral value type is known.
                //Type type = kvp.Value.GetType();
                //if (!(kvp.Value is Decimal) && !(kvp.Value is string) && !(type.IsPrimitive)) throw new Exception("Unknown peripheral type.");
                if (kvp.Value != null)
                {
                    data.Add(kvp.Key, new List<string>());
                    data[kvp.Key].Add("=" + UpperCaseUrlEncode(kvp.Value.ToString()));
                }
            }
        }
        return data;
    }

    public static string UpperCaseUrlEncode(string s)
    {
        char[] temp = HttpUtility.UrlEncode(s).ToCharArray();
        for (int i = 0; i < temp.Length - 2; i++)
        {
            if (temp[i] == '%')
            {
                temp[i + 1] = char.ToUpper(temp[i + 1]);
                temp[i + 2] = char.ToUpper(temp[i + 2]);
            }
        }
        return new string(temp);
    }
}

【讨论】:

    猜你喜欢
    • 2010-11-23
    • 2018-12-21
    • 2012-01-18
    • 2011-01-29
    • 2017-03-12
    • 1970-01-01
    • 2011-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多