【问题标题】:knockoutjs mapping from/to POCO object从/到 POCO 对象的 knockoutjs 映射
【发布时间】:2011-10-18 05:30:48
【问题描述】:

有没有办法从/映射到 POCO 和可观察的 knockoutjs?

我有一个笔记类:

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; }
}

这是我的javascript:

$(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);
        }
    });
}

忽略没有使用保存功能的事实(这里简化代码)。

因此,当我加载页面时,我会调用服务器并检索 Note 对象列表并将其映射到 javascript 中。请注意 ID 是如何未映射的,因为我的视图中不需要它。

到目前为止一切顺利,我在屏幕上看到了注释,但是如何将注释保存回服务器?

我尝试将笔记(我只保存新笔记而不是整个集合)转换为 JSON 并将其发送到我的控制器,但我不知道如何访问控制器中的笔记。我试过了:

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

但不工作。我想要类似的东西:

public string AddNote(Note note) {}

(顺便说一句,仅将数据保存在 DB 上的方法的最佳回报是什么?无效?)

那么,我该怎么做呢?我尝试了 knockout.mapping 插件,但它非常令人困惑,我无法让它为我工作。

谢谢。

【问题讨论】:

    标签: asp.net-mvc mapping poco knockout.js


    【解决方案1】:

    ASP.NET MVC 的模型绑定器将查找区分大小写的属性。您需要将 JSON 对象传递回服务器,其属性名称与您的 poco 对象匹配。

    我通常做两件事中的一件:

    1. 将我的 javascript 对象属性名称设为大写(在 JS 中这样,我知道该对象有时会成为服务器的 DTO)

      function Note(date, content, category, color, background) {
          this.Date = date;
          this.Content = content;
          this.Category = category;
          this.Color = color;
          this.Background = background;
      };
      
    2. 在我的 AJAX 调用中,我将创建一个匿名对象以传回服务器(注意这不需要 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) { }
      });
      

      (注意不同的 contentType 参数)

    您需要让 ActionMethod 接受 (Note note) 而不仅仅是参数数组。

    另外,因为模型绑定器以几种不同的方式查看发布的值。我很幸运地在没有指定 ActionMethod 参数名称的情况下发布了 JSON 对象: 而不是:

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

    只是做:

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

    (但这可能会因为数组绑定到集合和复杂类型......等等而变得冒险)

    就执行 db 调用的方法返回的“最佳”签名而言,我们通常更喜欢查看布尔值,但这也取决于您的需求。显然,如果它是微不足道的数据, void 会很好,但如果它更关键,您可能希望传递一个布尔值(至少)让您的客户知道它可能需要重试(特别是如果有并发异常) .

    如果您确实需要让您的客户知道数据库中发生了什么,您可以涉足custom error handlingexception catching 的世界。

    此外,如果您需要根据成功/不成功的数据库提交向用户显示非常具体的信息,那么您可以查看创建custom ActionResults,根据数据库事务中发生的情况重定向到某些视图。

    最后,关于从服务器取回数据并使用 Knockout...

    1. 如果您的属性名称大小写相同,或者您创建了稍微更明确的映射,映射插件将再次起作用
    2. 我自己的 JS 对象技巧如下。初始化函数是我创建的,它应该可以在所有对象中重用,因为它只是说“如果属性名称匹配(在小写之后),要么通过调用函数来设置它们(兼容敲除),要么只分配值。:

      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 是很好的答案。有很好的例子就很清楚了。
    猜你喜欢
    • 2014-02-19
    • 2015-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-09
    • 1970-01-01
    • 2012-12-26
    • 2012-11-06
    相关资源
    最近更新 更多