ASP.NET mvc 2 - 将出生日期与下拉列表绑定

时间:2010-09-07 15:48:41

标签: asp.net-mvc-2

在ASP.NET MVC 2中,你将如何绑定一个视图模型属性,该属性是一个DateTime,其中应用程序必须有3个下拉列表来选择月,日,年?我读过Scott H.的关于约会日期的博客帖子,这对于这样一个简单的案例来说似乎完全过于复杂。当然有更干净/更好的方法吗?

无论我使用何种解决方案,我都希望使用DataAnnotations保留内置验证,并且我还希望能够使用验证属性指定最小/最大日期范围。

我的第一个想法是一个简单的自定义模型绑定器,如下所示:

protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor)
{
    var model = bindingContext.Model as RsvpViewModel;
    var form = controllerContext.HttpContext.Request.Form;

    if (model == null) 
        throw new ArgumentException("bindingContext.Model");

    if (propertyDescriptor.Name.Equals("BirthDate"))
    {
        if (!string.IsNullOrEmpty(form["BirthYear"]) &&
            !string.IsNullOrEmpty(form["BirthMonth"]) &&
            !string.IsNullOrEmpty(form["BirthDay"]))
        {
            try
            {
                var yy = int.Parse(form["BirthYear"]);
                var mm = int.Parse(form["BirthMonth"]);
                var dd = int.Parse(form["BirthDay"]);
                model.BirthDate = new DateTime(yy, mm, dd);
                return;
            }
            catch (Exception)
            {
                model.BirthDate = DateTime.MinValue;
                return;
            }
        }
    }

    base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
}

然后我尝试创建一个DateTimeAttribute来进行验证,但是在属性声明中指定日期范围遇到了一些困难,因为属性参数类型是有限的,而DateTime不是允许类型之一。

我最终创建了一个IDateRangeProvider接口和一个特定于出生日期的实现,如下所示:

public interface IDateRangeProvider
{
    DateTime GetMin();
    DateTime GetMax();
}

public class BirthDateRangeProvider : IDateRangeProvider
{
    public DateTime GetMin()
    {
        return DateTime.Now.Date.AddYears(-100);
    }

    public DateTime GetMax()
    {
        return DateTime.Now.Date;
    }
}

这允许我在我的视图模型上使用DateTime属性并保持所有构建良好...

[DisplayName("Date of Birth:")]
[Required(ErrorMessage = "Date of birth is required")]
[DateTime(ErrorMessage = "Date of birth is invalid", RangeProvider=typeof(BirthDateRangeProvider))]
public DateTime? BirthDate { get; set; }

但实际上,整个解决方案都有过度工程和过度思考的气味。是不是有更好的方法?

3 个答案:

答案 0 :(得分:1)

  

创建seprate 3下拉列表并添加   必需的验证属性   它们。

     

并使用BdateList,BMonthList来   填充DropdownList

[DisplayName("Date of Birth ")]
public DateTime? Birthdate { get; set; }

[Required(ErrorMessage = "Date is required")]
public int BirthDateDate { get; set; }
[Required(ErrorMessage = "Month is required")]
public int BirthDateMonth { get; set; }
[Required(ErrorMessage = "Year is required")]
public int BirthDateYear { get; set; }


public List<System.Web.Mvc.SelectList> BDateList
{
    get
    {
        // create List here

    }
}
  

在post方法中你可以分配   用户选择的值为Model BirthDate

BirthDate.Date.AddDays(BirthDateDate -1).AddMonths(BirthDateMonth)

答案 1 :(得分:0)

给你一个想法

有class birthDate

public class birthDate{
public int day{get;set;}
public int month{get;set;}
public int year{get;set;}
}

现在在您的实体中: 将您的生日元素设置为私有

并将出生日期项目添加到课程中 在你只是处理每个部分的项目后。 并将此处理为一个日期:)

答案 2 :(得分:0)

您可以拥有生日的自定义类型,其中包含

等属性
public class BirthDateModel
{
    [Required(), Range(1, 12)]
    public Int32 BirthMonth { get; set; }

    [Required, Range(1, 31)]
    [DayShouldBeValid("BirthYear", "BirthMonth")]
    public Int32 BirthDay { get; set; }

    [Required,Range(1990, 2012)]
    public virtual Int32 BirthYear { get; set; }

    public DateTimeOffset GetBirthDate()
    {
        DateTimeOffset birthDate;
        if (DateTimeOffset.TryParse(String.Format("{0}-{1}-{2}", BirthMonth, BirthDay, BirthYear), out birthDate))
            return birthDate;

        // what should be returned here?
        return DateTime.MinValue;
    }

}

现在创建自定义验证器aka DayShouldBeValid来检查月份和年份,这一天是否有效。

并非日期的每个部分都有自己的控制权。

相关问题