last days I have a quite hard time to convince MVC5 project to work with dates as I would like to. After intensive googling I've tried numerous attepmts to make it work properly, but without success.
Here is the problem:
I need to display and edit dates on my webpage in format dd.MM.yyyy (i.e. 15.07.2015). For editing I also need to use jquery ui datepicker. The thing here is that I've been able to successfully set that datepicker to display date in requested format, also the jquery validation is now correctly validating the date in given format. So as for UI so far so good. The problem appeared in moment, when I clicked submit button - there was an error message like:
The value '15.07.2015' is not valid for Start Date.
After brief investigation I've found that when the date is passed to server it has switched format - instead of dd.MM.yyyy the date is treated like MM.dd.yyyy. In other words the error pops up only when the day part of date is higher than 12.
Here are some highlights from my code:
In my model for date I have this:
[Required]
[Display(Name = "Start Date")]
[DataType(DataType.Date)]
[UIHint("Date")]
[DisplayFormat(DataFormatString = "{0:dd.MM.yyyy}", ApplyFormatInEditMode = true)]
public DateTime DateStarts;
Which I believe is everything I need to do to make that date display in specified format and also force users to fill the textbox with date in right format.
As given in [UIHint("Date")], I have my own template for rendering textbox for editing date. The implementation of that template is following:
#model Nullable<DateTime>
#{
DateTime dt = DateTime.Now;
if (Model != null)
{
dt = (System.DateTime)Model;
}
#Html.TextBox("", dt.ToString("dd.MM.yyyy"), new { #class = "form-control datecontrol", type = "text", data_val_date = "Field must have format dd.MM.yyyy" })
<i class="fa fa-calendar form-control-feedback lowerzindex"></i>
}
The jquery datepicker has following implementation:
$('.datecontrol').datepicker({
onClose: function () { $(this).valid(); },
minDate: "-1M",
dateFormat: "dd.mm.yy",
});
So even the datepicker knows how the format should look like.
The last component is the validation by jquery.validation:
$.validator.addMethod(
'date',
function (value, element, params) {
if (this.optional(element)) {
return true;
};
var result = false;
try {
$.datepicker.parseDate('dd.mm.yy', value);
result = true;
} catch (err) {
result = false;
}
return result;
},
''
);
I know that the date is passed to server in some culture neutral format, but I thought that when I decorated code on numerous places with the requested format, this will ensure that the conversion into that culture neutral format will be done right. Or am I missing something else ?
Thanks
Your problem lies in the fact that you have not set proper Culture for your application. Your request end-up executing under culture that has month-day-year order (probably under en-US) causing you a problem.
The easiest solution is to set set the culture that actually has day-month-year order and . as date separator in your web.config, for example:
<configuration>
<system.web>
<globalization uiCulture="de-DE" culture="de-DE" />
...
https://msdn.microsoft.com/en-us/library/bz9tc508%28v=vs.140%29.aspx
The MVC uses current culture when parsing and binding posted data to your models/parameters.
It is advised to use same date separator across entire scope - html, client, javascript, server culture, ...
Related
I am getting an invalid ModelState when data is returned from a View using an ajax call but only for edits. I am passing a datetime value from a SQL record to the view. The date shows up just fine in a Kendo UI DateTime picker. If I make a new selection from the datetime picker, I don't get the exception, it's only if I don't make any changes do I get the invalid error. Here is what the MVC controller is showing:
The value '/Date(1387443600000)/' is not valid for RequiredByDate."
What am I missing here? First time I have ever had an issue with a datetime field like this.
EDIT: Found out the date was being formatted in the view once the controller passed it in. Here is what I had to do before using it on the page and eventually sending it back to the controller (code is verbose for debugging purposes):
var myModel = model;
var jsonDate = myModel.Header.RequiredByDate; // "/Date(1387443600000)/"
var value = new Date(parseInt(jsonDate.substr(6)));
var ret = value.getMonth() + 1 + "/" + value.getDate() + "/" + value.getFullYear();
//ret is now in normal date format "12-13-2013"
After posting an edit above I found what I think is an even better solution to the problem. Here is a function that converts the string to an actual date object:
function dateFromStringWithTime(str) {
var match;
if (!(match = str.match(/\d+/))) {
return false;
}
var date = new Date();
date.setTime(match[0] - 0);
return date;
}
I'm not sure whether this is related to jqgrid or is a webservice/postback/JSON issue, but I'll try to give as much information as I can.
I am posting the jqgrid's modal popup with the DateTime field .
When it posts back from the browser it submits the following data (as seen in Firebug):
InStock Yes
Name Desktop Computer
Note note
Ship 4
ShipDate 05-11-2013
id 1
oper edit
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string UpdateOrder(DateTime ShipDate, string Name, Stock InStock,Ship Ship, string Note,int id)
{
return "";
}
The colModel of jqgrid looks like ..
colModel:[
{name:'Id',index:'Id', width:60, sorttype:"int", editable: false},
{name:'ShipDate',index:'ShipDate',width:90, editable:true, sorttype:"date",unformat: pickDate},
{name:'Name',index:'Name', width:150,editable: true,editoptions:{size:"20",maxlength:"30"}},
{name:'InStock',index:'InStock', width:70, editable: true,edittype:"checkbox",editoptions: {value:"Yes:No"},unformat: aceSwitch},
{name:'Ship',index:'Ship', width:90, editable: true,edittype:"select",editoptions:{value:"4:FedEx;1:InTime;2:TNT;3:ARAMEX"}},
{name:'Note',index:'Note', width:150, sortable:false,editable: true,edittype:"textarea", editoptions:{rows:"2",cols:"10"}}
],
and the pickDate looks like
function pickDate( cellvalue, options, cell ) {
setTimeout(function(){
$(cell) .find('input[type=text]')
.datepicker({format:'dd-mm-yyyy' , autoclose:true});
}, 0);
}
Also the edit form style is as follows (when edit form shows up)
function style_edit_form(form) {
//enable datepicker on "sdate" field and switches for "stock" field
form.find('input[name=ShipDate]').datepicker({format:'dd-mm-yyyy' , autoclose:true})
.end().find('input[name=stock]')
.addClass('ace ace-switch ace-switch-5').wrap('<label class="inline" />').after('<span class="lbl"></span>');
However when the data is received at the server (asmx service), the datetime (ShipDate) changes to "11/05/2013 00:00:00" whereas the shipdate sent from the client is 05-11-2013 (which is correct). Any idea what's happening?
For datepicker you are using 'dd-mm-yyyy' format but on server side it converting to different format according to culture installed i.e. 'mm/dd/yyyy hh:mm:ss' with the time.
If you need the same format what you are passing from jquery you need to parse the date on server side in specified format.
DateTime time = Convert.ToDateTime("11/05/2013 00:00:00");
Console.WriteLine(time); //Default format
string format = "d/M/yyyy"; // Use this format
Console.WriteLine(time.ToString(format));
I have a View that renders a list of items, and each item contains a Date property.
<%:Html.HiddenFor(m => m.Items[j].Date)%>
A number of other properties are hidden or shown, and the user is able to enter comments against any item and save these comments to the database. It's a 'bulk edit' type View.
I've used these Views before to good effect, but I'm having a problem with the Date property because it renders thus
<input name="Items[3].Date" type="hidden" value="3/05/2012 11:56:48 AM" />
The problem is that I need to use the DateTime as a part of the primary key for this data item. I could truncate the milliseconds in the database to allow the match but there is no guarantee that there will only be one data point per second.
How do I ensure that the hidden input field for my DateTime retains all of the property's information, including the milliseconds component?
well do you really need to use
<%:Html.HiddenFor(m => m.Items[j].Date)%>
why not just keep it simple
<input type="hidden" name="Items[<%:j%>].Date" value="<%:model.Items[j].Date.ToString("dd/MM/yy/ HH:mm:ss.fffff")%>"/>
I've not had any success forcing the format of a DateTime in a HiddenFor field.
The DisplayFormat attribute can force the format for a DisplayFor field but has no effect on a HiddenFor field.
I resorted to the below no-quite-a-hack to get this to work - serialize and deserialize the ticks property to ensure the true time is retained.
public long DateTicks
{
get
{
return this.Date.HasValue ? this.Date.Value.Ticks : 0;
}
set
{
if (value == 0)
this.Date = null;
else
this.Date = new DateTime(value);
}
}
Use
<%:Html.HiddenFor(m => m.Items[j].Date.Ticks)%>
Use the DisplayFormat attribute on the Date property in your model, and spell out the milliseconds in the format string:
[DisplayFormat(DataFormatString = "{0:yyyyMMddhhmmssfff}")]
Hi I am having a problem in date.
I am having a custom dateChooser.
In the dateChooser component highlights some holidays and at the same time lists the holidays in a container.
The Problem is the date I am displaying in the container is not in ascending order could some one please help.
Link for the demo application with view source enabled
http://125.22.254.206/clients/flexdemos/calendardemo/calendardemo.html
The said logic is implemented in ExtendedDateChooser.as under custome folder.
Are you trying to sort the date in the 'holidayView' vbox?
You cant compare and sort two dates. You can use the date comparison method given below (search the web to find a better one).If the control in the vbox to display holidays is a datagrid, using
<mx:DataGridColumn
headerText="Created Date"
date="createdDt"
sortCompareFunction="date_sortCompareFunc">
</mx:DataGridColumn>
in the tag attribute will result in sortedDate
private function date_sortCompareFunc(itemA:Object, itemB:Object):int
{
/* Date.parse() returns an int, but
ObjectUtil.dateCompare() expects two
Date objects, so convert String to
int to Date. */
var dateA:Date=isoToDate(itemA.createdDt);
var dateB:Date=isoToDate(itemB.createdDt);
return ObjectUtil.dateCompare(dateB, dateA);
}
private function isoToDate(value:String):Date {
var dateStr:String = value;
dateStr = dateStr.replace(/\-/g, "/");
dateStr = dateStr.replace("T", " ");
dateStr = dateStr.replace("Z", " GMT-0000");
return new Date(Date.parse(dateStr));
}
I think, you cant sort by Date.
First, I can't see the container in your app.
My way would be to parse the date in to milliseconds since 1970
parse(date:String):Number
Then you can sort it by some logic.
BR
Frank
can any one tell me the code to validate the date field in signup form(which shd also validate the leap year and no of days in each month
That depends on the input but suppose you have a string input for the whole date then you could try something like:
try
{
DateTime parsedDate = DateTime.Parse(incomingDateString);
}
catch
{
throw new Exception("Incoming Date string could not be parsed as a DateTime");
}
Alternatively if you have three integers as strings coming in from the form then you would replace the DateTime.Parse with
DateTime parsedDate = new DateTime(Int32.Parse(yearString), Int32.Parse(MonthString), Int32.Parse(DayString));
and allow the DateTime constructor take care of the details of analyzing days of month and leap years. You could be more sophisticated and use Int32.TryParse and provide more specific error messages and checks for null strings if thats what you need.
You can make sure you get a valid date by adding a calendar control or a date picker control. This will avoid having to add extra validation just to validate this field.
If you don't want to use a calendar control or date picker, you can use DateTime.Parse and place it inside a Try, Catch block.
dateString = YourDateField.Text;
try {
dateValue = DateTime.Parse(dateString);
}
catch (FormatException) {
Console.WriteLine("Unable to convert, this is not a valid date '{0}'.", dateString);
}
Hope this helps.