2011-08-02 68 views
12

Có cách nào để ánh xạ từ/đến một POCO và knockoutj có thể quan sát được không?ánh xạ knockoutjs từ/đến đối tượng POCO

Tôi có một lớp Lưu ý:

public class Note 
{ 
    public int ID { get; set; } 
    public string Date { get; set; } 
    public string Content { get; set; } 
    public string Category { get; set; } 
    public string Background { get; set; } 
    public string Color { get; set; } 
} 

và đây là javascript của tôi:

$(function() { 
    ko.applyBindings(new viewModel()); 
}); 

function note(date, content, category, color, background) { 
    this.date = date; 
    this.content = content; 
    this.category = category; 
    this.color = color; 
    this.background = background; 
} 

function viewModel() { 
    this.notes = ko.observableArray([]); 
    this.newNoteContent = ko.observable(); 

    this.save = function (note) { 
     $.ajax({ 
       url: '@Url.Action("AddNote")', 
       data: ko.toJSON({ nota: note }), 
       type: "post", 
       contentType: "json", 
       success: function(result) { } 

      }); 
    } 

    var self = this; 
    $.ajax({ 
     url: '@Url.Action("GetNotes")', 
     type: "get", 
     contentType: "json", 
     async: false, 
     success: function (data) { 
      var mappedNotes = $.map(data, function (item) { 
       return new note(item.Date, item.Content, item.Category, item.Color, item.Background); 
      }); 
      self.notes(mappedNotes); 
     } 
    }); 
} 

Bỏ qua thực tế là chức năng tiết kiệm không được sử dụng (để đơn giản hóa mã ở đây).

Vì vậy, khi tôi tải trang tôi gọi máy chủ và tôi truy xuất danh sách các đối tượng Lưu ý và tôi ánh xạ nó trong javascript. Lưu ý cách ID không được ánh xạ vì tôi không cần nó trong quan điểm của tôi.

Cho đến giờ rất tốt, tôi thấy ghi chú trên màn hình, nhưng làm cách nào tôi có thể lưu ghi chú về máy chủ?

Tôi đã cố gắng chuyển đổi ghi chú (Im chỉ lưu ghi chú mới chứ không phải toàn bộ bộ sưu tập) vào JSON và gửi nó tới bộ điều khiển của tôi nhưng tôi không biết cách truy cập ghi chú trong bộ điều khiển. Tôi đã thử:

public string AddNote(string date, string content, string category, string background, string color) 
    { 
     // TODO 
    } 

nhưng không hoạt động. Tôi muốn có một cái gì đó như:

public string AddNote(Note note) {} 

(Btw, sự trở lại tốt nhất cho một phương pháp mà chỉ cần lưu dữ liệu trên DB là những gì làm mất hiệu lực?)

Vì vậy, thế nào tôi làm điều này? Tôi đã thử plugin knockout.mapping nhưng nó là khá khó hiểu và tôi không nhận được nó làm việc cho tôi.

Cảm ơn bạn.

Trả lời

24

Trình mô hình hóa của ASP.NET MVC sẽ tìm các thuộc tính phân biệt chữ hoa chữ thường. Bạn cần truyền đối tượng JSON của mình về máy chủ với tên thuộc tính khớp với đối tượng poco của bạn.

Tôi thường làm 1 trong tổng số 2 điều:

  1. Hãy vốn tên thuộc tính đối tượng javascript của tôi (mà cách trong JS, tôi biết rằng đối tượng này sẽ tại một số điểm là một DTO cho máy chủ)

    function Note(date, content, category, color, background) { 
        this.Date = date; 
        this.Content = content; 
        this.Category = category; 
        this.Color = color; 
        this.Background = background; 
    }; 
    
  2. Trong cuộc gọi AJAX của tôi sẽ chỉ cần tạo một đối tượng ẩn danh để vượt qua trở lại máy chủ (lưu ý đây không đòi hỏi ko.toJSON):

    $.ajax({ 
         url: '@Url.Action("AddNote")', 
         data: JSON.stringify({ note: { 
           Date: note.date, 
           Content: note.content, 
           Category: note.category, 
           Color: note.color, 
           Background: note.background 
           } 
          }), 
         type: "post", 
         contentType: "application/json; charset=utf-8", 
         success: function(result) { } 
    }); 
    
    .210

    (chú ý tham số contentType khác nhau cũng)

