I have a model that contains a datetime field.
The column in the DB which it prepresents is of datatype 'date', so it has no time value.
The model date field is bound to a jquery-ui datepicker in my view.
When the page loads, it has time value: 1989/02/14 12:00:00 AM
How can I prevent the time value from being added?
Do I have to manually strip out the time portion with jQuery for every date field?
EDIT:
There is no point in editing the model, when the page loads its still there
Controller:
ClientModel c = DBContext.Clients.find(id);
//Doing any kind of date formatting here to c.DateOfBirth is ignored
return PartialView("_ClientDetailsView", c);
View:
#Html.TextBoxFor(model => model.DateOfBirth , new { #class = "date-field" })
I'm thinking that the solution would be something like a model attribute or a HtmlHelper parameter.
You can use the DataType attribute for this. Decorate your DateOfBirth property in the ClientModel with it:
public class ClientModel
{
[DataType(DataType.Date)]
public DateTime DateOfBirth { get; set; }
}
Also see the DataType enum.
You can also use the DisplayFormat attribute if you the DataType attribute doesn't fit your needs:
[DisplayFormat(DataFormatString = "dd MM, yyyy")]
public DateTime DateOfBirth { get; set; }
Thanks for the help Henk
In the end I grew tired of trying to find a 'proper' solution so I wrote the following jquery function and calling it on each page as required.
function DropTimeSegments() {
$(".datepicker").each(function (index, item) {
$(item).val(FormatDate(new Date($(item).val())));
});
function FormatDate(Date) {
return Date.getFullYear() + '-' + pad(Date.getMonth(), 2) + '-' + pad(Date.getDate(), 2);
}
function pad(num, size) {
var s = num + "";
while (s.length < size) s = "0" + s;
return s;
}
Related
I have added a property to my Customer Model, created a migration and updated the database. The field created in DB is datetime.
here is my Model code
public DateTime BirthDate { get; set; }
here is the view that is actually a form where I insert date and other fields and submit the form.
<div class="form-group">
#Html.LabelFor(m => m.Customer.BirthDate)
#Html.TextBoxFor(m => m.Customer.BirthDate, "{0: dd-MM-yyyy}", new { #class = "form-control" })
</div>
and here is the Action in the controller
public ActionResult Save(Customer customer)
{
if (customer.Id == 0)
{
_context.Customers.Add(customer);
}
else
{
var customerInDb = _context.Customers.Single(c => c.Id == customer.Id);
customerInDb = customer;
}
_context.SaveChanges();
return RedirectToAction("Index", "Customers");
}
I have papulated the BirthDate field with 23/04/1976 and debug the application and check the value of customer.BirthDate which is 23/04/1976 12:00:00 AM. The date is note before 1753/1/1 but I m receiving the said exception.
I have also tried the following:
Make the field nullable by
public DateTime? BirthDate { get; set; }
the exception is gone but the date is not being saved to the database.
Removed the formate "{0: dd-MM-yyy}" from the view but in vain.
Inserted dates in different formats e.g. 23-Apr-1952, 1985-12-01 and 1987/1/2 but didn't work.
Visual Studio 2013 and Database is LocalDb of visual studio.
The fact that the error goes away by making the property nullable gives the answer. If a value was being set, then you would get exactly the same error as when the field was not nullable.
Therefore, the value is not being set, which stores a null if the field is nullable (confirmed by you saying it doesn't store the value - it's storing null).
So for a not-nullable property, when it isn't set, it will have the default value for a dot net DateTime, which is DateTime.MinValue, which would be valid if stored in an SQL server datetime2 but not in a datetime, where you get the 1753 error.
By the way, I'm assuming this LocalDb is basically SQL server, based on the 1753 error. For the record, in SQL server you should be using datetime2: DateTime2 vs DateTime in SQL Server
But this field is actually a Date, so you should be using the date SQL type.
So in summary, I suspect the BirthDate value in the Customer passed to the Save method has the value DateTime.MinValue. Now you need to work out why... (but that's a different question)
P.S. Are you using dd-MM-yyy on purpose? Should there be an extra y?
The actual problem lies in both DateTime viewmodel property and this TextBoxFor helper:
#Html.TextBoxFor(m => m.Customer.BirthDate, "{0: dd-MM-yyy}", new { #class = "form-control" })
Depending on current culture setting, this will generate plain input with specified date format which may not matched with current culture setting in server, which causing default model binder to ignore its value and uses DateTime.MinValue as default value (because it's not a nullable type), which doesn't fit for datetime column type in SQL that has minimum value of 1753-01-01 (the equivalent type of System.DateTime in T-SQL is datetime2).
The most recommended setup to create input helper for DateTime property is using DataTypeAttribute set to DataType.Date and DisplayFormatAttribute to specify the format string:
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public DateTime BirthDate { get; set; }
Then, use either EditorFor or TextBoxFor with type="date" attribute to generate date input:
#* TextBoxFor *#
#Html.TextBoxFor(model => model.Customer.BirthDate, new { #class = "form-control", type = "date" })
#* EditorFor *#
#Html.EditorFor(model => model.Customer.BirthDate, new { htmlAttributes = new { #class = "form-control" } })
Note: The same setup like above also apply for Nullable<DateTime>/DateTime? property.
Additionally you should check for IsValid property of ModelState before using SaveChanges() and return the same view when validation failed:
[HttpPost]
public ActionResult Save(Customer customer)
{
if (ModelState.IsValid)
{
if (customer.Id == 0)
{
_context.Customers.Add(customer);
}
else
{
var customerInDb = _context.Customers.Single(c => c.Id == customer.Id);
customerInDb = customer;
}
_context.SaveChanges();
return RedirectToAction("Index", "Customers");
}
else
{
// validation failed, show the form again with validation errors
return View(customer);
}
}
Related issue: ASP.NET MVC date not saving when posting
I'm running asp.net 4 mvc and I've created a DropDownList of dates that defaults to the first entry in the list. When I select an entry, I invoke a controller function and do some processing. However, when my page does the PostBack, instead of displaying the list item I selected, it displays the original default list item again.
How do I get my page to display the last item I selected from the list? I've spent two full days searching this site and the Internet for a solution but nothing I try seems to work. Any assistance would be greatly appreciated.
My Html View
#Html.DropDownList("selectList", Model.ReverseMonthsLists(),
new { #onchange = "CallChangefunc(this.value)" })
<script>
function CallChangefunc(val) {
window.location.href = "/dashboard/Report_Performance?id=" + val;
}
</script>
My ViewModel
public SelectList MonthList { get; set; }
public IEnumerable<SelectListItem> ReverseMonthsLists()
{
var selectListItems = GetDates()
.Select(_ => _.ToString("MMM yyyy"))
.Select((dateString, index) => new SelectListItem { Selected = index == 0, Text = dateString, Value = dateString })
.ToList();
return selectListItems;
}
public static IEnumerable<DateTime> GetDates()
{
DateTime startDate = new DateTime(2017, 6, 1).Date;
var currentDate = DateTime.Now.Date;
int numberOfMonthsToShow = (currentDate.Year - startDate.Year) * 12 + currentDate.Month - startDate.Month;
var dates = new List<DateTime>(numberOfMonthsToShow);
currentDate = currentDate.AddMonths(-1);
for (int i = 0; i < numberOfMonthsToShow; i++)
{
dates.Add(currentDate);
currentDate = currentDate.AddMonths(-1);
}
return dates;
}
My Controller
[RequireLogin]
public ActionResult Report_Performance(string id)
{
DateTime newDate = DateTime.Now.Date.AddMonths(-1);
if (id != null)
newDate = DateTime.Parse(id);
var aVar = Models.Reporting.ListingStatsReportingViewModel.GetStats(userCurrentService.CompanyId.Value, Models.Reporting.DateTimePeriod.Monthly, newDate);
return this.View(aVar);
}
You can change your code as follows:
Let's say your model class that is being returned by GetStats method in the Report_Performance action is MyStats which contains a string property named SelectedDateString (you need to add this property to your view model class).
Updated view markup:
#model MyStats
#Html.DropDownList("SelectedDateString", Model.ReverseMonthsLists(),
new { #onchange = "CallChangefunc(this.value)" })
<script>
function CallChangefunc(val) {
window.location.href = "/dashboard/Report_Performance?id=" + val;
}
</script>
Updated controller:
[RequireLogin]
public ActionResult Report_Performance(string id)
{
DateTime newDate = DateTime.Now.Date.AddMonths(-1);
if (id != null)
newDate = DateTime.Parse(id);
var aVar = Models.Reporting.ListingStatsReportingViewModel.GetStats(userCurrentService.CompanyId.Value, Models.Reporting.DateTimePeriod.Monthly, newDate);
//This will make sure that the model returns the correct value of the property as a string.
aVar.SelectedDateString = id;
return this.View(aVar);
}
A Html.DropDownList() works by getting data from a string property in the model which is of the same name as the name of the DropDownList itself.
In your case, you need to set the DropDownList value using javascript or jquery as it's not connected to a model property.
Let me give you an example:
A drop down list in MVC can be created by using either
#Html.DropDownListFor(m => m.PreferredContactMethod, Model.PreferredContactMethods, "")
or
#Html.DropDownList("PreferredContactMethod", Model.PreferredContactMethods, "")
In both cases, PreferredContactMethod is a string property in my model that is connected to the view - which is done by specifying #model PreferredContactModel at the top of the view.
In your case, your list name is selectList and if the specified model is connected to the view and if there's a property in the model that gets the selected date, then you need to change the name of your drop down list to it.
I hope it makes sense, if there's any issue, please comment back. I want to help with this.
The problem is here:
window.location.href = "/dashboard/Report_Performance?id=" + val;
This essential tells the browser to navigate to a new page, which is an HttpGet operation. Thus, there is no correlation between your current settings and those of a new page.
It's as if you had just gone up to the address bar and hit enter. It issues a new page with all new defaults.
There are many ways you can address this problem. The easiest would be to have some javascript that looks at the URL and extracts the id query parameter, then selects the item in the dropdown box that corresponds with the id.
Another option is to set the dropdownlist's selected value based on the ID in your controller.
In controller:
ViewBag.SelectedItem = id;
In View:
#Html.DropDownList("SelectedItem", Model.ReverseMonthsLists(), ...)
I have one Textbox in mvc4 application as below.
#Html.TextBoxFor(x=>x.dateofAction, ViewBag.filterdateTime as string, new { #id = "dateofAction", #placeholder = "Date Of Action", #class = "txtBox form-control calender validate[required]" })
I am using jquery calender for this textbox.
$(document).on('focus', '.calender', function(){
$(this).datepicker({
dateFormat: "dd/mm/yy",
changeMonth: true,
changeYear: true,
showOn: 'button',
buttonImage: '/images/icondate.png',
buttonImageOnly: true
})
});
This is my model
[DisplayName("dateofAction")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:yyyy-MM-dd}")]
public DateTime dateofAction { get; set; }
I am facing problem when first time page loads default date 1/1/0001 12:00:00 AM is displaying in textbox. Actually i want to show placeholder value.
May i know why i am not able to get placeholder value?
In order to display an empty textbox with the placeholder, you need to make your property nullable. If also want a date to be selected, then you can also decorate the property with the [Required] attribute.
Note also that your [DisplayFormat] is unnecessary and is ignoted by the TextBoxFor() method. You should also be using the [Display] attribute, not [DisplayName] Your property should be
[Display(Name= "Date of Action")]
[Required(ErrorMessage = "Please select a date")]
public DateTime? dateofAction { get; set; }
Then in the view your code should be just
#Html.TextBoxFor(x=>x.dateofAction, new { #placeholder = "Date Of Action", #class = "txtBox form-control calender validate[required]" })
and your datepicker plugin should be initialize when the DOM is rendered, not each time its focused
$('#dateofAction').datepicker({
dateFormat: "dd/mm/yy",
....
})
the DateTime is struct and value. when you pass model to view "dateofAction" has default value. two way for this challenge:
make dateofAction as nullable.
set dateofAction to DateTime.Now when create model.
Two ways to solve this problem.
set the entity Nullable by adding "?" next to the datatype of entity
like public DateTime? dateofAction { get; set; }
If you don't want to make the entity Nullable the you can add this code in the view "view.cshtml"
var variableName =
Model.Value.ToString("d") == default(DateTime).ToString("d") ? "" :
Model.Value.ToString("d");
in this case Model.Value.ToString("d"); is replaced by Model.dateofAction.ToString("d");
Use "variableName" this as value in your input field
in ToString("d"), "d" is string formatter
Learn more about string formatting here
This question already has an answer here:
Default datetime picker in visual studio 2015 showing only date picker not allowing to select time
(1 answer)
Closed 6 years ago.
So. If I have this in my model :
[DataType(DataType.Date)]
public DateTime Birthday { get; set; }
I get a nice date picker field when I invoke (can't select time though) :
#Html.EditorFor(model => model.Birthday, new { htmlAttributes = new { #class = "form-control" } })
But, if I want to record something like date and starting time of an event :
[DataType(DataType.DateTime)]
public DateTime Start { get; set; }
I get just a regular text field.
Also, I've just noticed that when I want to edit existing record, date is empty and has to be entered again even though all other fields are populated nicely.
I think you can also specify the datetime-local property in HTML.
#Html.TextBoxFor(model => model.Property, new { htmlAttributes = new { #class = "form-control", #type="datetime-local" } })
This is a pretty simple and easy way to get a date/time picker in your application.
Edit:
To get date/time to be set as the "default", you need a bit of jQuery as this isn't possible through #Value (that I know of). I use the following to set the date/time on forms.
$(document).ready(function () {
var now = new Date();
var day = (#Model.myDate.Day.ToString().Length != 2) ? "0" + #Model.myDate.Day : #Model.myDate.Day;
var month = (#Model.myDate.Month.ToString().Length != 2) ? "0" + #Model.myDate.Month : #Model.myDate.Month;
var today = #Model.myDate.Year + "-" + (month) + "-" + (day);
$('#IdOfDateElement').val(today);
});
You can save date-time as string in db or manipulate datetime value posted from UI from. See reference :
http://eonasdan.github.io/bootstrap-datetimepicker/
http://forums.asp.net/t/1975676.aspx?Tutorial+for+Adding+Datepicker+in+MVC+5
I have a MVC CRUD site that has a Date Approved Textbox. When the new entry is created it is stored properly as "dd-MM-yyyy" in the SQL Sever. When I want to update an entry the Date Required textbox contains the date AND 12:00:00AM . I'm guessing this is because SQL Server is a date datatype and .Net is a DateTime. Any idea how to get rid of the 12:00:00AM ?
Failed attempts...
I've tried adding it to my viewmodel
[DisplayFormat(DataFormatString = "{0:MM-dd-yyyy}", ApplyFormatInEditMode = true)]
[Required(ErrorMessage="Required")]
[DataType(DataType.Date)]
[Display(Name="Date Requested")]
public DateTime? Date_Requested { get; set; }
and also...
string test = Convert.ToDateTime(model.Date_Requested).ToString;
EDIT
the html textbox
#Html.TextBoxFor(model => model.Date_Requested,new {#class="datepicker" })
EDIT JQuery DatePicker
$(".datepicker").datepicker({
onSelect: function () {
$(this).valid();
}
});
you could add another property, using ToShortDateString:
public string DateRequestedShortDate
{
get
{
return Date_Requested == null ? "" : Date_Requested.ToShortDateString();
}
}
or simply set the textbox value to the ShortDateString to keep your binding
TextBoxFor does not honor format attributes (not sure if this is intended or a bug). You can either use EditorFor:
#Html.EditorFor(model => model.Date_Requested,new {#class="datepicker" })
or set the format in TextBoxFor:
#Html.TextBoxFor(model => model.Date_Requested,
new {
#class="datepicker",
#Value = Model.Date_Requested.ToString("MM-dd-yyyy")
});
Expanding on Jonesy answer from above.
public string DateRequestedShortDate
{
get
{
return Date_Requested == null ? "" : Date.Parse(Date_Requested).ToShortDateString();
}
}
Parse won't mess up the data being inserted into SQL , hope it helps.