MVC2 client/server validation of DateTime/Date using DataAnnotations - c#

The following are true:
One of my columns (BirthDate) is of type Date in SQL Server.
This very same column (BirthDate) is of type DateTime when EF generates the model.
I am using JQuery UI Datepicker on the client side to be able to select the BirthDate.
I have the following validation logic in my buddy class:
[Required(ErrorMessageResourceType = typeof(Project.Web.ValidationMessages), ErrorMessageResourceName = "Required")]
[RegularExpression(#"\b(0?[1-9]|1[012])[/](0?[1-9]|[12][0-9]|3[01])[/](19|20)?[0-9]{2}\b", ErrorMessageResourceType = typeof(Project.Web.ValidationMessages), ErrorMessageResourceName = "Invalid")]
public virtual DateTime? BirthDate
{
get;
set;
}
There are two issues with this:
This will not pass server side validation (if I enable client side validation it works just fine). I am assuming that this is because the regular expression doesn't take into account hours, minutes, seconds as the value in the text box has already been cast as a DateTime on the server by the time validation occurs.
If data already exists in the database and is read into the model and displayed on the page the BirthDate field shows hours, minutes, seconds in my text box (which I don't want). I can always use ToShortDateString() but I am wondering if there is some cleaner approach that I might be missing.
Thanks

1: This is easily solved by changing DateTime to be non-nullable, meaning the datetime value entered must be parse-able and therefore valid, and then use the:
[DataType(DataType.Date)]
attribute instead of the regular expression. This will make sure the field is required and must be parse-able.
2: This is a templating issue. The easy way is to create a custom Date.ascx template inside of /Views/Shared/EditorTemplates that calls ToShortDateString() and will hook up your jquery datepicker.
This is what mine looks like:
<%# Import Namespace="System.Web.Mvc.Html" %>
<%
string displayText = string.Empty;
if (Model != null)
{
if (DateTime.Parse(Model.ToString()) != DateTime.MinValue)
displayText = DateTime.Parse(Model.ToString()).ToShortDateString();
}
%>
<%= Html.TextBox("", displayText, new { #class = "date-box" })%>

Related

How to pre-populate a 'date' input field with Razor/C# values

I have a 'date' type input, and I'm trying to get the Razor code to pre-fill the date with information that the server already has, because it's for an Edit field on an MVC ASP.NET Core app I'm working on.
The code I'm using is:
<input type="date" name="DeliveredDate" id="DeliveredDate" value='#Model["order"].DeliveredDate.ToString("mm/dd/yyyy")'>
I can get the code to show the string in any other part of the page, but is there a trick to getting that same string to populate the value of a date field? All my googling hasn't turned up anything particularly helpful.
You can use either #Html.TextBox() or strongly-typed #Html.TextBoxFor() helper to do so, by either setting DisplayFormatAttribute or date format directly in the helper:
Viewmodel property
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
public DateTime DeliveredDate { get; set; }
View
#Html.TextBox("DeliveredDate", Model["order"].DeliveredDate, "{0:MM/dd/yyyy}", new { type = "date" })
#Html.TextBoxFor(model => model.DeliveredDate, "{0:MM/dd/yyyy}", new { type = "date" })
Or using EditorFor by setting date format, which automatically appends type = "date" attribute:
#Html.EditorFor(model => model.DeliveredDate)
If you're using tag helper, just set asp-for attribute:
<input asp-for="DeliveredDate" type="date" />
Notes:
1) Make sure that you're already set the date value inside controller action, e.g. model.DeliveredDate = DateTime.Now (model has type of Model["order"]).
2) The latter approach requires setting DisplayFormatAttribute in viewmodel property because there's no string formatting parameter to set the format from EditorFor or tag helper itself.
The correct command ended up being
#Model["order"].DeliveredDate.ToString("yyyy-MM-dd")
but then I learned from my instructor that there's a date range that is able to be displayed, and it varies with different platforms, but I'm pretty sure the range that can be displayed is between the years 1950, and 2049.
Once I actually set the dates it was supposed to display to one that was within that range, it worked, and if I tried to display a date outside of that range, it would break again.

How can I sort a shortdate string as if it were a date in an MVC 5 model?

I have a field in an MVC 5 C# model that maps to an SQL table. The source data is of type nvarchar(10) for the needs of others who also use the table.
In the latest iteration, the users also want to be able to sort by this column, which means that I need to convert this to a datetime value (so it can be correctly sorted) and display as a shortdate.
I know I can make this field private and create a separate public function that casts this as a date, but I was wondering if there was a more compact way I could do this all in one function. I have searched around, but not seen any examples of what I am describing. Is this even possible?
Stated another way, I want to display this as a shortdate but sort it as a date. Am I on the right track, or am I missing something?
[Required]
[StringLength(10)]
[Display(Name = "Entry Date")]
[DisplayFormat(DataFormatString="{0:d}")]
public string EntryDate { get; set; }
If the data represents a date, add a property which is a date:
public DateTime? EntryDateValue
{
get
{
DateTime dateValue;
if (DateTime.TryParse(EntryDate, out dateValue))
return dateValue;
return null;
}
set
{
// parse "value" to the string format you want
// and store it in EntryDate
}
}
Bind the view to that property instead, formatting the output with .ToString("...") as needed, and allow the sorting to take place on the DateTime? rather than on the string. Essentially creating a pass-through property for the application code, obscuring the backing "stringly-typed" value.
In general, it's easier to tweak the correct backing data for text display than it is to tweak the text display to act like backing data.

How to format the DateTime Property using MVC3 Razor?

I am having the following Razor Code to Render TextBox for ValidFrom Property of DateTime type.
#Html.TextBox("ValidFrom", (Model.ValidFrom.ToString("dd-MMM-yyyy")), new { #class = "FrmTextBox" })
And the same is rendering the Default Date(01-01-0001 00:00:00) as '01-Jan-0001' while opening of my Form and my values are also getting stored into the database once I submitted the form.
But, If I try to update the ValidFrom Property of the Subjected Record from the Database then the Record returning as 02-10-2012 00:00:00 but the Date is being displayed in the 02/10/2012 00:00:00 format only.
How to format the above DateTime Value into 02-Oct-2012.?
Could anyone please help..
Thanks in Advance.
Try to use the following attribute in your model.
[DisplayFormat(ApplyFormatInEditMode = true,
DataFormatString = "specify_format_string_here")]
Then, on your view : #Html.EditorFor(m => m.ValidFrom). More about editor templates you can find for example here. For your requirements format string should be smth like this:
"{0:dd-MMMM-yyyy}"

ASP.NET MVC 3 Binding & Validating Date to html textbox control

I have a SmallDateTime field in my Sql Server 2008 database to store users Birthdays.
On my 'Edit Profile' web page, I have a standard textbox which I want to bind the 'Birthday' date to (excluding the time as this is not required). At present I am binding to the textbox but it is rendering the full Date and Time.
In addition, when the user updates their profile, I want to be able to validate the Birthday textbox, ensuring that the value specified complies to dd/mm/yyyy, and any deviation from that is highlighted via my existing validation summary on the page.
How do I go about:
a) configuring the Birthday property in my ViewModel to display in dd/mm/yyyy format (excluding the time).
b) validate Birthday (based on dd/mm/yyyy format) when the user submits the form?
[DisplayFormat(DataFormatString="{0:dd/MM/yyyy}", ApplyFormatInEditMode=true)]
public DateTime DateOfBirth { get; set; }
This should give you the automatic formatting on the field (without you having to manually do it) and also the validation.
I usually use a string property paired with the DateTime object, something like
public string MyDateStr
{
get
{
return MyDateDate == null ? "" : MyDateDate.ToShortDateString();
}
set
{
// Usually a tryParse for the string value
}
}
I know that is not the canonical way, but up to now, is the fastest I've found.
HTH
M.
EDIT: for the validation stuff see this:other question on SO
a) you can use .ToShortDateString to render your datetime without time. Format still depends on globalization defaults.
b) to validate, you could do it with Data Annotations on your model like this:
[DataType(DataType.DateTime, ErrorMessage = "Please enter a valid date in the format dd/mm/yyyy")]
public DateTime Birthday { get; set; }