Bạn sẽ muốn chắc ActionMethod bạn mất trong một (Note note) và không chỉ là mảng các tham số.

Ngoài ra, do modelbinders xem xét các giá trị được đăng theo một vài cách khác nhau.Tôi đã có may mắn đăng đối tượng JSON với ra chỉ định tên tham số ActionMethod: thay vì:

{ note: { 
     Date: note.date, 
     Content: note.content, 
     Category: note.category, 
     Color: note.color, 
     Background: note.background 
     } 
    } 

chỉ làm:

{ 
     Date: note.date, 
     Content: note.content, 
     Category: note.category, 
     Color: note.color, 
     Background: note.background 
    } 

(nhưng điều này có thể nhận được dicey với mảng liên kết với các bộ sưu tập và phức tạp loại ... vv)

Theo như chữ ký 'Tốt nhất' để trả về phương thức thực hiện cuộc gọi db, chúng tôi thường thích xem boolean hơn, nhưng điều đó cũng tùy thuộc vào nhu cầu của bạn. Rõ ràng nếu nó là dữ liệu tầm thường, void sẽ ổn, nhưng nếu nó quan trọng hơn một chút, bạn có thể muốn chuyển tiếp một boolean (ít nhất) để cho client của bạn biết nó có thể cần phải thử lại (đặc biệt nếu có ngoại lệ đồng thời) .

Nếu bạn thực sự cần cho khách hàng biết điều gì đã xảy ra trong cơ sở dữ liệu, bạn có thể đột nhập vào thế giới của custom error handlingexception catching. Ngoài ra, nếu bạn cần hiển thị thông tin rất cụ thể cho người dùng tùy thuộc vào một cơ sở dữ liệu thành công/không thành công, thì bạn có thể xem xét việc tạo custom ActionResults chuyển hướng đến một số lượt xem dựa trên những gì đã xảy ra trong giao dịch cơ sở dữ liệu.

Cuối cùng, theo như nhận được dữ liệu từ máy chủ và sử dụng Knockout ...

  1. lại plugin mapping sẽ làm việc nếu tên tài sản của bạn là những trường hợp tương tự hoặc bạn tạo một ánh xạ một chút rõ ràng hơn
  2. Bí quyết của riêng tôi với các đối tượng JS của tôi là dưới đây. Hàm khởi tạo là thứ tôi tạo ra có thể tái sử dụng trên tất cả các đối tượng của bạn vì nó chỉ nói "nếu tên thuộc tính khớp (sau khi được hạ thấp), hoặc đặt chúng bằng cách gọi hàm (loại bỏ tương thích) hoặc chỉ gán giá trị .:

    .
    function Note(values){ //values are what just came back from the server 
        this.date; 
        this.content; 
        this.category; 
        this.color; 
        this.background; 
    
        initialize(values); //call the prototyped function at the bottom of the constructor 
    }; 
    
    Note.prototype.initialize = function(values){ 
        var entity = this; //so we don't get confused 
         var prop = ''; 
         if (values) { 
          for (prop in values) { 
           if (values.hasOwnProperty(prop.toLowerCase()) && entity.hasOwnProperty(prop.toLowerCase())) { 
            //the setter should have the same name as the property on the values object 
    
            if (typeof (entity[prop]) === 'function') { 
             entity[prop](values[prop]); // we are assuming that the setter only takes one param like a Knockout observable() 
            } else {// if its not a function, then we will just set the value and overwrite whatever it was previously 
             entity[prop] = values[prop]; 
            } 
           } 
          } 
         } 
    }; 
    
+1

tạo ảnh vui nhộn câu trả lời hoành tráng Nó hoạt động hoàn hảo nhưng: Ông có thể giải thích cho tôi đoạn cuối cùng Và .. làm thế nào để tải từ máy chủ bản đồ bằng tay như Im làm gì ở đây hay tôi phải cố gắng plugin lập bản đồ?? –

+1

Có, +1 cho câu trả lời tuyệt vời, rất rõ ràng với các ví dụ tuyệt vời –

+0

Wow - công việc tuyệt vời. –

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