Reputation: 34830
I'd like to bind to a dynamic object from the request querystring in ASP.NET Web API. Whilst decorating the action parameter with [FromUri]
works with a normal class, it does not appear to work with dynamic (the dynamic object is empty).
public dynamic Get(string id, [FromUri]dynamic criteria)
{
return Ok();
}
Note that this needs to work for GET requests so there is no body.
Upvotes: 6
Views: 6238
Reputation: 60556
No it can't work.
The [FormUri]
attribute tries to bind the object properties to the query string properties by name.
A dynamic object has no properties so it can't bind.
You can create your own model binder to achieve this goal. I don't suggest for you to go that way, but it is possible.
The "problem" with dynamics in this case is that it is not compiler safe and you can get errors at runtime if the parameters you expect are not part of the request.
Upvotes: 4
Reputation: 17584
While Web API complains that Multiple actions were found that match the request
when overriding the Get
method with a single parameter, you can "trick" the default model binder into binding the model you want by adding another parameter.
public class House
{
public string Color { get; set; }
public double SquareFeet { get; set; }
public override string ToString()
{
return "Color: " + Color + ", Sq. Ft.:" + SquareFeet;
}
}
public class Car
{
public string Color { get; set; }
public double EngineSize { get; set; }
public override string ToString()
{
return "Color: " + Color + ", cc: " + EngineSize;
}
}
public class ValuesController : ApiController
{
public string Get([FromUri] bool house, [FromUri] House model)
{
return model.ToString();
}
public string Get([FromUri] bool car, [FromUri] Car model)
{
return model.ToString();
}
}
Using the above code, the following URLs produce the respective output:
~/api/values?house=true&color=white&squarefeet=1500
<string>Color: white, Sq. Ft.:1500</string>
~/api/values?car=true&color=black&enginesize=2500
<string>Color: black, cc: 2500</string>
Upvotes: 0
Reputation: 17584
You might be interested in the GetQueryNameValuePairs
extension method (docs).
While it doesn't bind the query parameters to a model, it does allow you to access query parameters in a dynamic way (which sounds like your ultimate goal) via a dictionary-like object.
Also, see this answer.
var dict = new Dictionary<string, string>();
var qnvp = this.Request.GetQueryNameValuePairs();
foreach (var pair in qnvp)
{
if (dict.ContainsKey(pair.Key) == false)
{
dict[pair.Key] = pair.Value;
}
}
Upvotes: 7