【问题标题】:using foolproof to make sure end datetime is greater than start datetime使用万无一失确保结束日期时间大于开始日期时间
【发布时间】:2016-08-01 14:02:36
【问题描述】:

我在 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 日期初始化语句,您在提交时会得到无效的日期。

注意,我使用的是引导程序 datetimepicker,但注释掉了在文档准备好时初始化它的位。我认为这与问题有关,但似乎没有。最终我希望 datetimepicker 也能正常工作。

还要注意我在澳大利亚,所以日期格式是 dd/mm/yyyy

【问题讨论】:

  • 我猜万无一失在这里是错误的。还有其他方法进行注释验证吗?
  • 问题是jquery.validate.js(用于万无一失)基于MM/dd/yyyy格式验证日期(所以end=02/08/2016是2月8日,start=11/07/2016是12月7日,这意味着end更少比start)。一些选项请参考this answer
  • 如果您使用 jquery-ui datepicker,还有 this answer(我假设 bootstrap datetimepicker 也有类似的方法将值解析为特定日期格式)
  • 请注意与 this chat 相关 - 你没有 ping 我(通过以 @username 开头的消息,所以我直到现在才意识到你已经添加了评论)

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


【解决方案1】:

在您发布到 Index2 的 HTML 中,将其更改为 Index 在应用程序的 GreaterThanAttribute 中将 String 转换回 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);

    }
}

你的测试模型

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;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-02
    • 2022-10-13
    • 2020-03-21
    • 1970-01-01
    • 2021-09-06
    • 2021-08-05
    相关资源
    最近更新 更多