0

Similar to Datetime field in MVC Entity Framework, but not quite. Their solutions also, did not fix my issue. I have a dB with seeded data and the following,

A Model with a nullable DateTime prop:

[DataType(DataType.Time)]
[DisplayFormat(DataFormatString = "{0:hh:mm tt}", ApplyFormatInEditMode = true)]
[Display(Name = "Evening Showtime")]
public DateTime? ShowtimeEve { get; set; }

A Razor Pages View called Productions.cshtml:

@model TheatreCMS.Models.Production
@using TheatreCMS.Controllers
@{
  ViewBag.Title = "Edit";
}

@Styles.Render("~/Content/Site.css")

<h2>Edit</h2>

@using (Html.BeginForm("Edit", "Productions", null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
  @Html.AntiForgeryToken()
  <div class="formContainer2">
    <div class="form-horizontal">
      <h4>Production</h4>
      <hr />
      @Html.ValidationSummary(true, "", new { @class = "text-danger" })
      @Html.HiddenFor(model => model.ProductionId)
      
      <div class="form-group">
        @Html.LabelFor(model => model.ShowtimeEve, htmlAttributes: new { @class = "control-label col-md-2 inputLabel" })
        <div class="col-md-10 formBox">
          @Html.EditorFor(model => model.ShowtimeEve, new { htmlAttributes = new { @class = "form-control" } })
          @Html.ValidationMessageFor(model => model.ShowtimeEve, "", new { @class = "text-danger" })
        </div>
      </div>
}

And a Controller ProductionsController.cs that passes the data to the View using inheritance of DBContext (It's a code first project):

[HttpGet]
public ActionResult Edit(int? id)
{
   if (id == null)
  {
      return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
   }
   Production production = db.Productions.Find(id);
   if (production == null)
   {
      return HttpNotFound();
    }

   return View(production);
}

The form on the View will not populate the data in the input field that gets created. It's creating a blank Time picker field. I need it to be a data populated time picker field. It's an Edit View, so the goal is to have all the fields populated with the data, showing the client what they would be changing it from.

I ran the debugger, step by step, checking output values. It's passing the DateTime value to the View from the Controller, but it's getting lost somewhere after that.

This is what it looks like rendered: An empty time picker input field

Scott K.
  • 191
  • 1
  • 2
  • 12
  • 1
    What does the rendered HTML look like – Vince Aug 27 '20 at 06:52
  • 1
    I think this is because the variable that you declare is of `Datetime` and the type that you force to specify is `Datatype.time` – Abdul Haseeb Aug 27 '20 at 07:05
  • @AbdulHaseeb If I'm not mistaken, the `DataType.Time`, just like `DataType.Date`, are inherited from the base `DataType.Datetime `. At least for `[DataAnnotations]`, that is. I know there is no "Time" data type, at least not natively, in C#. That would just be DateTime, then formatted with a `DateTime.ToString("hh:mm tt")`. – Scott K. Aug 27 '20 at 08:53
  • @Vince The original html rendered as ``, but after changing `{0:hh:mm tt}` to `{0:hh:mm}` in the `[DataAnnotation]`, it sent it as a 24 hr. formatted time, which is what it needed, thus correctly rendering `` instead. – Scott K. Aug 27 '20 at 09:01

2 Answers2

1

I will give you some advice,the problem is should be one of them.

Change datetime format like this DataFormatString = "{0:hh:mm}"

When I look your get action, I noticed to you are using entitiy but your view page model is a model. You should convert entity data to your model and return with your view page model. But your model and entity is a same class, this shouldn't be the problem. For example your action;

[HttpGet]
    public ActionResult Edit(int? id)
    {
       if (id == null)
       {
          return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
       }
       Production production = db.Productions.Find(id);
       if (production == null)
       {
          return HttpNotFound();
       }
       else
       {
          var productionModel = new Production();//TheatreCMS.Models.Production
          productionModel.ShowtimeEve = production.ShowtimeEve;
          //other converts here

       }
    
       return View(productionModel);
    }

My other advice, try use this code in view;

@Html.TextBoxFor(m => m.ShowtimeEve, new { @class = "form-control" })
Mcan_Cicek
  • 234
  • 2
  • 7
  • Thanks for the insight into using Entity Framework better. Unfortunately, I don't control how the program is structured. I'm just the newbie, squashing bugs atm. – Scott K. Aug 27 '20 at 08:45
  • Not a problem, just set a alert your view and look model.ShowtimeEve with this script; $(document).ready(function () { alert(@Model.ShowtimeEve)} – Mcan_Cicek Aug 27 '20 at 08:59
1

I was able to find the answer. I was over complicating the question. While everyone provided good answers and insights, the real issue was an HTML5 issue and how the value attribute is sent to the view. The format for the value attribute on a form input tag needs to be in the 24 hr. format, not 12 hr.

So by merely changing:

[DisplayFormat(DataFormatString = "{0:hh:mm tt}", ApplyFormatInEditMode = true)]

to

[DisplayFormat(DataFormatString = "{0:HH:mm}", ApplyFormatInEditMode = true)]

The value sent to the Production's Edit View's input element is now rendered in the 24 hr. format allowing the time picker to correctly re-format back to a 12 hr. view.

It was right there in the inspector all along! Chrome inspector view for debugging

Thanks for everyone's help. I'm new to C#, let alone ASP.NET Entity MVC, so the support is greatly appreciated.

Scott K.
  • 191
  • 1
  • 2
  • 12