简体   繁体   中英

Date parameter in controller action

I'm writing an API in dotnet core. I would like my controller action to take a date (eg. '2019-11-12') as a parameter, so the user doesn't have to provide a full datetime .

I have the following:

[HttpGet]
public async Task<ActionResult<IEnumerable<DogDto>>> GetDogsForKennelOnDate([FromQuery]string kennelName, [FromQuery]DateTime birthDate)
{...}

It seems to me that this is probably a common use case, but I haven't been able to find a solution on SO. Can you help?

EDIT:

Should I take a string as parameter and then create a new DateTime from this string ? Is this the right way to do it?

The reason why you get a compilation error for this:

[HttpGet]
public async Task<ActionResult<IEnumerable<DogDto>>> GetDogsForKennelOnDate([FromQuery]string kennelName, [FromQuery]DateTime.Date birthDate)
{...}

is because the compiler is expecting you to define the data type for the birthDate parameter, but DateTime.Date is not a data type, but a property of the DateTime data type.

Now consider this, tested on .NET Core 2.2:

[HttpGet]
public async Task<ActionResult<IEnumerable<DogDto>>> GetDogsForKennelOnDate([FromQuery]string kennelName, [FromQuery]DateTime birthDate)
{...}

The query string parameter:

birthDate=2019-11-12

binds successfully to the birthDate parameter in the action (with 0 for the hours, minutes and seconds). So I think your assumption that the user has to provide the full date and time is wrong.

Note: The DateTime.Date property is itself a DateTime with the time value set to 12:00:00 midnight (00:00:00); see https://docs.microsoft.com/en-us/dotnet/api/system.datetime.date?view=netcore-2.2 .

Edit: rather than making it impossible for the user to include the time in the query string parameter, you can instead ignore it (my preference as it is user-friendly):

[HttpGet]
public async Task<ActionResult<IEnumerable<DogDto>>> GetDogsForKennelOnDate([FromQuery]string kennelName, [FromQuery]DateTime birthDate)
{
    DateTime birthDateDate = birthDate.Date;
}

Or you could validate that the hours, minutes and seconds are 0, and create a model state error if they are not (not so user friendly). You can do this using a custom validation attribute:

public sealed class DateAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (validationContext == null)
        {
            throw new ArgumentNullException(nameof(validationContext));
        }

        if (!(value is DateTime))
        {
            return new ValidationResult($"Not a DateTime object ({value}).");
        }

        DateTime date = (DateTime)value;

        if (date.Date != date)
        {
            return new ValidationResult($"Do not specify the time ({value}).");
        }

        return ValidationResult.Success;
    }
}

Usage:

[HttpGet]
public async Task<ActionResult<IEnumerable<DogDto>>> GetDogsForKennelOnDate([FromQuery]string kennelName, [FromQuery] [Date] DateTime birthDate)
{
    ...
}

This will now succeed validation:

birthDate=2019-11-12

But this will fail:

birthDate=2019-11-12 11:22:33

However, this will still succeed:

birthDate=2019-11-12 00:00:00

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM