'Using FromUri to bind object without parameter name prefixes
When using ASP.NET WebApi2 and Swashbuckle/Swagger, I am trying to bind an object using the FromUri attribute, something like this:
[RoutePrefix("api/v1/example")]
public class ExampleController : ApiController
{
[HttpGet]
[Route("{id}")]
public ExampleModel Get(string id, [FromUri]ExampleModel searchCriteria)
{
...
}
}
public class ExampleModel
{
public string id { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
}
I find that the URL to perform this GET operation and search by last name ends up being something like:
http://localhost:52259/api/v1/example/1?searchCriteria.firstName=paul
How can I remove the "searchCriteria" prefix from the query parameter? I want to keep it as an ExampleModel object in the controller's method signature, but be able to use (and have this reflected in the Swagger UI docs):
http://localhost:52259/api/v1/example/1?firstName=paul
Solution 1:[1]
There's a Name property on the FromUri attribute. If I set that to an empty string, it makes the Swagger UI docs appear without the "searchCriteria." prefix:
public ExampleModel Get(string id, [FromUri(Name = "")]ExampleModel searchCriteria)
{
...
}
It appears that the controller receives the firstName regardless of whether or not there is a "searchCriteria." prefix as part of the query parameter name.
Solution 2:[2]
I managed to solve it, I inserted a static method, follow the code below if anyone needs it
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()))));
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Paul K. |
| Solution 2 | Rafael Parenza |
