0
votes

Using BreezeJS/Angular/WebAPI(OData), I have set up a project where I can call a GET with:

    breeze.EntityQuery
          .from(resource)
          .using(manager)
          .execute()
          .then(function (data) {
              deferred.resolve(data.results);
          });

However, when I attempt to save changes or create a new entity with:

    var type = manager.metadataStore.getEntityType(model);
    type.setProperties({
        autoGeneratedKeyType: breeze.AutoGeneratedKeyType.KeyGenerator
    });
    var newM = manager.createEntity(type, m);
    manager.saveChanges().then(function () { alert('success'); }, function (error) { prompt("", JSON.stringify(error)); });

I get the error:

"No HTTP resource was found that matches the request URI 'http://localhost:57508/odata/odata/Models'"

This is weird because the URL is wrong. It has the service url plus an extra 'odata'.

My AngularJS factory is pretty simple:

app.factory("EntityManagerFactory", ['breeze', function (breeze) {
    configureBreeze();
    var serviceRoot = window.location.protocol + '//' + window.location.host + '/';
    var serviceName = serviceRoot + 'odata/';
    var factory = {
        manager: newManager,
        serviceName: serviceName,
        metadataStore: {}
    };

    return factory;

function configureBreeze() {
    // use Web API OData to query and save
    breeze.config.initializeAdapterInstance('dataService', 'webApiOData', true);

    // convert between server-side PascalCase and client-side camelCase
    // breeze.NamingConvention.camelCase.setAsDefault();
}

function newManager() {
    var mgr = new breeze.EntityManager(serviceName);

    mgr.fetchMetadata().then(function () {
        //var modelType = manager.metadataStore;
    });
    return mgr;
}
}]);

I'm not really sure where else to look for the extra 'odata' that's being added to the generated URL. Removing the 'odata' from the serviceName then prevents GET's working.

Thanks very much.

2

2 Answers

1
votes

YOU SHOULD NOT PATCH BREEZE!!!

It is not necessary to solve this problem and patching breeze complicates your ability to upgrade as we release new versions which we do about every 2 or 3 weeks.

We are aware of the issue you raise and the discussion at https://github.com/Breeze/breeze.js.samples/issues/31. We're going to do something about it ... we just haven't decided exactly what we'll do.

But meanwhile, you can apply your preferred workaround without changing Breeze.

That's because we made getRoutePrefix a published extension point of the "webApiOData" adapter.

For example, you can do almost exactly as @user2908937 suggests without changing a line of Breeze source.

Simply overwrite that extension method in your application setup logic ... like this.

function configureBreeze() {

    // choose and get the Web API OData DataServiceAdapter
    var adapter = breeze.config.initializeAdapterInstance(
                  'dataService', 'webApiOData', true);

    // override the getRoutePrefix instance method
    adapter.getRoutePrefix = function (dataService) {
        return "";
    };

    // ... more configuration ...
}

This isn't hacking. This is exactly why we exposed this method.

Why don't we just fix it?

Good question.

The ASP.NET Web API OData implementation has undergone so much churn and so many breaking changes that we've been holding back on trying to keep up with until we see stability and proper behavior. The inside-the-$batch url is one of the things they broke recently. It is causing us pain but it is a tiny issue compared to everything else they've broken. We'd prefer a comprehensive solution to death by 1000 cuts.

Recent conversations with the MS team have been encouraging. We intend to try to sync up again soon.

Meanwhile, you're well positioned to take care of this particular issue in the manner I suggested here.

0
votes

It looks like this is a bug with Breeze or maybe an unintended consequence of absolute vs relative urls:

https://github.com/Breeze/breeze.js.samples/issues/31

Basically, if you comment out the code at lines 16573 - 16575 in breeze.debug.js:

if (prefix[0] === '/') {
  prefix = prefix.substr(1);
} // drop leading '/'  (all but IE)

This only fixes Chrome/Firefox. To fix all in my case, I just returned an empty string at the beginning of the function:

webApiODataCtor.prototype.getRoutePrefix = function (dataService) {
  return "";
  // Removed Code
};

Works like a charm then. Guess I'll let .NET minify the js file.