2010-04-05 25 views
6

Điều này đang hoạt động, nhưng làm thế nào ???Làm thế nào để asp.net MVC nhớ các giá trị không chính xác của tôi trên postback?

Tôi có một hành động điều khiển cho một bài:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Edit(Person person) 
{ 
    bool isvalid = ModelState.IsValid; 
    etc. 

Đối tượng Person có một ngày sinh tài sản, loại DateTime. Khi tôi nhập một số dữ liệu không hợp lệ trong biểu mẫu, hãy nói 'blabla' rõ ràng không phải là Ngày giờ hợp lệ, nó sẽ điền tất cả các thuộc tính Person (khác) với dữ liệu chính xác và thuộc tính Ngày sinh với một DateTime trống mới. Giá trị bool isvalid có giá trị 'false'. Cho đến nay rất tốt.

Sau đó, tôi làm điều này:

return View(p); 

và trong giao diện i có điều này:

<%= Html.TextBox("BirthDate", String.Format("{0:g}", Model.BirthDate)) %> 
<%= Html.ValidationMessage("BirthDate", "*") %> 

Ant có nói: Tôi mong các mô hình để chứa các mới, DateTime trống, vì tôi didn Thứ hai, khi View hiển thị một cái gì đó, nó phải là một DateTime, bởi vì Model.BirthDate không thể giữ bất cứ điều gì ngoài một DateTime. Nhưng với sự ngạc nhiên của tôi, nó cho thấy một hộp văn bản với giá trị 'blabla'! (và màu đỏ * đằng sau nó)

Ngôn ngữ nào là tốt bởi vì người dùng có thể nhìn thấy những gì anh ta gõ sai, nhưng chuỗi (blabla) đó có thể được chuyển đến View trong trường DateTime như thế nào?

EDIT: Thông tin ModelState đã giúp tôi rất nhiều ở đây. Tôi cũng nhận thấy rằng trong MVC 2, khi bạn tạo Mẫu của riêng bạn cho Html.EditorFor() bạn phải tự mình thực hiện hành vi này. Tôi tạo ra một

DateTime.ascx 

trong views/chia sẻ thư mục// EditorTemplates, và trong đó tôi đã phải kiểm tra nếu có một lỗi ModelState cho giá trị tài sản này, và nếu như vậy, hiển thị dữ liệu không hợp lệ trong thay vì dữ liệu Mô hình.

Vì vậy, theo quan điểm tôi sử dụng này:

<%= Html.LabelFor(model => model.DateOfBirth) %> 

và trong DateTime.ascx tôi sử dụng này:

<% 
bool invalidData = false; 
string propertyName = ViewData.ModelMetadata.PropertyName; 

ModelState ms = ViewData.ModelState[propertyName]; 
if (ms != null) 
{ 
    invalidData = ms.Errors.Count > 0; 
} 
string valueToshow = invalidData ? ViewData.ModelState[propertyName].Value.AttemptedValue : String.Format("{0:g}", Model); 
%> 
<input class="text-box single-line" id="<%= propertyName %>" name="<%= propertyName %>" type="text" value="<%= valueToshow %>" /> 

Trả lời

10

ModelState giữ KeyValuePairs cho mỗi yếu tố hình thức với phím là tên trường và giá trị là những gì bạn đặt trong trường. Sau đó, những người trợ giúp Html nhìn vào ModelState và nếu bạn không chỉ định rõ ràng một giá trị, họ sẽ kéo giá trị từ ModelState.

+0

Cảm ơn, hiện không phải người trợ giúp đã phân tích cú pháp giá trị trong mô hình. – Michel

4

Giá trị đã nhập trước đó được lưu trữ trong ModelState. Khi bạn có lỗi trên biểu mẫu, trình trợ giúp kéo giá trị từ ModelState thay vì sử dụng một trong hai giá trị từ Mô hình hoặc các giá trị được cung cấp cụ thể (dưới mui xe, nếu bạn không cung cấp giá trị rõ ràng, nó sẽ mặc định cho mô hình giá trị nếu có khi không có lỗi).

+0

1 cho câu trả lời, Keith hơi nhanh hơn, hy vọng bạn không nhớ đánh dấu câu trả lời của mình là – Michel

+0

Tôi nghĩ câu trả lời này là đúng, và Keith không đúng. Câu trả lời của Keith cho biết ModelState được sử dụng nếu bạn không chỉ định rõ ràng một giá trị; câu trả lời này nói rằng ModelState được sử dụng nếu có lỗi, có hay không giá trị được chỉ định rõ ràng. Mẫu để gọi bộ điều khiển GET sau bộ điều khiển POST khi có Lỗi mô hình, chỉ hoạt động vì dữ liệu chế độ xem ModelState luôn ghi đè bất kỳ thứ gì bạn mã trong bộ điều khiển GET. –

1

Tôi đã có một số mã trong 'postback' có thể xóa mã khuyến mại không hợp lệ và tận dụng phản hồi. Ngay cả khi bạn cập nhật mô hình với giá trị mới, nó sẽ không được hiển thị vì giá trị ModelState được ưu tiên (như những giá trị khác đã được trả lời).

<%= Html.TextBox("PromoCode", Model.PromoCodes) %> 

Nhưng nếu bạn có một trường hợp này đã xảy ra và bạn không muốn giá trị cũ vẫn kiên trì bạn cần phải làm điều này:

ModelState.Remove("PromoCode"); 

hoặc dứt khoát thiết lập giá trị mới vào ModelState (có thể là cách tiếp cận tốt hơn):

ModelState.SetModelValue("PromoCode", 
     new ValueProviderResult(newValue, newValue, CultureInfo.CurrentCulture)); 
+0

+1 để bổ sung. – Michel

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