使用MVC4 ApiController实现乐观并发

时间:2013-11-27 17:17:53

标签: javascript vb.net asp.net-mvc-4 knockout.js

我有一个MVC 4混合SPA(每个函数是一个SPA,但在函数之间导航,重新加载页面)是用Visual Studio 2012创建的,我打算依赖Entity Framework和乐观并发(虽然更新不会去通过实体框架,我可以使用它的一些乐观并发框架来存储或比较原始值。所以我使用POCO来表示我的对象模型,就像这样......

Partial Public Class FS_Item
   Public Property ItemNumber As String
   Public Property ItemDescription As String
   Public Property ItemUM As String
   ' zillions more properties
   Private _ItemInventories As ICollection(Of FS_ItemInventory) = New HashSet(Of FS_ItemInventory)
   Public Overridable Property ItemInventories As ICollection(Of FS_ItemInventory)
      Get
         Return _ItemInventories
      End Get
      Friend Set(value As ICollection(Of FS_ItemInventory))
         _ItemInventories = value
      End Set
   End Property

End Class

我有一个用ApiController派生的类实现的RESTful API,如此......

Public Class FSItemController
   Inherits ApiController

   Private data As New FSDB()

   ' GET api/fsitem
   Public Function GetValues() As IEnumerable(Of FS_Item)
      Return data.FS_Item.Take(50).ToArray()
   End Function

   ' Etc...

   ' POST api/fsitem
   Public Sub PostValue(ByVal value As IEnumerable(Of FS_Item))
      ' Not implemented yet
   End Sub
End Class

按照Todo列表应用程序的SPA示例代码,我有一个客户端datacontext可以发布数据,我正在考虑从网格控件中做这样的事情......

window.webui = window.webui || {};

window.webui.inventorycontext = (function () {
    var datacontext = {
        getItems: getItems,
        getItem: getItem,
        getNextItem: getNextItem,
        saveItems: saveItems
    };
    return datacontext;

    function getItems(itemsObservable, errorObservable) {
        return ajaxRequest("get", inventoryUrl())
            .done(getSucceeded)
            .fail(getFailed);
       // ...
    }

    // ...

    function saveItems(items, errorObservable) {
        return ajaxRequest("post", inventoryUrl(), items)
            .done(postSucceeded)
            .fail(postFailed);

        function postSucceeded(data) {
           // Not implemented yet
        }

        function postFailed() {
            errorObservable("Error saving items.");
        }
    }

    function ajaxRequest(type, url, data, dataType) { // Ajax helper
        var options = {
            dataType: dataType || "json",
            contentType: "application/json",
            cache: false,
            type: type,
            data: data ? ko.toJSON(data) : null
        };
        var antiForgeryToken = $("#antiForgeryToken").val();
        if (antiForgeryToken) {
            options.headers = {
                'RequestVerificationToken': antiForgeryToken
            }
        }
        return $.ajax(url, options);
    }
    // routes
    function inventoryUrl(id) { return "/api/FSItem/" + (id || ""); }
    function inventoryNextUrl(id, next) { return "/api/FSItem/" + (id || "") + "?nextItem=" + next; }
})();

网格基于SlickGrid,来自的数据由save文件中的.viewmodel.js函数提取,如此...

self.save = function () {
    grid.getEditorLock().commitCurrentEdit();
    var items = grid.getData().getItems();
    datacontext.saveItems(items, error);
};

BTW,我也使用knockout进行数据绑定,并且我已经包含了jQuery和jquery-ui的元素。

我在读取值,更改值以及将整个数组发布回服务器并在调试器中查看更新方面取得了巨大成功,但还没有找到一种最佳方式来安全地保存它们。

最后我的问题。我已经读过有一个惯例,其中knockoutjs和可能的其他框架都知道在删除对象中添加_destroy属性或其他内容会将其视为已删除,因此服务器代码可以知道它的删除。我怀疑使用乐观并发处理更新的对象可能会有类似的约定,但即使有,我也不清楚这些信息如何使它回到服务器,因为我在服务器端的对象模型不包括像_destroy或其他对象这样的属性,添加它们可能会偏离POCO理想,对吗?

确保客户端提交的更新对象自上次访问后没有更改的正确方法是什么。如果不存在原始值和新值,我可能会想出我自己的方法来跟踪客户端上的原始值和新值(尽管我有兴趣了解可能已存在的机制)。但是我很难知道如何在不污染POCO对象的情况下将这些信息传回ApiController。有没有人用这组框架实现乐观并发?

1 个答案:

答案 0 :(得分:0)

我在控制器中创建了一个新类:

Public Class PostedFS_ItemData
   Public Property originals As FS_Item()
   Public Property updated As FS_Item()
End Class

并更新了我的Post方法:

Public Sub PostValue(ByVal value As PostedFS_ItemData)
   'Not implemented yet
End Sub

现在我想我可以根据所需的键值将原始行映射到更新的行。