Validate textbox to accept only valid datetime value using DataAnnotations in mvc3 - c#

I want to validate a textbox to accept datetime value using DataAnnotations in MVC3. But I don't have any idea how to do it. Given below is what I'm trying to accomplish my requirement and it's not working.
[DataType(DataType.DateTime, ErrorMessage = "Invalid Datetime")]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy HH:mm}")]
[Display(Name = "Start Datetime")]
public DateTime? StartDateTime { get; set; }
As When I click on submit button after filling corrupted data first problem is that form get post and later it shows the message that "Invalid date" and second if I enter just date without time still form get post but this time it does not shows the message which is also wrong.
So I just want to know how can I validate my textbox to accept datetime in "dd/MM/yyyy HH:mm" format only using MVC DataAnnotations .

1. Your client side validation is not working. You are seeing error message after the form is submitted - means client side validation is not working properly. To make the client side validation work, ASP.NET MVC assumes that you have jquery.validate.js and jquery.validate.unobtrusive.js referenced on the page. You can download them using NuGet Package Manager on your Visual Studio.
2. Date field is not being validated. You are expecting the DisplayFormat to validate the date format for you. But actually it does not. That is more of about displaying your date on the View.
In order to validate the date format, you need to use your own custom Attribute. Or you can simply use RegularExpression attribute. The most simple example looks like this:
[RegularExpression(#"\d{1,2}/\d{1,2}/\d{2,4}\s\d{1,2}:\d{1,2}", ErrorMessage = "")]
Or if you want to make a custom attribute, then:
public class DateFormatValidation : ValidationAttribute{
protected override bool IsValid(object value){
DateTime date;
var format = "0:dd/MM/yyyy HH:mm"
bool parsed = DateTime.TryParseExact((string)value, format, System.Globalization.CultureInfo.InvariantCulture, DateTimeStyles.None, out date)
if(!parsed)
return false;
return true;
}
}
Then use it like:
[DataType(DataType.DateTime, ErrorMessage = "Invalid Datetime")]
[DateFormatValidation]
[Display(Name = "Start Datetime")]
public DateTime? StartDateTime { get; set; }

I got it from diff website, saying its a problem in chrome and he has fixed it by applying this code.
So check first if it works in firefox then you might be forced to apply this code, however this code skips checking the date format.
$.validator.methods["date"] = function (value, element) { return true; }

Related

How do I handle multi line AddModelError Errors?

I'm trying to check for multiple errors on my form. Here is the code I have:
var hasErrors = false;
var sb = new StringBuilder();
if (string.IsNullOrEmpty(creditCard.CardNumber))
{
hasErrors = true;
sb.AppendLine("Credit card number is required.");
//ModelState.AddModelError("PaymentAmount", "Credit card number is required.");
}
if (string.IsNullOrEmpty(creditCard.ExpirationDateMonth) || string.IsNullOrEmpty(creditCard.ExpirationDateYear))
{
hasErrors = true;
// ModelState.AddModelError("PaymentAmount", "Expiration date is required.");
sb.AppendLine("Expiration date is required.");
}
if (string.IsNullOrEmpty(creditCard.NameOnCard))
{
hasErrors = true;
// ModelState.AddModelError("PaymentAmount", "Name is required.");
sb.AppendLine("Name is required.");
}
decimal amt = 0;
creditCard.PaymentAmount = creditCard.PaymentAmount.Replace("$", string.Empty);
if (!decimal.TryParse(creditCard.PaymentAmount, out amt))
{
hasErrors = true;
//ModelState.AddModelError("PaymentAmount","Amount is invalid.");
sb.AppendLine("Amount is invalid.");
}
if (hasErrors)
{
ModelState.AddModelError("PaymentAmount", sb.ToString().Replace(Environment.NewLine,"<br>"));
return View("CreditCard", creditCard);
}
I'm trying to get AddModelError to display in multiple lines but I'm not having any luck. It's displaying the <br> as text on the screen instead of rending a break.
I had it where the error was being submitted individually but you'd have to submit the form multiple times before you got the errors on screen. That's why the AddModelError is commented out in each line.
Is there a way to display multiple lines on the AddModelError or is there a better way to handle this?
Thanks for the help!
You should call ModelState.AddModelError for each of the errors you have in your controller, IMHO, it is not a good practice to mix your validation logic with the way things are rendered in the user interface. In fact, the MVC pattern is all about separating the three concerns, the model (data), the controller (logic, such as validation) and the views (the user interface).
So I would do something like this:
if (string.IsNullOrEmpty(creditCard.CardNumber))
{
ModelState.AddModelError("PaymentAmount", "Credit card number is required.");
}
if (string.IsNullOrEmpty(creditCard.ExpirationDateMonth) || string.IsNullOrEmpty(creditCard.ExpirationDateYear))
{
ModelState.AddModelError("PaymentAmount", "Expiration date is required.");
}
if (string.IsNullOrEmpty(creditCard.NameOnCard))
{
ModelState.AddModelError("PaymentAmount", "Name is required.");
}
[…]
Then in your view, you can use the following HTML helper to render each error in a list:
If you are using ASP.NET Core:
<div asp-validation-summary="ValidationSummary.ModelOnly"></div>
If you are using the previous versions of ASP.NET MVC:
#Html.ValidationSummary()
This will generate HTML that you can style using CSS.
See here for more info if you are using asp.net core or here for an example if you are using the previous version of ASP.NET MVC.
If you want to display the errors in a different way you can access the errors directly in your view or even better, roll your own helper, see the answers to this question: How do I get the collection of Model State Errors in ASP.NET MVC?

c# -ModelState.IsValid returns false only when resource language changed?

I have one field on my razor view as following
#Html.TextBoxFor(model => model.Duration, new { #class = "form-control txtSite input-large rounded-custom", name = "Duration", #type = "number", min = "0", id = "durationId", required = "true", Tabindex = "1", value = "0" })
#Html.ValidationMessageFor(model => model.Duration, "", new { style = "color: red" })
I used entity model structure in MVC .The field duration is defined in database table "Activity" (Same model i used on razor) as Float. But the entity metadata shows it as Double as follows.
public Nullable<double> Duration { get; set; }
I used partial class as Activity.cs for required validations as follows
[MetadataTypeAttribute(typeof(Activity.Metadata))]
public partial class Activity
{
internal sealed class Metadata
{
[Required(ErrorMessageResourceType = typeof(Resources.Common), ErrorMessageResourceName = "PleaseEnterDuration")]
public Nullable<double> Duration { get; set; }
}
}
on Controller my code is like this
[HttpPost]
public ActionResult AddActivity(Activity model)
{
if (ModelState.IsValid)
{
//Some Code
}
}
The strange is my code works well for float values when my Resource language to display labels is English and its not working when i change it into another language (french).here ModelState.IsValid returning false. And I am getting error as
"The value 3.5(any float value) is invalid for Duration."
how to fix it for another resource language?. Any help will be appreciated
You are getting that error because your site's culture is set to a language (French) that does not use a dot . as a decimal separator. However the entry for Duration has a dot in it so your model's state is evaluating to invalid.
In other words your site (server side) is in French culture but the browser or whatever client you are using is NOT in French.
Fix
You need to synch the language of the client and the server ON EVERY REQUEST: Make sure your code to set the culture is executed for each request and not just on application startup. The user can switch languages between requests. Setting CurrentCulture to the appropriate language will use that language's numeric formatting, datetime formatting etc.
Additionally, it is suggested but not required to fix your issue, you should also set the CurrentUICulture, it will get labels, messages etc. from your resource file for the language (If you have any resource files).
Follow #orhun.begendi answer above to set the above 2 items.
You can easily override your global.asax.cs file like this
protected void Application_AcquireRequestState(object sender, EventArgs e)
{
//Create culture info object
CultureInfo ci = new CultureInfo("en");
if(Request.Url.Host.Equals("yourdomain.com", StringComparison.InvariantCultureIgnoreCase))
{
ci = new CultureInfo("fr"); //in your case
}
System.Threading.Thread.CurrentThread.CurrentUICulture = ci;
System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name);
}
Also you can set in begin_request method.
Further information you can check this link
https://www.codeproject.com/articles/778040/beginners-tutorial-on-globalization-and-localizati

How can I modify a form field value during form submission?

I'm developing a form using ASP.NET form controls. One of the form fields is Date of Birth. The date format is in dd/mm/yyyy. What I need to do is actually convert this form field to mm/dd/yyyy once the user submits the form but before the data goes to the server because the system the form data is going to is forcing US date formats (mm/dd/yyyy) which I can't control, hence all date formats in dd/mm/yyyy will be reversed so they will be incorrect. So I need to actually switch it before hand, so its actually reversed back to the correct format. Here's what I've wrote in order to switch the value.
string userDOB = Request.Form["txtDOB2"];
DateTime convertedDOB = Convert.ToDateTime(userDOB);
txtDOB2.Text = convertedDOB.ToString("MM/dd/yyyy");
Note: I am checking to make sure the Date of Birth field not null or empty etc, just posting the specific code related to my question.
I'm running this in code behind via a submit button click action. So far, a test label just appends the switched date format value to confirm its working. However I'm unsure how to switch the form value itself so it ends up in the actual posted form data. Request.Form is read only, so I don't know how to assign the modified date to the form field value.
Another potential problem is the form action is to an external source, outside of the domain the form is running on.
This would be how I'd attack it:
FormatDatesModule.cs
public class FormatDatesModule : IHttpModule
{
private static readonly Regex dateFilter = new Regex(#"^(?<d>\d{2})\/(?<m>\d{2})\/(?<y>\d{4})$", RegexOptions.Compiled);
public void Init(HttpApplication context)
{
context.BeginRequest += (sender,e) => {
HttpRequest request = ((HttpApplication)sender).Request;
if (request.QueryString.Count > 0)
{
this.FormatDatesInCollection(request.QueryString);
}
if (request.HttpMethod == "POST" && request.Form.Count > 0)
{
this.FormatDatesInCollection(request.Form);
}
};
}
private static void FormatDatesInCollection(NameValueCollection parameters)
{
// Bypass readonly
PropertyInfo isReadOnly = parameters.GetType().GetProperty("IsReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
isReadOnly.SetValue(parameters, false, null);
for (var i = 0; i < parameters.Count; i++)
{
Match dateMatch = dateFilter.Match(parameters[i]);
if (dateMatch.Success)
{
parameters[i] = String.Join("/", dateMatch.Groups["m"].Value, dateMatch.Groups["d"].Value, dateMatch.Groups["y"].Value);
}
}
isReadOnly.SetValue(parameters, true, null);
}
public void Dispose()
{
}
}
web.config
<configuration>
<system.web>
<httpModules>
<add name="FormatDatesModule" type="FormatDatesModule"/>
</httpModules>
</system.web>
<system.webServer> <!-- IIS 7 Integrated Mode -->
<modules>
<add name="FormatDatesModule" type="FormatDatesModule"/>
</modules>
</system.webServer>
</configuration>
You can write this code on button click event.
for e.g
textBox1.Text="31/03/2014"
then
Button_click()
{
DateTime MyDateTime = new DateTime();
MyDateTime = DateTime.ParseExact(textBox1.Text, "MM/dd/yyyy", null);
textBox2.Text = MyDateTime.ToString("dd/MM/yyyy");
}
OR Directly you can use
textBox2.Text=(DateTime.ParseExact(textBox1.Text, "MM/dd/yyyy",null).ToString("dd/MM/yyyy"));
First you have to Convert it to DateTime format, then again in string. Hope that would be helpful for you.
After reviewing everything I've decided to use a WebRequest:
http://msdn.microsoft.com/en-us/library/debx8sh9.aspx
With the form action being an external URL (not on the same domain) I have come to the conclusion I am unable to modify the form data. However, by allowing the form to postback and specifying the form action and everything else in code behind I'm able to specify the DOB value to send, using Himanshu's DOB conversion method, I was able to POST a form with the DOB switched.

RegularExpression validation not working on model

I have the following code:
public class Register
{
[RegularExpression(#"^\w+#[a-zA-Z_]+?\.[a-zA-Z]{2,3}$", ErrorMessage = "eMail is not in proper format")]
[Required(ErrorMessageResourceName="Name Required"), ErrorMessageResourceType = typeof(ErrorMessages))]
public string Email{ get; set; }
}
Email that i tried: asd#asd.com is valid but it fail the validation.
The required is working, but the regular expression is failing. Even if I enter a valid email address, it will still say that email is not in proper format.
Anything I missed here? Thanks in advance!
EDIT
This regex validator is working on my other mvc application by using Resources.resx. So I think what is wrong here is how I declared it on my model class.
Regex regx = new Regex(#"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|"
+ #"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)"
+ #"#[a-z0-9][\w\.-]*[a-z0-9]\.[a-z][a-z\.]*[a-z]$");
/* declare in public and validate for your mail text box */
This is solved. I accidentally put the wrong regex on my code:
"^\w+#[a-zA-Z_]+?\.[a-zA-Z]{2,3}$
instead of:
#"^\w+#[a-zA-Z_]+?\.[a-zA-Z]{2,3}$
Now I will focus on to make the best email regex. Thanks!

WebClient SendValues() method changes datetime value

I use WebClient class to send a response acknowledge message in an mvc 3 project. Message is sending from one action method on a project to another projects action method.
Surprisingly the date parameter is 3 hours later, on recieving data.
For example if my sending date is receving data is "2012-08-14 13:42:50Z" i see "2012-08-14 16:42:50Z" on the other side.
Here is a simplified code sample of my case;
NameValueCollection ack = new NameValueCollection();
ack.Add("RESID", form.RESPONSE.ID.ToString());
ack.Add("A_DateTime", DateTime.Now.ToString("u")); //2012-08-14 13:42:50Z
using (var client = new WebClient())
{
client.Encoding = System.Text.Encoding.UTF8;
var result = client.UploadValues("http://localhost:11578/HPM/ResponseAck", ack);
}
//HPM Controller:
ResponseAck(HttpPostResponseAckMessage response)
{
//Here response.Date vale is 2012-08-14 16:42:50Z ???
}
It seems to me its about sneaky little serialization monsters changing it cause of some culture specific issue. But i don't know the real cause so the solution.
Edit:
public class HttpPostResponseAckMessage
{
public int RESID { get; set; }
public DateTime A_DateTime { get; set; }
}
You should either change the culture of the current thread or convert and process all dates in a fixed format such as UTC.
You can change the current culture of the thread using the following code:
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-EN");
Ok, I think its about expecting mvc model binder to parse a formated datetime.
With the "u" format model binder thinks the datetime is UTC.
So my solution will be changing the type of property A_DateTime to string and will parsing it internaly.
Hope this helps someone else like me.
Thanks all.

Categories