2011-12-22 15 views
8

Trong thuật ngữ của giáo dân, những gì hiện UpdateModel() làm, cũng như TryUpdateModel()? Tôi không thể tìm thấy (trên SO hoặc web) bất kỳ lời giải thích rõ ràng về những gì nó thực sự làm (trong điều khoản rõ ràng), chỉ những người gặp vấn đề khi sử dụng nó.UpdateModel() làm gì?

IntelliSense của VisualStudio cũng không giúp ích cho tôi. Lý do tại sao tôi hỏi là bởi vì, chúng ta hãy nói, nếu tôi có điều này trong bộ điều khiển của tôi:

[HttpPost] 
public ActionResult Index(UserViewModel vm, FormCollection form) 
{  
    var statesCheckBoxes = form["StatesList"];  

    vm.BA.StatesTraveledTo = statesCheckBoxes.Split(',').ToList<string>(); 

    return View(vm); 
} 

Không phải tôi đã cập nhật mô hình của tôi bằng cách thiết lập vm.BA.StatesTraveledTo? Tại sao tôi cần chạy UpdateModel? Ngoài ra, khi tôi thực sự cố gắng để làm như sau:

[HttpPost] 
public ActionResult Index(UserViewModel vm, FormCollection form) 
{  
    var statesCheckBoxes = form["StatesList"];  

    vm.BA.StatesTraveledTo = statesCheckBoxes.Split(',').ToList<string>(); 

    UpdateModel(vm); // IS THIS REDUNDANT TO THE PREVIOUS LINE? 

    return View(vm); 
} 

Không có gì có thể xảy ra trong khi tôi kiểm tra giá trị của ModelState (sau khi tôi chạy UpdateModel()), tôi không thấy bất cứ điều gì chứng tỏ rằng bất cứ điều gì đã thay đổi. Tôi không thấy một khóa mới trong từ điển ModelState.

Thực sự nhầm lẫn. Cảm ơn!

Edit:

gửi bài mã nguồn cho các lớp ViewModel và Model:

public class UserViewModel 
{ 
    public BankAccount BA { get; set; } 
} 

public class BankAccount 
{ 
    public Person User { get; set; } 
    public List<string> StatesTraveledTo { get; set; } 
} 

public class Person 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public int Age { get; set; } 
} 
+1

Đây là mã nguồn cho nó: http://aspnet.codeplex.com/SourceControl/changeset/view/72551#266451 Nó khá đơn giản, chỉ cần tạo ra một ModelBindingContext và liên kết nó –

+1

Ngoài ra, nó có phần hiếm khi vượt qua cùng một đối tượng mà bạn nhận được như là đầu vào trong một hành động vào xem, nó xảy ra nhưng nó hiếm và điều này không có vẻ giống như một trong những sử dụng đó. Thông thường, bạn lấy làm đầu vào một đối tượng đại diện cho dữ liệu được đăng và sau đó tạo một mô hình riêng cho chế độ xem –

+0

Cảm ơn. Lý do tại sao tôi vượt qua mô hình trở lại xem là cho mục đích xác nhận. Vì vậy, trong trường hợp xác thực không thành công, tôi muốn mô hình và các giá trị của nó được chuyển đến khung nhìn sao cho các trường biểu mẫu được nhận lại và thông báo lỗi được hiển thị. Xin lỗi, tôi đoán với mã tôi đã cho thấy, nó có thể không giống như một ví dụ thực tế. – SaltProgrammer

Trả lời

5

gì xảy ra khi bạn viết

public ActionResult Index(UserViewModel vm) 
{ } 

và khi bạn kiểm tra trong ActionResult bạn thấy rằng vm chứa giá trị mà bạn gửi từ giao diện. đó là vì mvc chỉ đạo trình mô hình hóa để trích xuất các giá trị từ các nguồn khác nhau (thu thập biểu mẫu, các giá trị tuyến đường, chuỗi truy vấn, vv) và điền các giá trị của mô hình của bạn. Nhưng để điều này xảy ra, các khóa biểu mẫu của bạn phải khớp với tên của các thuộc tính trong mô hình của bạn và nếu đó là trường hợp mô hình của bạn được điền chính xác. bây giờ chúng ta đến với câu hỏi thực tế: UpdateModel làm gì? câu trả lời đơn giản là gì ngoài mô hình ràng buộc. Sự khác biệt chỉ là bạn gọi nó một cách rõ ràng.Trên đây ActionResult thể được viết lại như sử dụng UpdateModel

Public ActionResult Index() 
{ 
    UserViewModel vm = new UserViewModel(); 
    UpdateModel(vm);// it will do same thing that was previously handled automatically by mvc 
} 

