specifying min length if field has data - asp.net-mvc

I need to control a field with a min length if someone enters a value but if they don't enter anything in, I don't want the form to tell them there is a min value.
This is what I have:
[Required]
[StringLength(15, ErrorMessage = "Please supply at least {2} characters.", MinimumLength = 3)]
[Display(Name = "Last name on account or first part of the company's name")]
public string LastName { get; set; }
I just need for it to allow blanks also or if data is entered, require it to be a min of 3 characters..
Any suggestions?

The problem is with the validation logic of the StringLength attribute, that returns true also for the string with null value, here the implementation:
public override bool IsValid(object value)
{
this.EnsureLegalLengths();
int num = value == null ? 0 : ((string) value).Length;
if (value == null)
return true;
if (num >= this.MinimumLength)
return num <= this.MaximumLength;
else
return false;
}
Also the Required attribute that you used is not helping :-).
Anyway the only thing you can do for your scenario is to create a custom attribute to validate LastName with the logic that you need, here a link to an MVC3 example, or you can try googling, there is a lot of examples and is not hard to implement.

Related

ASP.NET MVC USD Currency Validation

In my ViewModel, I have the following System.ComponentModel.DataAnnotations on a property that contains USD currency:
[DisplayFormat(DataFormatString = "{0:C2}")]
[Range(0.01, 100000, ErrorMessage = "Payment amount is required between .01 and $100,000.")]
[DataType(DataType.Currency)]
[DisplayName("Payment Amount")]
public Double PrinAmount { get; set; } = 0.00;
When I enter a value of $10.005, I get the following validation model error from the ModelState.IsValid check:
The value '$10.005' is not valid for Payment Amount.
When I enter a value 10.005, the ModelState.IsValid is equal to true.
What do I need to do to modified the validation to capture both formats as invalid?
You can use Regular Expression;
[RegularExpression(#"^\d+\.\d{0,2}$")]
the DataAnnotations above ensures 2 digits.

Getting values from Bind. One key returns "0"

I want to make a few strings out of the Bind values. Easy enough except that one of them is messing with me. _surveyID = "0"
SurveyController:
public ActionResult Create([Bind(Include = "SurveyID,SurveyName,SenderID,ConsultantID,ResponderID,Question1,Question2,Question3,Question4,Question5,SurveyTime")] Survey survey)
{
if (ModelState.IsValid)
{
string _surveyID = survey.SurveyID.ToString();
string _surveyName = survey.SurveyName;
string _surveyTime = survey.SurveyTime.ToString();
//ANOTHER ATTEMPT, SAME RESULT
//string _surveyID = db.Surveys
//.FirstOrDefault(x => x.SurveyID == survey.SurveyID)
//.SurveyID;
}
SurveyID to database = 1002
SurveyID to my _surveyID = "0"
Notice that _surveyName and _surveyTime are both working fine.
The survey Bind values: http://i.imgur.com/khEDUns.png
Why is my SurveyID beeing set to 0 when I try to pull out the value?
EDIT: Is the ID value created when beeing put into database? Is my code too soon in the flow of code?
EDIT2: This is a bump1

#Html.DisplayFor for Empty

I am trying to display empty string when model.EndDate is 0
#Html.DisplayFor(modelItem => model.EndDate)
I tried
#Html.DisplayFor(modelItem => model.EndDate == 0 ? "" : model.EndDate.ToString())
and
#Html.Display("End Date",model.EndDate == 0 ? "" : model.EndDate.ToString())
both did not worked for me. Both of the displaying empty when data is available.
Do a conditional outside the DisplayFor:
#if (Model.EndDate != 0)
{
Html.DisplayFor(modelItem => model.EndDate)
}
You can't compare a datetime to 0 in asp.net.
error CS0019: Operator `==' cannot be applied to operands of type `System.DateTime' and `int'
A DateTime is a value type so it get a default value of DateTime.MinValue when it isn't set.
using System;
public class Test {
public static DateTime badDate;
public static DateTime goodDate = DateTime.Now;
public static void Main(string[] args) {
Console.WriteLine(goodDate == DateTime.MinValue ? "" : goodDate.ToString());
Console.WriteLine(badDate == DateTime.MinValue ? "" : badDate.ToString());
}
}
How about this one ?
DateTime dt;
if (DateTime.TryParse("Your Date", out dt))
{
//Now you have validated the date
//Your code goes here
}
I think you should make your model property be a nullable type. So for example if its type is DateTime then declare the property as a nullable DateTime:
public DateTime? EndDate { get; set; }
this way instead of a 0 date (whatever that means) you will have no value. This also makes sense especially if this model property is coming from the database and is nullable.
You can read more about the nullable types here: http://msdn.microsoft.com/en-us/library/2cf62fcy(v=vs.80).aspx
I didn't like the answers given above because adding IF Statements to everything just slows your system down, in my case i needed to display a default string value several times in each row of a list view when the class property was a null value.
So have a look at the MS Docs here:
DisplayFormatAttribute.NullDisplayText Property
The following example shows how to use the NullDisplayText to define a caption to display when the data field is null.
// Display the text [Null] when the data field is empty.
// Also, convert empty string to null for storing.
[DisplayFormat(ConvertEmptyStringToNull = true, NullDisplayText = "[Null]")]
public object Size;

MVC .net annotation-based valiadation : Remove dashes and parenthesis from phone numbers

Is it possible to both validate, that the provided data is in the form of a phone number AND trim it down to just the numbers in the validator?
Input: (902) 837-2832
Output: VALID: YES, 9028372832
Or do I have to convert the input to the number-only format after the fact?
Add a property to your model with only a getter that returns the stripped down version of the property that is bound to the input. Put your validation attribute on that property.
public string PhoneNumber {get;set;}
[Required(ErrorMessage="Phone number is required.")]
[RegularExpression(#"\d{10}", ErrorMessage="Phone number is invalid.")]
public string PhoneNumberValue
{
get
{
var temp = PhoneNumber
temp = Regex.Replace(temp, #"[^0-9]", "");
temp = temp.Length == 11 && temp.StartsWith("1")
? temp.Substring(1) : temp;
}
set
{
// I can't remember off the top of my head if MVC model
// binding requires a setter or not. If so, just leave this
// empty. Otherwise you can remove it entirely.
}
}
Then, in your view, just render the alternate validation message.
#Html.LabelFor(x=>x.PhoneNumber)
#Html.TextBoxFor(x=>x.PhoneNumber)
#Html.ValidationMessageFor(x=>x.PhoneNumberValue)
Here is an example how to validate with Regular expression:
[Required(ErrorMessage="Phone Number is required")]
[RegularExpression("^(?([0-9]{3}))?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$", ErrorMessage="Not a valid number")]
public string PhoneNumber { get; set; }
We may use Trim method of string to clean the phone number and get only digits.
char[] charsToTrim = { '(', ' ', ')', '-'};
string phoneNumber = "(123)-345-6789";
string result = banner.Trim(charsToTrim);
Finally here is a post that explains Enabling Validation using DataAnnotations in more detail

Storing string versions of database status values

I'm writing an ASP.NET MVC 3 site and I need to convert some integer values from the database that represent statuses with user readable strings, for example:
...
<td>
#item.Status
</td>
...
I've written an HTML Helper to do the conversion:
public static string MessageType(this HtmlHelper helper, int type)
{
string messageType = "Unknown";
switch((Types.MessageTypes)type)
{
case Types.MessageTypes.Join:
messageType = "Join App";
break;
case Types.MessageTypes.New:
messageType = "New App";
break;
}
return messageType;
}
And I'm storing the types as an enumeration in the Types class.
My question is whether there is a cleaner way to do this? I don't like these magic strings in my code and it creates numerous dependencies in different parts of the code.
Any thoughts?
Many thanks,
Sam
I usual decorate the enums with the DisplayAttribute like this.
enum MessageTypes
{
[Display(Name = "Join App")]
Join,
[Display(Name = "New App")]
New
}
Then I use a helper to extract them:
public static string EnumDisplay(this HtmlHelper helper, Enum model)
{
var enumType = model.GetType();
var modelValue = Convert.ToInt64(model);
var matches = from field in enumType.GetMembers()
where field.MemberType == MemberTypes.Field && Enum.IsDefined(enumType, field.Name)
let value = Convert.ToInt64(Enum.Parse(enumType, field.Name, false))
where modelValue == value
let attribute = field.GetCustomAttributes(typeof (DisplayAttribute), false).Cast<DisplayAttribute>().FirstOrDefault()
select attribute == null
? field.Name
: attribute.Name;
return matches.FirstOrDefault() ?? "Unknown";
}
Then you can do
#Html.EnumDisplay((MessageType)item.MessageType)
In my opinion, you should be storing the corresponding user readable strings in the database next to the integer. And return an object e.g. StatusViewModel to the view model. the View model may have >
class StatusViewModel
{
int type;
string displayMessage;
}
makes sense?

Resources