Datetime required (+18 years) - asp.net-mvc

I have a little problem, here is my code:
public partial class Tourist
{
public Tourist()
{
Reserve = new HashSet<Reserve>();
}
public int touristID { get; set; }
[Required]
[StringLength(50)]
public string touristNAME { get; set; }
public DateTime touristBIRTHDAY { get; set; }
[Required]
[StringLength(50)]
public string touristEMAIL { get; set; }
public int touristPHONE { get; set; }
public virtual ICollection<Reserve> Reserve { get; set; }
}
}
How can I restrict touristBIRTHDAY to be +18 years old? I think that I have to use this function, but I don't know where to put it:
Note: this function it's an example.
DateTime bday = DateTime.Parse(dob_main.Text);
DateTime today = DateTime.Today;
int age = today.Year - bday.Year;
if(age < 18)
{
MessageBox.Show("Invalid Birth Day");
}
Thanks ;)
UPDATE:
I follow the solution of Berkay Yaylaci, but I'm getting a NullReferenceException. It's seems that my value parameter is default, and then my method is not posting, why? What is the solution to that?

You can write your own Validation. First, create a class.
I called MinAge.cs
public class MinAge : ValidationAttribute
{
private int _Limit;
public MinAge(int Limit) { // The constructor which we use in modal.
this._Limit = Limit;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
DateTime bday = DateTime.Parse(value.ToString());
DateTime today = DateTime.Today;
int age = today.Year - bday.Year;
if (bday > today.AddYears(-age))
{
age--;
}
if (age < _Limit)
{
var result = new ValidationResult("Sorry you are not old enough");
return result;
}
return null;
}
}
SampleModal.cs
[MinAge(18)] // 18 is the parameter of constructor.
public DateTime UserBirthDate { get; set; }
IsValid runs after post and check the Limit. If age is not greater than the Limit (which we gave in modal!) than return ValidationResult

Implement IValidatableObject on your tourist class.
Put your logic in the Validate() method.
You are using MVC so there is no MessageBox.Show(). The MVC model binder will automatically call you validation routine.
Here's another SO question with the details How do I use IValidatableObject?
Also your age logic is wrong. it needs to be
DateTime now = DateTime.Today;
int age = now.Year - bday.Year;
if (now < bday.AddYears(age)) age--;

Related

NET 6 WebAPI with Swagger - take default value from inline init not from attribute

Is there a chance to tell swagger to take default value from init not from attribute [DefaultValue]?
public class MyClass
{
public Guid RowId { get; set; } = Guid.NewGuid();
public int? ExampleInt { get; set; } = 1;
public string? ExampleText { get; set; } = string.Empty;
}
I don't want to type all default values twice.

validate required field depend on other field in model MVC