Bây giờ, những gì đã không được xử lý bằng cách liên kết sẽ không được xử lý bởi mô hình rõ ràng ràng buộc cũng mô hình tự động vì nó không phải là vấn đề với mô hình chất kết dính các vấn đề của mình với html của bạn . với các mô hình điểm lồng nhau như của bạn, tên trường mẫu phải được chế tác cẩn thận để MVC một cách chính xác có thể tiêm nó vào mô hình của bạn mà không cần phải viết một cái gì đó giống như

vm.BA.StatesTraveledTo = statesCheckBoxes.Split(',').ToList<string>(); 

và nếu bạn không muốn làm kiểm tra điều như vậy này google search

2

Đây là mã nguồn cho nó: http://aspnet.codeplex.com/SourceControl/changeset/view/72551#266451

Nó khá đơn giản,

protected internal bool TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties, IDictionary<string, ValueProviderResult> valueProvider) where TModel : class { 
     if (model == null) { 
      throw new ArgumentNullException("model"); 
     } 
     if (valueProvider == null) { 
      throw new ArgumentNullException("valueProvider"); 
     } 

     Predicate<string> propertyFilter = propertyName => BindAttribute.IsPropertyAllowed(propertyName, includeProperties, excludeProperties); 
    IModelBinder binder = Binders.GetBinder(typeof(TModel)); 

    ModelBindingContext bindingContext = new ModelBindingContext() { 
     Model = model, 
     ModelName = prefix, 
     ModelState = ModelState, 
     ModelType = typeof(TModel), 
     PropertyFilter = propertyFilter, 
     ValueProvider = valueProvider 
    }; 
    binder.BindModel(ControllerContext, bindingContext); 
    return ModelState.IsValid; 
} 

Thi s chỉ tạo ra một ModelBindingContext và liên kết nó. Tôi tin rằng nó đã xảy ra theo mặc định trước khi hành động của bạn được gọi. Thật hiếm khi phải gọi nó bằng tay.

Chỉ cần đoán ở đây nhưng bạn có thể nhận được kết quả lạ bởi vì bạn đang làm mọi thứ một cách không điển hình. Chữ ký của hành động của bạn:

public ActionResult Index(UserViewModel vm, FormCollection form) 

lấy UserViewModel và FormCollection. Thông thường mọi người làm một hoặc khác (thực sự FormCollection là khá hiếm hiện nay). Một lần nữa, tôi sẽ tắt bộ nhớ ở đây nhưng tôi đoán rằng UpdateModel không làm gì bởi vì những giá trị đó đã bị ràng buộc. Nếu nó có sản phẩm nào thì có thể là do FormCollection nhận (liên kết) tất cả các giá trị submittd của bạn và không có giá trị nào được để lại cho viewmodel để liên kết.

+0

Cảm ơn. Xin lỗi, bạn nói rằng UpdateModel() được chạy theo mặc định trước hành động của tôi để không cần chạy một cách rõ ràng từ hành động? – SaltProgrammer

+0

Lý do tại sao tôi sử dụng FormCollection là vì trình mô hình hóa mặc định (được sử dụng cho ViewModel) không thể liên kết một tập các hộp kiểm mà tôi có trên khung nhìn đối với thuộc tính List mà tôi có trong đối tượng BankAccount bên trong đối tượng UserViewModel. Kiểm tra mã nguồn tôi vừa thêm vào câu hỏi. Để ánh xạ chính xác thuộc tính lồng nhau sâu, tôi lấy nó trực tiếp từ FormCollection. Một cách khác để không sử dụng đối tượng FormCollection, mà tôi biết, đang tạo ra một chất kết dính mô hình tùy chỉnh, nhưng tôi không muốn làm cho nó phức tạp hơn nó, hay tôi đang thiếu một cái gì đó? – SaltProgrammer

+1

Vâng, chỉ cần tạo một lớp cho các giá trị khác mà bạn muốn với các loại thích hợp cho các hộp kiểm. Nếu nó có thể liên kết nó với FormCollection, nó sẽ có thể liên kết nó với một kiểu tĩnh. Ngoài ra, bạn chỉ có thể lấy đồ vật ra khỏi đối tượng Yêu cầu. –

0

Mô hình cập nhật về cơ bản được sử dụng để cập nhật các giá trị mới trong Mô hình hiện tại của bạn. bạn không cần gán giá trị một cách rõ ràng.

+0

Bạn đang nói rằng tôi không phải làm việc này hơn ... vm.BA.StatesTraveledTo = statesCheckBoxes.Split (','). ToList (); ??? Nếu tôi không phải làm điều đó, thì cú pháp nào hơn nếu tôi chỉ muốn sử dụng phương thức UpdateModel()? – SaltProgrammer