10

I need to make a GET request to a method that contains Dictionary as a parameter. I browse through but could not find any kinds of information about how I could send Dictionary so my request hit to my method. Method signature is as like as below

public void AddItems(Dictionary<string,object> Items)

Best Regards,

Kemal

2
  • 2
    @kkcocabiyik Were you able to pass the Items into your GET request as URL query parameters? If so, can you post a sample of the syntax to use? Thanks! Commented Oct 8, 2013 at 18:19
  • To my knowledge, a GET request with ASP.NET Web API is not able to natively bind a Dictionary<TKey, TValue>. You will have to implement a model binder (learn.microsoft.com/en-us/aspnet/core/mvc/advanced/…) Commented May 3, 2022 at 7:35

4 Answers 4

11

Did you read ASP.NET Wire Format for Model Binding to Arrays, Lists, Collections, Dictionaries

Sign up to request clarification or add additional context in comments.

5 Comments

Asp. Net Web Api is a part of asp.net mvc
@KirillBestemyanov From a marketing perspective yes. From an implementation perspective there is some overlap, however there is also plenty of Web API code that is distinct from MVC. In the case of the Model binder however, I do believe the code is shared.
@KirillBestemyanov this is not true. As Darrel says it might be marketed as something that's part of it, but that's far from truth. Web API is, first and foremost, stand alone. And model binding itself is much different, see: blogs.msdn.com/b/jmstall/archive/2012/04/16/…
This answer is not helpful and quite misleading as the question pertains to Web API, which works differently to MVC 5.
And may be you add right answer instead of this? This answer was written 1 and half year ago based on mvc 4 and web api 1.0.
2

I wrote a ModelBinder that does exactly what you wanted:

public class DictionaryModelBinder : DefaultModelBinder
{
    private const string _dateTimeFormat = "dd/MM/yyyy HH:mm:ss";

    private enum StateMachine
    {
        NewSection,
        Key,
        Delimiter,
        Value,
        ValueArray
    }

    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var stream = controllerContext.HttpContext.Request.InputStream;
        string text;

        stream.Position = 0;
        using (var reader = new StreamReader(stream))
        {
            text = reader.ReadToEnd();
        }

        int index = 0;
        return Build(text, ref index);
    }

    private static Dictionary<string, object> Build(string text, ref int index)
    {
        var state = StateMachine.NewSection;
        var dictionary = new Dictionary<string, object>();
        var key = string.Empty;
        object value = string.Empty;

        for (; index < text.Length; ++index)
        {
            if (state == StateMachine.NewSection && text[index] == '{')
            {
                dictionary = new Dictionary<string, object>();
                state = StateMachine.NewSection;
            }
            else if (state == StateMachine.NewSection && text[index] == '"')
            {
                key = string.Empty;
                state = StateMachine.Key;
            }
            else if (state == StateMachine.Key && text[index] != '"')
            {
                key += text[index];
            }
            else if (state == StateMachine.Key && text[index] == '"')
            {
                state = StateMachine.Delimiter;
            }
            else if (state == StateMachine.Delimiter && text[index] == ':')
            {
                state = StateMachine.Value;
                value = string.Empty;
            }
            else if (state == StateMachine.Value && text[index] == '[')
            {
                state = StateMachine.ValueArray;
                value = value.ToString() + text[index];
            }
            else if (state == StateMachine.ValueArray && text[index] == ']')
            {
                state = StateMachine.Value;
                value = value.ToString() + text[index];
            }
            else if (state == StateMachine.Value && text[index] == '{')
            {
                value = Build(text, ref index);
            }
            else if (state == StateMachine.Value && text[index] == ',')
            {
                dictionary.Add(key, ConvertValue(value));
                state = StateMachine.NewSection;
            }
            else if (state == StateMachine.Value && text[index] == '}')
            {
                dictionary.Add(key, ConvertValue(value));
                return dictionary;
            }
            else if (state == StateMachine.Value || state == StateMachine.ValueArray)
            {
                value = value.ToString() + text[index];
            }
        }

        return dictionary;
    }

    private static object ConvertValue(object value)
    {
        string valueStr;
        if (value is Dictionary<string, object> || value == null || (valueStr = value.ToString()).Length == 0)
        {
            return value;
        }

        bool boolValue;
        if (bool.TryParse(valueStr, out boolValue))
        {
            return boolValue;
        }

        int intValue;
        if (int.TryParse(valueStr, out intValue))
        {
            return intValue;
        }

        double doubleValue;
        if (double.TryParse(valueStr, out doubleValue))
        {
            return doubleValue;
        }

        valueStr = valueStr.Trim('"');

        DateTime datetimeValue;
        if (DateTime.TryParseExact(valueStr, _dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out datetimeValue))
        {
            return datetimeValue;
        }

        if (valueStr.First() == '[' && valueStr.Last() == ']')
        {
            valueStr = valueStr.Trim('[', ']');
            if (valueStr.Length > 0)
            {
                if (valueStr[0] == '"')
                {
                    return valueStr
                        .Split(new[] { '"' }, StringSplitOptions.RemoveEmptyEntries)
                        .Where(x => x != ",")
                        .ToArray();
                }
                else
                {
                    return valueStr
                        .Split(',')
                        .Select(x => ConvertValue(x.Trim()))
                        .ToArray();
                }
            }
        }

        return valueStr;
    }
}

More explanations and full post you can see in my blog:

Json To Dictionary generic model binder

Comments

0

If you have problems receiving Dictionary in your webApi controller, relatively painless solution is to switch the parameter to List<"ObjectRepresentingDict"> insetead. It will map automatically.

Comments

-5

You Can Use Dictionary As A Parameter In This Way:

protected object DictionaryFunction()
{
    Dictionary<int,YourObjectName> YourDictionaryObjectName=new Dictionary<int,YourObjectName>();
    ...
    ...

    return YourDictionaryObjectName;
}

protected MyFunction()
{
    Dictionary<int,YourObjectName> MyDictionary=(Dictionary<int,YourObjectName>)DictionaryFunction();
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.