0

In my Razor Pages .NET Core 3.1 application I have the following simple form

<form method="post" id="formReport">
  <div class="form-group">
    <label asp-for="Parameters.From" class="control-label"></label>
    <input id="txtFrom" asp-for="Parameters.From" type="text" class="form-control" style="width:90%;" />
  </div>
  <button type="submit" class="btn btn-primary btn-sm" title="Show report">
    <i class="far fa-eye"></i> Show Report
  </button>
</form>

txtForm is a date input field implemented using DateTimePicker jQuery plugin (https://xdsoft.net/jqplugins/datetimepicker/).

var from = $('#txtFrom').datetimepicker({
            format: 'd/m/Y H:i',
            formatDate: 'Y/m/d',
            formatTime: 'H:i',
            defaultTime: '06:00',
            mask: '39/19/9999 29:59',
            monthChangeSpinner: true,
            onChangeDateTime: function (dp, $input) {
                console.log($input.val());
            }
       });

The output from console.log above when I enter as date 13/02/2022 06:00 is the same: 13/02/2022 06:00. So, I guess, this is the value submitted via POST. But on server-side I get "0001-01-01T00:00:00".

The code works fine when run in Debug mode from Visual Studio, or when I deploy it to a local web server. But when the app is deployed to production site using Docker the form submission doesn't work. Submitted value is converted to "0001-01-01T00:00:00".

This is the Dockerfile I am using:

FROM mcr.microsoft.com/dotnet/aspnet:3.1-bionic-arm64v8 AS base
WORKDIR /app
EXPOSE 80

FROM mcr.microsoft.com/dotnet/sdk:3.1-bionic-arm64v8 AS build
WORKDIR /src
COPY ["myApp.Web/myApp.Web.csproj", "myApp.Web/"]
RUN dotnet restore "myApp.Web/myApp.Web.csproj"
COPY . .
WORKDIR "/src/myApp.Web"
RUN dotnet build "myApp.Web.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "myApp.Web.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .

# Create a folder for saving images; this folder exists in container filesystem
# and has to be mounted to folder of the host filesystem inside docker-compose
RUN mkdir -p /app/images

ENTRYPOINT ["dotnet", "myApp.Web.dll"]

For some reason when date is submitted it is not properly converted to a DateTime value by the model binder. Any ideas what I could do to solve the issue?

Giorgos Betsos
  • 71,379
  • 9
  • 63
  • 98
  • Most likely the date format isn't recognised by JS. Note that only `mm/dd/yyyy` and `yyyy/mm/dd` string formats will be parsed by the `Date()` object constructor. [Demo](https://jsfiddle.net/une2cykv/) of this in action – Rory McCrossan Feb 14 '22 at 16:23
  • @RoryMcCrossan But the code works when deployed to a local server, or when run in debug mode from visual studio. In these cases I'm getting the correct DateTime value on the server side. – Giorgos Betsos Feb 14 '22 at 17:02
  • That means that the datetime format is being changed by the culture setting of the server. You need to explicitly set the format when sending the value to the client side. – Rory McCrossan Feb 14 '22 at 17:23
  • @RoryMcCrossan And how can I do this since I'm using Docker? – Giorgos Betsos Feb 14 '22 at 17:27
  • Where you set the value of `txtFrom`: `yourDate.ToString("yyyy-MM-dd")`. Again, I'm just guessing from the behaviour you describe as you've not shown any of the relevant code, or confirmed the date format difference between the two servers as that would be the first logic debugging step – Rory McCrossan Feb 14 '22 at 17:29
  • @RoryMcCrossan The value of `txtFrom` is set from the plugin, it's `13/02/2022 06:00` in the example I've given. This value is submitted to the server. – Giorgos Betsos Feb 14 '22 at 18:30
  • In your ASP.NET MVC Model, decroate the `DateTime` property with the appropriate data annotation attribute (something like `[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy HH:mm}")]`) – Heretic Monkey Feb 14 '22 at 19:08
  • The answer to the question of "why is this happening" is the same as [Why DateTime TryParse is returning date as {01/01/0001 00:00:00}?](https://stackoverflow.com/q/58285324/215552). – Heretic Monkey Feb 14 '22 at 19:14
  • Similar question/answer: [Working with Datetime & date picker](https://stackoverflow.com/q/24184073/215552) – Heretic Monkey Feb 14 '22 at 19:20

2 Answers2

1

Comments from @Heretic Monkey helped me find a simple solution to my problem. I converted my form view model class from:

public class ReportFormViewModel
{
    public DateTime From { get; set; }
    public DateTime To { get; set; }       
}

to:

public class ReportFormViewModel
{
    public string From { get; set; }
    public string To { get; set; }

    public DateTime DateFrom
    {
        get
        {
            return DateTime.ParseExact(From, "dd/MM/yyyy HH:mm", 
                                         CultureInfo.InvariantCulture);
        }
    }

    public DateTime DateTo
    {
        get
        {
            return DateTime.ParseExact(To, "dd/MM/yyyy HH:mm",
                                         CultureInfo.InvariantCulture);
        }
    }

}

So the value submitted is not converted to DateTime by the model binder. Instead I explicitly parse the string received using the client side date format.

Giorgos Betsos
  • 71,379
  • 9
  • 63
  • 98
1

Just rewrite this model like: [Make nullable by using ? ]

public class ReportFormViewModel
{
    public DateTime? From { get; set; }
    public DateTime? To { get; set; }       
}

That's it.

Subarata Talukder
  • 5,407
  • 2
  • 34
  • 50