RangeAttribute Data Annotation Not Working as Expected

I am developing an ASP.NET MVC2 application in which I have a User class with a property named SecurityQuestionID as follows:
public class User
{
[RangeAttribute(1, 5, ErrorMessage = "Security Question is required")]
[DisplayName("Security Question")]
public virtual int SecurityQuestionID { get; set; }
}
The SecurityQuestionID field gets populated from a dropdown in the view as follows:
<%: Html.LabelFor(model => model.SecurityQuestionID)%>
<%: Html.DropDownListFor(model => model.SecurityQuestionID, ViewData["securityQuestions"] as SelectList,"Choose a Question",null) %>
<%: Html.ValidationMessageFor(model => model.SecurityQuestionID)%>
The controller sends the security questions to the view by using view data as follows:
ViewData["securityQuestions"] = new SelectList(_securityQuestionService.GetAll(), "SecurityQuestionID", "Question");
If I don't select a question from the dropdown and hit the submit button, then "The Security Question field is required." message is displayed instead of "Security Question is required". Can anyone help me understand what I am doing wrong here?
If the integer is not nullable, then it is required by default. So the range validation isn't failing but Required validation is failing.
You may want to specify a separate error message for when it is required by adding a required attribute.
[Required(ErrorMessage="Security Question is required")]
It's probably throwing that error because it is a required field. See http://forums.asp.net/p/1391688/2977493.aspx. This is consistent with the fact that the field in question is defined as an int, and not an int?, so it cannot assume a null value.
In other words, it's not hitting your range validator.

Categories

Resources