I try to combine these technologies, but nothing good comes, because entity structure metadata is not consumed by breeze.js, even all configurations where setup is a bit complicated situation, there are literally no examples of that, so this is my example code that doesn't It works properly, but for some reason, maybe someone will find my mistake and ultimately help to solve this riddle or find it a starting point.
OdataService.ts
'use strict'; module twine.components { class MetadataStoreOptions implements breeze.MetadataStoreOptions{ namingConvention:breeze.NamingConvention = breeze.NamingConvention.defaultInstance; } class Manager implements breeze.EntityManagerOptions { metadataStore: breeze.MetadataStore; constructor( public dataService: breeze.DataService) { } } class DataServiceOptions implements breeze.DataServiceOptions { serviceName = 'http://twine.azurewebsites.net/odata'; hasServerMetadata = true; } export class ODataService { options: Manager; manager: breeze.EntityManager; metadataStore: breeze.MetadataStore; storeOptions: MetadataStoreOptions; static $inject: string[] = ['$http', '$rootScope']; cache: twine.Model.IEntity[]; constructor(private $http: ng.IHttpService, private $rootScope: ng.IRootScopeService){ this.storeOptions = new MetadataStoreOptions(); this.metadataStore = new breeze.MetadataStore(this.storeOptions); this.options = new Manager( new breeze.DataService( new DataServiceOptions() )); this.options.metadataStore = this.metadataStore; this.manager = new breeze.EntityManager( this.options ); breeze.config.initializeAdapterInstance('dataService', 'webApiOData', true);
And this is tagController.ts
'use strict'; module twine.routes { interface ITagsScope extends ng.IScope { vm: TagsCtrl; } interface ITagsCtrl extends twine.components.ITwineRoute{ tags:any[]; getTags: () => void; tag: any[]; getTag: (id:number) => void; } export class TagsCtrl implements ITagsCtrl{ static controllerId: string = 'TagsController'; static controllerAsId: string = 'tagsCtrl'; static $inject: string[] = ["$scope", "ODataService", '$route']; entityQueryName: string = 'Tag'; query: breeze.EntityQuery; tags:any; tag: any; constructor (private $scope: ITagsScope, private ODataService: twine.components.ODataService, $route: ng.route.IRouteService) { this.query = new breeze.EntityQuery(this.entityQueryName); if($route.current && $route.current.params.id){ this.getTag($route.current.params.id); } else { this.getTags(); } } getTags() { this.ODataService.All(this.query , (data) => { this.tags = data.results[0].value; }, (error) => { console.log('error', error); }); } getTag(id:number){ this.ODataService.Get(id , (data) => { this.tag = data.results[0].value; }, (error) => { console.log('error', error); }); } } }
There are many errors in different configurations, sometimes it is There is no resourceName for this query or EntityKey must be set , or Other stupid errors , which really should not appear, because it is typescript that does not allow type mismatches, but the configuration itself is incorrect.
And this is an abstract controller
[EnableCors(origins: "*", headers: "*", methods: "*")] public abstract class EntityController<T> : ODataController where T: Entity { protected ODataRepository<T> repo = new ODataRepository<T>(); private static ODataValidationSettings _validationSettings = new ODataValidationSettings(); public EntityController() { }
And finally, this is the ASP.NET webApi configuration
public static class WebApiConfig { public static void Register(HttpConfiguration config) { // -API config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html")); // -API config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); //CORS var cors = new EnableCorsAttribute( "*", "*", "*", "DataServiceVersion, MaxDataServiceVersion" ); config.EnableCors(cors); // Odata //config.EnableQuerySupport(); config.AddODataQueryFilter(); Builder<Account>(config); Builder<Branch>(config); Builder<Bucket>(config); Builder<Ingredient>(config); Builder<Like>(config); Builder<Meetup>(config); Builder<Shot>(config); Builder<Skill>(config); Builder<Tag>(config); Builder<Team>(config); } private static void Builder<T>(HttpConfiguration config) where T: class { var entityType = Activator.CreateInstance<T>().GetType(); if (entityType != null) { var builder = new ODataConventionModelBuilder(); builder.EntitySet<T>(entityType.Name); config.Routes.MapODataServiceRoute("odata_" + entityType.Name, "odata", builder.GetEdmModel()); } } }
For testing purposes, I have this working support for the OData service at http://twine.azurewebsites.net/odata/Tag (there are currently no restrictions from CORS, feel free to), the last object can be changed to a different name based on the configuration method webApi Build . Please feel free to ask for any other information. If someone needs a whole source, I am ready to publish it on github
Update
Forget about stretching, the problem is in the Get ODataService method. I canβt bind metadata from the server to the breeze, the Everything method works fine. But the fetchByEntityKey request throws the errors described above