尝试使用带有breeze.js的自定义数据存储,自定义JsonResultsAdapter和mockJson AJAX适配器

时间:2014-01-11 01:53:12

标签: ajax breeze

我一直试图弄清楚这里出了什么问题。我创建了一个mockJson适配器来拦截Ajax请求。我基本上只是在我的适配器中调用success方法而不是进行Ajax调用。正如您所看到的,我正在使用mockJson欺骗一些JSON数据。

ctor.prototype.ajax = function (config) {

    var jqConfig = {
        type: config.type, 
        url: config.url,
        data: config.params || config.data,
        dataType: config.dataType,
        contentType: config.contentType,
        crossDomain: config.crossDomain
    }

    if (!core.isEmpty(this.defaultSettings)) {
        var compositeConfig = core.extend({}, this.defaultSettings);
        jqConfig = core.extend(compositeConfig, jqConfig);
    }

    jqConfig.success = function (data, textStatus, XHR) {

        var httpResponse = {
            data: data.results,
            //status: XHR.status,
            //getHeaders: getHeadersFn(XHR),
            config: config
        };
        config.success(httpResponse);
        //XHR.onreadystatechange = null;
        //XHR.abort = null;
    };
    jqConfig.error = function (XHR, textStatus, errorThrown) {
        var httpResponse = {
            data: XHR.responseText,
            status: XHR.status,
            getHeaders: getHeadersFn(XHR),
            error: errorThrown,
            config: config
        };
        config.error(httpResponse);
        XHR.onreadystatechange = null;
        XHR.abort = null;
    };

    jqConfig.success($.mockJSON.generateFromTemplate({
        "results|1-1": [{
            "id|+1": 1,
            "$type": "Campaign",
            "name": "Campaign Name",
            "startDate": "2013-12-03T00:00:00.000",
            "budget|1-3000": 1
        }]
    }), null, null);

};

为简单起见,现在返回单个结果。接下来我也有一个自定义的JsonResultsAdapter。这基本上是将$ type属性映射到实体转换所需的元信息:

      function configureBreezeManager() {

        var jsonResultsAdapter = new breeze.JsonResultsAdapter({
            name: "mockJson",
            extractResults: function (json) {
                return json.results;
            },
            visitNode: function (node, mappingContext, nodeContext) {

                var entityType = node["$type"];

                return {
                    entityType: entityType
                };
            }
        });

        var dataService = new breeze.DataService({
            serviceName: config.remoteServiceName,
            jsonResultsAdapter: jsonResultsAdapter,
            hasServerMetadata: false // don't ask the server for metadata
        });

        var mgr = new breeze.EntityManager({ dataService: dataService });
        model.configureMetadataStore(mgr.metadataStore);

        //are we debugging? Lets use mockJson
        if (config.debugEnabled())
            breeze.config.initializeAdapterInstance("ajax", "mockJson", true);

        return mgr;
    }

最后,我在查询之前创建并调用了元数据模型对象:

    function configureMetadataStore(metadataStore) {

        addLookupTypes(metadataStore);
        addCampaignType(metadataStore);
        addMessageType(metadataStore);

        metadataStore.setEntityTypeForResourceName('Campaigns', 'Campaign');
        metadataStore.setEntityTypeForResourceName('Messages', 'Message');
        metadataStore.setEntityTypeForResourceName('Demos', 'Demo');

        referenceCheckValidator = createReferenceCheckValidator();
        Validator.register(referenceCheckValidator);

        log('Validators registered');
    }

        function addCampaignType(store) {
        store.addEntityType({
            shortName: "Campaign",
            namespace: "My.Models",
            dataProperties: {
                id: { dataType: DataType.Int32, isNullable: false, isPartOfKey: true },
                name: { dataType: DataType.String, maxLength: 30, isNullable: false }
            }
        });

        store.registerEntityTypeCtor("Campaign", null, campaignInitializer);
    }

    function campaignInitializer(campaign) {
        campaign.errorMessage = ko.observable();

        campaign.startDateFormatted = ko.computed(function () {
            return moment(campaign.startDate()).format("MM-DD-YYYY");
        });
    }

我的查询:

         var query = EntityQuery.from('Campaigns').
            select('id, name, startDate, budget')
            .orderBy(orderBy.campaign);

首先,如果我基本上以普通WebApi响应的形式欺骗数据,我认为我不需要自定义JsonResultsAdapter,但是我根据一些StackOverflow帖子设置了它。我遇到的问题是返回的实体没有将属性包装为knockout observables。后来的代码因此而失败,如果不发生这种情况,我将无法利用微风的所有方面。非常感谢任何帮助!

2 个答案:

答案 0 :(得分:0)

你这里有很多活动部件。我更倾向于选择一条更简单的道路。

当我读到你的时候,你正试图在开发期间创建一些模拟数据,而不是测试(如果你正在测试我会讨论sinon.js)。

除非您使用我们不支持开箱即用的数据源模拟对话,否则我不会弄乱jsonResultsAdapter。你没说。假设您正在尝试模拟ASP.NET Web API返回的JSON.NET结果(如果我猜错了,您可以纠正我。)

我注意到你的模拟JSON结果有camelCase属性。这不是我期望的服务器端业务模型,用静态类型语言编写,其中约定是PascalCase。例如,这里是“房间”响应的片段:

{
    $id: "2",
    $type: "CC.Model.Room, CC.Model",
    Id: 1,
    Name: "Surf A"
},
{
    $id: "3",
    $type: "CC.Model.Room, CC.Model",
    Id: 2,
    Name: "Surf B"
},

我注意到你的模型类有一个命名空间“My.Models”,所以我希望你能生成类似“My.Models.Campaign,My.Models”的$ type。

这些只是一些可能的断开连接。

创建一个丢弃数据库可能会更快,用一些数据填充它,然后点击一个微风客户端来查看你应该与你的模拟相匹配的元数据和JSON回复。

HTH

答案 1 :(得分:0)

感谢您的回复沃德。我简化了一切,并按照您的建议实际测试了真实的服务器响应。当我这样做时,它仍然被打破了。然后我试着比较我的应用程序和我做的另一个对我有用的差异。加载淘汰赛时,问题出在我的应用程序内部,它与require.js的加载方式与Breeze预期的不同。

本文捕捉到了正在发生的事情:BreezeJS integration with DurandalJS issues related to how KnockoutJS is loaded

所以我意识到没有找到淘汰赛,并将以下代码添加到我的durandal的main.js文件中,以不同方式映射淘汰赛,以便找到它:

map: {
    '*': { 'knockout': 'ko' }
}

再次感谢您的回复。 Breeze有没有办法提醒你它无法实例化淘汰?

我在代码中看到了这个:ko = core.requireLib(“ko”,“The Knockout library”);