using System;
using System.Linq;
using System.Threading.Tasks;
using EmbedIO.Utilities;
using Swan;
namespace EmbedIO.WebApi
{
///
/// Specifies that a parameter of a controller method will receive the value of a field,
/// obtained by deserializing a request URL query.
/// The parameter carrying this attribute can be either a simple type or a one-dimension array.
/// If multiple values are present for the field, a non-array parameter will receive the last specified value,
/// while an array parameter will receive an array of field values converted to the element type of the
/// parameter.
/// If a single value is present for the field, a non-array parameter will receive the value converted
/// to the type of the parameter, while an array parameter will receive an array of length 1, containing
/// the value converted to the element type of the parameter
/// If no values are present for the field and the property is
/// , a 400 Bad Request response will be sent to the client, with a message
/// specifying the name of the missing field.
/// If no values are present for the field and the property is
/// , a non-array parameter will receive the default value for its type, while
/// an array parameter will receive an array of length 0.
/// This class cannot be inherited.
///
///
///
///
[AttributeUsage(AttributeTargets.Parameter)]
public sealed class QueryFieldAttribute :
Attribute,
IRequestDataAttribute,
IRequestDataAttribute,
IRequestDataAttribute
{
///
/// Initializes a new instance of the class.
/// The name of the query field to extract will be equal to the name of the parameter
/// carrying this attribute.
///
public QueryFieldAttribute()
: this(false, null)
{
}
///
/// Initializes a new instance of the class.
///
/// The name of the query field to extract.
/// is .
/// is the empty string ("").
public QueryFieldAttribute(string fieldName)
: this(false, Validate.NotNullOrEmpty(nameof(fieldName), fieldName))
{
}
///
/// Initializes a new instance of the class.
/// The name of the query field to extract will be equal to the name of the parameter
/// carrying this attribute.
///
/// If set to , a 400 Bad Request
/// response will be sent to the client if no values are found for the field; if set to
/// , a default value will be assumed.
public QueryFieldAttribute(bool badRequestIfMissing)
: this(badRequestIfMissing, null)
{
}
///
/// Initializes a new instance of the class.
///
/// The name of the query field to extract.
/// is .
/// is the empty string ("").
/// If set to , a 400 Bad Request
/// response will be sent to the client if no values are found for the field; if set to
/// , a default value will be assumed.
public QueryFieldAttribute(string fieldName, bool badRequestIfMissing)
: this(badRequestIfMissing, Validate.NotNullOrEmpty(nameof(fieldName), fieldName))
{
}
private QueryFieldAttribute(bool badRequestIfMissing, string? fieldName)
{
BadRequestIfMissing = badRequestIfMissing;
FieldName = fieldName;
}
///
/// Gets the name of the query field that this attribute will extract,
/// or if the name of the parameter carrying this
/// attribute is to be used as field name.
///
public string? FieldName { get; }
///
/// Gets or sets a value indicating whether to send a 400 Bad Request response
/// to the client if the URL query contains no values for the field.
/// If this property is and the URL query
/// contains no values for the field, the 400 Bad Request response sent
/// to the client will contain a reference to the missing field.
/// If this property is and the URL query
/// contains no values for the field, the default value for the parameter
/// (or a zero-length array if the parameter is of an array type)
/// will be passed to the controller method.
///
public bool BadRequestIfMissing { get; }
Task IRequestDataAttribute.GetRequestDataAsync(
WebApiController controller,
string parameterName)
{
var data = controller.HttpContext.GetRequestQueryData();
var fieldName = FieldName ?? parameterName;
if (!data.ContainsKey(fieldName) && BadRequestIfMissing)
throw HttpException.BadRequest($"Missing query field {fieldName}.");
return Task.FromResult(data.GetValues(fieldName)?.LastOrDefault());
}
Task IRequestDataAttribute.GetRequestDataAsync(
WebApiController controller,
string parameterName)
{
var data = controller.HttpContext.GetRequestQueryData();
var fieldName = FieldName ?? parameterName;
if (!data.ContainsKey(fieldName) && BadRequestIfMissing)
throw HttpException.BadRequest($"Missing query field {fieldName}.");
return Task.FromResult(data.GetValues(fieldName) ?? Array.Empty());
}
Task