使用万无一失以确保结束日期时间大于开始日期时间

时间:2016-08-01 14:02:36

标签: asp.net-mvc asp.net-mvc-4 bootstrap-datetimepicker foolproof-validation

我在MVC项目中使用万无一失。 我似乎正在进行文本比较,以确定结束日期时间是否大于开始日期时间。

以下是模型:

public class TestModel
{
    [Required]
    [DataType(DataType.DateTime)]
    public DateTime start { get; set; }

    [Required]
    [DataType(DataType.DateTime)]
    [GreaterThan("start")]
    public DateTime end { get; set; }
}

视图

@model WebApplication1.Models.TestModel

@{
    ViewBag.Title = "Home Page";
}


@using (Html.BeginForm("Index2", "Home", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()

    @Html.ValidationSummary("", new { @class = "text-danger" })
    <div class="form-group">
        @Html.LabelFor(m => m.start, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.start, "{0:dd/MM/yyyy HH:mm}", new { @class = "form-control datetimepicker" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.end, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.end, "{0:dd/MM/yyyy HH:mm}", new { @class = "form-control datetimepicker" })
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Set password" class="btn btn-default" />
        </div>
    </div>
}

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

控制器

    public ActionResult Index()
    {
        TestModel model = new TestModel();
        // model.start = new DateTime(2016, 5, 31);
        //model.end = new DateTime(2016, 8, 31);
        model.start = DateTime.Now;
        model.end = DateTime.Now.AddMinutes(30);
        return View(model);
    }

您可以下载我的项目试用: https://www.dropbox.com/s/pf0lkg297hq0974/WebApplication1.zip?dl=0

有两个问题: 1)当您开始日期11/07/2016 23:51和结束日期02/08/2016 00:21时,您会收到验证错误,因为它认为结束日期小于开始日期。这似乎是对我的文本比较。

2)此外,如果您取消注释掉两个model.start和model.end日期初始化语句,则在提交时会收到无效日期。

注意我正在使用bootstrap datetimepicker,但在文档准备好时将其初始化的位置注释掉了。我认为这与问题有关但似乎没有。最终我想让datetimepicker工作。

另请注意我在澳大利亚,因此日期格式为dd / mm / yyyy

1 个答案:

答案 0 :(得分:1)

在您的HTML中发布到Index2将其更改为Index 将String转换回应用程序中GreaterThanAttribute的DateTime,然后比较

试试这个我测试了这个实现

控制器

 public class TestController : Controller
{
    // GET: Test

    [HttpGet]
    public ActionResult Index()
    {

        var model = new TestModel();
        // model.start = new DateTime(2016, 5, 31);
        //model.end = new DateTime(2016, 8, 31);
        model.start = DateTime.Now;
        model.end = DateTime.Now.AddMinutes(30);
        return View(model);


    }
    [HttpPost]
    public ActionResult Index(TestModel model)
    {
        if (ModelState.IsValid)
        {

            // model.start = new DateTime(2016, 5, 31);
            //model.end = new DateTime(2016, 8, 31);
            model.start = DateTime.Now;
            model.end = DateTime.Now.AddMinutes(30);
             return View("Index", model);
        }
        return View("Index", model);

    }
}

您的TestModel

public class TestModel
{
    [Required]
    [DataType(DataType.DateTime)]
    public DateTime start { get; set; }

    [Required]
    [DataType(DataType.DateTime)]
    [GreaterThan("start", "Your Error Message")]
    public DateTime end { get; set; }
}

您的GreaterThenAttribute.cs

 public class GreaterThanAttribute : ValidationAttribute, IClientValidatable
{

    public string otherPropertyName;
    public GreaterThanAttribute()
    {
    }
    public GreaterThanAttribute(string otherPropertyName, string errorMessage) : base(errorMessage)
    {
        this.otherPropertyName = otherPropertyName;
    }

    protected override ValidationResult IsValid
        (object value, ValidationContext validationContext)
    {
        ValidationResult validationResult = ValidationResult.Success;
        try
        {
            // Using reflection we can get a reference to the other date property, in this example the project start date
            var containerType = validationContext.ObjectInstance.GetType();
            var field = containerType.GetProperty(this.otherPropertyName);
            var extensionValue = field.GetValue(validationContext.ObjectInstance, null);
            var datatype = extensionValue.GetType();

            //var otherPropertyInfo = validationContext.ObjectInstance.GetType().GetProperty(this.otherPropertyName);
            if (field == null)
                return new ValidationResult(String.Format("Unknown property: {0}.", otherPropertyName));
            // Let's check that otherProperty is of type DateTime as we expect it to be
            if ((field.PropertyType == typeof(DateTime) ||
                 (field.PropertyType.IsGenericType && field.PropertyType == typeof(Nullable<DateTime>))))
            {
                DateTime toValidate = (DateTime)value;
                DateTime referenceProperty = (DateTime)field.GetValue(validationContext.ObjectInstance, null);
                // if the end date is lower than the start date, than the validationResult will be set to false and return
                // a properly formatted error message
                if (toValidate.CompareTo(referenceProperty) < 1)
                {
                    validationResult = new ValidationResult(ErrorMessageString);
                }
            }
            else
            {
                validationResult = new ValidationResult("An error occurred while validating the property. OtherProperty is not of type DateTime");
            }
        }
        catch (Exception ex)
        {
            // Do stuff, i.e. log the exception
            // Let it go through the upper levels, something bad happened
            throw ex;
        }

        return validationResult;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules
        (ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule
        {
            ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
            ValidationType = "isgreater",
        };
        rule.ValidationParameters.Add("otherproperty", otherPropertyName);
        yield return rule;
    }
}