Tôi muốn nói rằng bạn sử dụng lại thuật ngữ ViewModel cho cả hai hướng tương tác với khách hàng. Nếu bạn đã đọc đủ mã ASP.NET MVC trong tự nhiên, bạn có thể đã thấy sự phân biệt giữa ViewModel và EditModel. Tôi nghĩ rằng đó là quan trọng.
ViewModel đại diện cho tất cả thông tin cần thiết để hiển thị một chế độ xem. Điều này có thể bao gồm dữ liệu được hiển thị ở những nơi không tương tác tĩnh và cũng có thể là dữ liệu hoàn toàn để thực hiện kiểm tra để quyết định xem chính xác những gì sẽ hiển thị. Hành động GET của Bộ điều khiển thường chịu trách nhiệm đóng gói ViewModel cho View của nó.
EditModel (hoặc có thể là ActionModel) đại diện cho dữ liệu cần thiết để thực hiện hành động mà người dùng muốn thực hiện cho POST đó. Vì vậy, một EditModel thực sự đang cố gắng mô tả một hành động. Điều này có thể sẽ loại trừ một số dữ liệu khỏi ViewModel và mặc dù có liên quan, tôi nghĩ điều quan trọng là nhận ra chúng thực sự khác nhau.
Một ý tưởng
Điều đó nói rằng bạn có thể rất dễ dàng có một cấu hình AutoMapper để chuyển từ Model -> ViewModel và một cấu hình khác để chuyển từ EditModel -> Model. Sau đó, các hành động Controller khác nhau chỉ cần sử dụng AutoMapper. Địa ngục EditModel có thể có các chức năng trên đó để xác thực các thuộc tính của nó so với mô hình và áp dụng các giá trị đó cho chính Mô hình. Nó không làm bất cứ điều gì khác và bạn vẫn có ModelBinders trong MVC để ánh xạ Yêu cầu tới EditModel.
Một ý tưởng khác
Ngoài ra, điều mà tôi đã nghĩ đến gần đây, loại hoạt động dựa trên ý tưởng về ActionModel là những gì khách hàng đang đăng lại cho bạn thực sự là mô tả về một số hành động mà người dùng đã thực hiện chứ không chỉ là một khối dữ liệu lớn. Điều này chắc chắn sẽ yêu cầu một số Javascript ở phía máy khách để quản lý nhưng tôi nghĩ ý tưởng này rất hấp dẫn.
Về cơ bản khi người dùng thực hiện các hành động trên màn hình mà bạn đã trình bày, Javascript sẽ bắt đầu tạo một danh sách các đối tượng hành động. Một ví dụ có thể là người dùng đang ở màn hình thông tin nhân viên. Họ cập nhật họ và thêm địa chỉ mới vì nhân viên này đã kết hôn gần đây. Dưới các nắp này tạo ra một ChangeEmployeeName
và một AddEmployeeMailingAddress
đối tượng cho một danh sách. Người dùng nhấp vào 'Lưu' để thực hiện các thay đổi và bạn gửi danh sách hai đối tượng, mỗi đối tượng chỉ chứa thông tin cần thiết để thực hiện mỗi hành động.
Bạn sẽ cần một ModelBinder thông minh hơn thì một ModelBinder mặc định nhưng bộ tuần tự JSON tốt sẽ có thể xử lý việc ánh xạ các đối tượng hành động phía máy khách với các đối tượng phía máy chủ. Những cái phía máy chủ (nếu bạn đang ở trong môi trường 2 tầng) có thể dễ dàng có các phương thức hoàn thành hành động trên Model mà chúng làm việc. Vì vậy, hành động Bộ điều khiển kết thúc chỉ nhận được một Id cho cá thể Model để kéo và danh sách các hành động để thực hiện trên đó. Hoặc các hành động có id trong chúng để giữ chúng rất riêng biệt.
Vì vậy, có thể một cái gì đó như thế này được nhận ra ở phía máy chủ:
public interface IUserAction<TModel>
{
long ModelId { get; set; }
IEnumerable<string> Validate(TModel model);
void Complete(TModel model);
}
[Transaction]
public ActionResult Save(IEnumerable<IUserAction<Employee>> actions)
{
var errors = new List<string>();
foreach( var action in actions )
{
var employee = _employeeRepository.Get(action.ModelId);
errors.AddRange(action.Validate(employee));
}
foreach( var action in editModel.UserActions )
{
var employee = _employeeRepository.Get(action.ModelId);
action.Complete(employee);
_employeeRepository.Update(employee);
}
}
Điều đó thực sự làm cho hành động đăng lại khá chung chung vì bạn đang dựa vào ModelBinder của mình để lấy cho bạn cá thể IUserAction chính xác và cá thể IUserAction của bạn để thực hiện đúng logic hoặc (nhiều khả năng) gọi vào Mô hình với thông tin.
Nếu bạn đang ở trong môi trường 3 tầng, IUserAction chỉ có thể được tạo ra các DTO đơn giản để bắn qua ranh giới và thực hiện theo một phương pháp tương tự trên tầng ứng dụng. Tùy thuộc vào cách bạn thực hiện mà lớp đó có thể được tách ra rất dễ dàng và vẫn ở trong giao dịch (điều cần lưu ý là yêu cầu / phản hồi của Agatha và tận dụng bản đồ nhận dạng của DI và NHibernate).
Dù sao thì tôi chắc rằng đó không phải là một ý tưởng hoàn hảo, nó sẽ yêu cầu một số JS ở phía khách hàng để quản lý và tôi chưa thể thực hiện một dự án để xem nó diễn ra như thế nào, nhưng bài đăng đang cố gắng nghĩ về cách đến đó và trở lại một lần nữa vì vậy tôi nghĩ rằng tôi sẽ đưa ra suy nghĩ của mình. Tôi hy vọng nó sẽ hữu ích và tôi rất muốn biết những cách khác để quản lý các tương tác.