I want create model that will validate required field in model that depend on other field condition.
public class FixedDeposit
{
public int DebitAmount { get; set; }
public string PAN { get; set; }
}
Now if the DebitAmount is greater than 50,000 then PAN field is must be required.
You can implement IValidatableObject
public class FixedDeposit : IValidatableObject
{
public int DebitAmount { get; set; }
public string PAN { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (DebitAmount > 50000 && string.IsNullOrEmpty(PAN))
{
yield return new ValidationResult("PAN required for debits > 50,000.", new [] { "PAN" } );
}
}
}
http://weblogs.asp.net/scottgu/class-level-model-validation-with-ef-code-first-and-asp-net-mvc-3
You can also use MVC Foolproof validation package. This package provides you with many conditional validations in the form of annotations.
Complete list is here:
http://foolproof.codeplex.com/
You can add this library to your VS project as a package:
And, for your FixedPayment class, it should look something like this:
using Foolproof;
public class FixedDeposit
{
public int DebitAmount { get; set; }
[RequiredIf("DebitAmount", Operator.GreaterThan, 50000)]
public string PAN { get; set; }
}
Alternate code
using Foolproof;
public class FixedDeposit
{
public int DebitAmount { get; set; }
private bool _panRequired { get { return DebitAmount > 50000; } }
[RequiredIf("_panRequired", true, ErrorMessage="PAN is required if Debit Amount is greater than 50000")]
public string PAN { get; set; }
}
There are two options which you can use.
The first is the very easy to use and quite concise ExpressiveAnnotations JS library developed by Jaroslaw Waliszko. Follow this link to https://github.com/jwaliszko/ExpressiveAnnotations for more information. This library allows you to perform different conditional validations.
Similarly to Foolproof it is added to your Visual Studio environment through adding the NuGet package. Once added, within your model add the using statement using ExpressiveAnnotations.Attributes; Then simply use the RequiredIf declaration to do what you need. For example:
public class FixedDeposit
{
public int DebitAmount { get; set; }
[RequiredIf("DebitAmount >= 50000")]
public string PAN { get; set; }
}
The second option is to use ModelState.AddModelError(). This is done within your controller. Simply create a new method:
private void ValidateRequiredFields(modelname)
{
if(modelname.DebitAmount >= 50000)
{
if(modelname.PAN == null)
{
ModelState.AddModelError("PAN", "Place whatever error message you want here");
}
}
}
Next you place a reference to your validation method in whichever view method you want this to be called. The line to reference is ValidateRequiredFields(ModelName);
public class RequiredIfAttribute : RequiredAttribute
{
private String PropertyName { get; set; }
private Object DesiredValue { get; set; }
public RequiredIfAttribute(String propertyName, Object desiredvalue)
{
PropertyName = propertyName;
DesiredValue = desiredvalue;
}
protected override ValidationResult IsValid(object value, ValidationContext context)
{
Object instance = context.ObjectInstance;
Type type = instance.GetType();
Object proprtyvalue = type.GetProperty(PropertyName).GetValue(instance, null);
if (proprtyvalue.ToString() == DesiredValue.ToString())
{
ValidationResult result = base.IsValid(value, context);
return result;
}
return ValidationResult.Success;
}
}
Usage
[RequiredIf("DebitAmount",50000, ErrorMessage = "PAN field is required")]
public string PAN
{get;set;
}

Create item using a ViewModel setting unwanted defaults

I am using a ViewModel to Create a new item in my DB
the ViewModel has only the properties that I want the user to be able to set, and when it is posted back I make a new 'real' object and save it away to the DB.
I am doing this as detailed below
[HttpGet]
public ActionResult Create(int id = 0)
{
var opt = unitOfWork.OptionRepository.GetByID(id);
CreateAvailabilityViewModel model = new CreateAvailabilityViewModel();
model.OptionDescription = opt.Description;
model.CentreCode = opt.CentreCode;
model.OptionID = id;
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CreateAvailabilityViewModel cavm)
{
if (ModelState.IsValid)
{
OptionAvailability newOA = new OptionAvailability();
DateTime now = DateTime.Now;
newOA.ChangedDate = newOA.CreatedDate = now;
newOA.ChangedBy = newOA.CreatedBy = User.Identity.Name;
newOA.DateFrom = cavm.DateFrom;
newOA.DateTo = cavm.DateTo;
newOA.MinNumbers = cavm.MinNumbers;
newOA.MaxNumbers = cavm.MaxNumbers;
newOA.OptionID = cavm.OptionID;
unitOfWork.OptionAvailabilityRepository.Insert(newOA);
unitOfWork.Save();
return RedirectToAction("Detail", "Option", new { id = newOA.OptionID });
}
return View(cavm);
}
and this is the ViewModel
public class CreateAvailabilityViewModel
{
[HiddenInput(DisplayValue = false)]
public int OptionAvailabilityID { get; set; }
[HiddenInput(DisplayValue = false)]
public int OptionID { get; set; }
[Required]
public DateTime DateFrom { get; set; }
[Required]
public DateTime DateTo { get; set; }
[Required]
public int MinNumbers { get; set; }
[Required]
public int MaxNumbers { get; set; }
public string CentreCode { get; set; }
public string OptionDescription { get; set; }
}
the problem I am facing is that when the form is rendered the form fields for the dates and ints are defaulting to 01/01/0001 and 0 instead of being blank. I am using the Html.EditorFor helpers to render the inputs I assume it is because in the HttpGet Create method, when I instantiate the ViewModel it uses the type defaults and then passes them through in the object to the form, but this is not wha tI want to be happening.. do I need to set these properties to DateTime? and/or int? ?
I am pretty sure this is good practice to use but am a bit stumped as to why
can anyone explain what I am doing wrong please
thanks muchly
You can instantiate the dates with whatever values you want.
You could use backing fields in your viewmodel (instead of auto properties) and initialize them:
public class MyViewModel
{
private DateTime _firstDate = new DateTime(12/12/2012);
private DateTime _secondDate = DateTime.Now();
public DateTime FirstDate { get { return _firstDate; } set { _firstDate = value; } }
...
}
Or you could initialize them in the viewmodel's constructor:
public class MyViewModel
{
public MyViewModel(DateTime firstDate)
{
FirstDate = firstDate;
SecondDate = DateTime.Now();
}
public DateTime FirstDate { get; set; }
....
}
Or you could initialize them in your controller; you probably get the idea.
Also consider decorating these members with metadata:
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime FirstDate { get; set; }

