2011-06-17 33 views
5

Tôi có một loại thuộc tính DateTime MyDate trong ViewModel của mình. Tôi muốn chắc chắn rằng người dùng chỉ nhập ngày tham gia vào một hộp văn bản trong một định dạng cụ thể (dd.mm.yyyy) và thử các thuộc tính sau:Xác thực ngày theo định dạng cụ thể trong ASP.NET MVC 3

[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode=true)] 
[RegularExpression(@"^(([0-2]\d|[3][0-1])\.([0]\d|[1][0-2])\.[2][0]\d{2})$", 
    ErrorMessage="Failed...")] 
public DateTime MyDate { get; set; } 

Chữ ký controller action cho một HttpPost trông giống như này:

[HttpPost] 
public ActionResult Edit(int id, MyViewModel viewModel) 
{ 
    // MyViewModel contains the MyDate property ... 
    // ... 
    if (ModelState.IsValid) 
    { 
     // ... 
    } 
    // ... 
} 

Trong giao diện Razor tôi đã cố gắng trong hai cách sau:

  1. @Html.TextBoxFor(model => model.MyDate)

  2. @Html.EditorFor(model => model.MyDate)

Nó không làm việc như tôi muốn. Kết quả là:

  • Khách hàng xác nhận phía làm việc như mong đợi với cả những người giúp đỡ Html
  • Server side validation luôn thất bại cho cả những người giúp đỡ, thậm chí với số ngày có giá trị như "2011/06/17" mà vượt qua biểu thức chính quy. Thuộc tính MyDate được điền chính xác với ngày đã nhập trong số viewModel được chuyển cho hành động. Vì vậy, có vẻ như mô hình ràng buộc đã được làm việc.
  • Thuộc tính DisplayFormat chỉ được tôn trọng bởi EditorFor chứ không phải bởi TextBoxFor. TextBoxFor hiển thị "hh dd.mm.yyyy: mm: ss"

Câu hỏi:

  1. Tôi có thể áp dụng một RegularExpressionAttribute ở tất cả trên một tài sản mà không phải là một string? Nếu nó được cho phép như thế nào là reg cũ được đánh giá cho một tài sản không dây như DateTime trên phía máy chủ? Có phải cái gì đó giống như MyDate.ToString() so với chữ reg cũ không? (Nó sẽ giải thích rằng xác nhận thất bại vì ToString sẽ trả về một chuỗi bao gồm việc bán thời gian mà không vượt qua các biểu thức chính quy.)

  2. DisplayFormat thuộc tính thường chỉ được tôn trọng bởi EditorFor và không bao giờ bằng TextBoxFor?

  3. Tôi làm cách nào để xác thực ngày?

Trả lời

4

Tôi hiện đã bỏ đi RegularExpression. Dường như nó không phù hợp với thuộc tính loại DateTime. Sau đó, tôi đã tạo ra một thuộc tính xác nhận mới cho DateTime và DateTime nullable:

[AttributeUsage(AttributeTargets.Property, Inherited = false, 
    AllowMultiple = false)] 
public sealed class DateOnlyAttribute : ValidationAttribute 
{ 
    public DateOnlyAttribute() : 
     base("\"{0}\" must be a date without time portion.") 
    { 
    } 

    public override bool IsValid(object value) 
    { 
     if (value != null) 
     { 
      if (value.GetType() == typeof(DateTime)) 
      { 
       DateTime dateTime = (DateTime)value; 
       return dateTime.TimeOfDay == TimeSpan.Zero; 
      } 
      else if (value.GetType() == typeof(Nullable<DateTime>)) 
      { 
       DateTime? dateTime = (DateTime?)value; 
       return !dateTime.HasValue 
        || dateTime.Value.TimeOfDay == TimeSpan.Zero; 
      } 
     } 
     return true; 
    } 

    public override string FormatErrorMessage(string name) 
    { 
     return string.Format(CultureInfo.CurrentCulture, 
      ErrorMessageString, name); 
    } 
} 

Cách sử dụng:

[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode=true)] 
[DateOnly] 
public DateTime MyDate { get; set; } 

Nó không cung cấp xác nhận phía khách hàng. Về phía máy chủ, việc xác nhận dựa trên mô hình ràng buộc (để đảm bảo rằng chuỗi đã nhập có thể chuyển đổi thành một số DateTime). Nếu người dùng đã nhập một phần thời gian khác với nửa đêm, thuộc tính DateOnly sẽ khởi động và cô ấy nhận được cảnh báo rằng chỉ nên nhập ngày.

10

Không sử dụng cụm từ thông dụng để xác thực ngày, chúng chỉ bị bỏ qua.

Sự khác biệt về văn hóa có thể là gốc rễ của sự cố. Xác thực phía máy khách sử dụng văn hóa của trình duyệt để xác thực ngày tháng. Vì vậy, ví dụ: nếu cấu hình được định cấu hình thành en-US định dạng mong muốn sẽ là MM/dd/yyyy. Nếu máy chủ của bạn được định cấu hình để sử dụng fr-FR định dạng mong muốn sẽ là dd/MM/yyyy.

Bạn có thể sử dụng phần tử <globalization> trong web.config để đặt văn bản phía máy chủ.Bạn có thể cấu hình nó theo cách như vậy mà nó sử dụng các nền văn hóa tương tự như khách hàng:

<globalization culture="auto" uiCulture="auto"/> 

Hanselman có một nice blog post về toàn cầu hóa và nội địa hóa trong ASP.NET MVC.

+0

Cảm ơn bạn đã liên kết, tôi đã đánh dấu trang đó để tham khảo trong tương lai. NHƯNG: Tôi không nghĩ rằng vấn đề của tôi có liên quan đến nội địa hoá. Tôi không tin rằng biểu thức chính quy bị bỏ qua: Công việc xác thực phía máy khách và xác thực phía máy chủ cũng thực hiện điều gì đó với reg cũ (nó không thành công với reg cũ này, như ModelState nói). Tôi thử nghiệm trên một máy dev (máy khách và máy chủ = cùng một máy), do đó, các ngôn ngữ là như nhau. Nhưng tôi cũng tin rằng trong khi chờ đợi rằng sử dụng một reg cũ là sai (mặc dù không bị bỏ qua). Làm cách nào để bạn xác thực rằng người dùng chỉ nhập ngày mà không có phần thời gian? – Slauma

+1

@Slauma, thực tế là bạn đã thử điều này trên cùng một máy không có nghĩa là không có sự khác biệt trong cài đặt văn hóa của trình duyệt và máy chủ. Theo như phần thời gian là có liên quan, tôi sẽ chỉ cần nói cho người dùng định dạng mà anh ta cần để nhập ngày vào, và trên máy chủ tôi sẽ đơn giản bỏ qua phần thời gian nếu ứng dụng của tôi không cần nó. Thậm chí có thể cung cấp bộ chọn ngày tháng để đơn giản hóa người dùng nhập ngày vào một định dạng đúng. –

+0

Bạn nói đúng, tôi đang thử nó quá phức tạp. Hiện tại, tôi đã tạo một thuộc tính 'DateOnly' (xem câu trả lời của riêng mình ở đây). Bộ chọn ngày là sự trợ giúp tốt hơn cho người dùng! Tôi sẽ thử nó như một trong những bước tiếp theo. – Slauma

Các vấn đề liên quan