1

I want to send an IEnumerable<T> and some other properties as a parameters to call a HttpGet from an API, my controller looks like this:

[HttpGet]
public Task<IEnumerable<string>> Get([FromQuery] Foo foo) //Notice [FromQuery]
{
    //some stuff here that returns an IEnumerable of strings
}  

the structure for Foo is:

public class Foo 
{
    public IEnumerable<Guid> Guids { get; set; }
    public DateTime BeginDate { get; set; }
    public DateTime EndDate { get; set; }
}

and my WebClient logic needs to hit dynamically different endpoints and create the parameters for the request, this is what I´ve done so far:

public class WebClientRequestClass
{
    public T Get<T>(string url, object args = null)
    {
        using (var webClient = new WebClient())
        {
            webClient.BaseAddress = @"http://localhost:(SomePortGoesHere)/api/";
            webClient.QueryString = ToQueryString(args);
            var json = webClient.DownloadString(@"SomeEndpointGoesHere");

            var javaScriptSerializer = new JavaScriptSerializer();
            javaScriptSerializer.MaxJsonLength = Int32.MaxValue;
            return (T)javaScriptSerializer.Deserialize(json, typeof(T));
        }
    }

    private NameValueCollection ToQueryString(object args)
    {       
        var pairs = args
               .GetType()
               .GetProperties(BindingFlags.Public | BindingFlags.Instance)
               .Select(p =>
               {
                   var value = p.GetValue(args, null);
                   if (value is DateTime)
                   {
                       return new KeyValuePair<string, string>(p.Name, Encode(((DateTime)value).ToString("yyyy-MM-dd")));
                   }
                   else
                   {
                       return new KeyValuePair<string, string>(p.Name, Encode(value.ToString())); //Problem goes here for objects and ToString() implementation

                   }
               });

        var nameValueCollection = new NameValueCollection();
        foreach (var pair in pairs)
        {
            nameValueCollection.Add(pair.Key, pair.Value);
        }
        return nameValueCollection;
    }
}

So my problem is that my collection is not being treated correctly, my Uri looks like http://localhost:666/api/EndPoint?Guids=System.Guid[]&BeginDate=2018-01-22&EndDate=2019-01-22

Notice the Guids=System.Guid[] instead of my collection values, how can I solve this problem?

Maybe custom implementation of ToString() in Foo?, Changing [FromQuery] in the controller?

Diego Osornio
  • 835
  • 1
  • 10
  • 20
  • 3
    This may be a bit more complex than a URL query string would generally handle. There's nothing inherently wrong with using a POST request for something like this, which appears to be a kind of search/filter process. GET is fine for getting individual resources, but POST is used for "getting" search results (or, if it's semantically more comfortable, "posting" a search request). You're not semantically getting a resource, you're invoking an action which performs logic and returns results. – David Jan 22 '19 at 23:08
  • I agree with David. Use a POST for this. – Robert Harvey Jan 22 '19 at 23:11
  • 1
    Why are you using `HttpGet`? If you don't know why, use `HttpPost` instead. – mjwills Jan 22 '19 at 23:31
  • @mjwills there is no specific reason, these are my first steps with web APIs – Diego Osornio Jan 22 '19 at 23:37
  • Then use `[HttpPost]` instead. – mjwills Jan 22 '19 at 23:43

0 Answers0