Convert TimeSpan to String in MVC 3 Controller

I have a question , I have a Timespan in my Database and i want to use it in my controller but this error appears
Cannot implicitly convert type 'string' to 'System.TimeSpan'
Controller :
int id = Convert.ToInt32(clientId);
clientShift = (from a in db.Client_Shift
where a.ID == id
select a).SingleOrDefault();
clientShift.DayFrom_LookID = Convert.ToInt32(dateFrom);
clientShift.DayTo_LookID = Convert.ToInt32(dateTo);
This is where the error occur --> clientShift.EndTime = endTime.Trim();
clientShift.DateModified = DateTime.UtcNow;
clientShift.ModifiedBy = User.Identity.Name;
Model :
public partial class Client_Shift
{
public int ID { get; set; }
public int Client_ID { get; set; }
public int DayFrom_LookID { get; set; }
public int DayTo_LookID { get; set; }
public System.TimeSpan StartTime { get; set; }
public System.TimeSpan EndTime { get; set; }
Thanks for someone who can help me :D
You need to Parse the TimeSpan:
clientShift.EndTime = TimeSpan.Parse(endTime.Trim());
If the string does not represent a valid time span, you will get an exception.

Appropriate way to set default values for ViewModel in MVC4?

I have a viewModel that contains the following:
public class CreateCardViewModel
{
[HiddenInput(DisplayValue = false)]
public int SetId { get; set; }
[Required]
public IList<Side> Sides { get; set; }
[Required]
public int Stage { get; set; }
[Required]
[DataType(DataType.Date)]
[HiddenInput(DisplayValue = false)]
public DateTime DateCreated { get; set; }
[Required]
public bool IsReady { get; set; }
}
The model is as follows:
public class Card
{
public virtual int CardId { get; set; }
// belongs to a Set
public virtual int SetId { get; set; }
public virtual Set Set { get; set; }
// has Sides
public virtual IList<Side> Sides { get; set; }
// is in a certain Stage
public virtual int Stage { get; set; }
// is ready to study
public virtual bool IsReady { get; set; }
public virtual DateTime DateCreated { get; set; }
}
How can I set a default value for DateCreated?
Would the method change if I want to insert a blank Side into Sides upon Card creation?
You could set defaults in the constructor:
public CreateCardViewModel()
{
DateCreated = DateTime.Now;
Sides = new List<Side> { new Side() };
}
Caveat: There is an issue with using DateTime.Now from a unit testing perspective. If you're unit testing your ViewModel creation and need to be able to verify that the created date is set to a known value, you can look at creating a separate concept for time, as detailed in Ayende's blog. You basically create a static func, SystemTime, that you can set to a known value in your tests. If you don't set it, it defaults to DateTime.Now:
public static class SystemTime
{
public static Func<DateTime> Now = () => DateTime.Now;
}
Your constructor code then becomes:
public CreateCardViewModel()
{
DateCreated = SystemTime.Now();
Sides = new List<Side> { new Side() };
}
If you need to actually set the time to a known value, you do this:
SystemTime.Now = () => new DateTime(2013, 2, 11, 17, 41, 12);
I agree on The SystemTime approach.
Although, I personally don't like setting the CreatedDate on the constructor, since there can be a short time lapse since you instantiate the object and when you persist it to the database. (And here I am assuming you definitely are)
You could make all your domain objects inherit from an interface like this one:
public interface ITimeStamped
{
DateTime DateCreated { get; set; }
}
And then on the Commit method int the Context class I would do something like this to set the date for all entities that implement the interface:
foreach (var entry in ChangeTracker.Entries<ITimeStamped>()
.Where(entry => entry.State == EntityState.Added))
{
entry.Entity.DateCreated = SystemTime.Now();
}
This way you're totally certain that the entity is stored with the correct DateTime when it was persisted on the database.

Resources