Im trying to combine those technologies, but nothing good comes, as entity framework meta-datas doesn't get consumed by breeze.js, even all configurations where setup, it's a bit tricky situation, there is literally no examples of that, so this is my sample code which doesn't work properly, but somehow maybe someone will find my mistake and eventually help to solve this puzzle or will find it as 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);
//this.manager.fetchMetadata((meta) => {
// this.metadataStore.importMetadata(meta);
//});
}
All( query:breeze.EntityQuery, successCallback: Function, failCallback?: Function ): void {
this.manager.executeQuery( query )
.then( ( data: breeze.QueryResult ) => {
successCallback( data );
this.$rootScope.$apply();
})
.catch( ( reason: any ) => {
if ( failCallback ) {
failCallback( reason );
}
});
}
Get( key:number, successCallback: Function, failCallback?: Function ): void {
//this.manager.fetchMetadata();
//var entityType = this.manager.metadataStore.getEntityType('Tag');
//var entityKey = new breeze.EntityKey(entityType, key);
this.manager.fetchEntityByKey( 'Tag', key )
.then( ( data: breeze.EntityByKeyResult ) => {
successCallback( data );
this.$rootScope.$apply();
})
.catch( ( reason: any ) => {
if ( failCallback ) {
failCallback( reason );
}
});
}
}
}
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{
/* @ngInject */
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, on different configurations, sometimes it's There is no resourceName for this query
or EntityKey must be set
, or Other stupid errors
which are indeed doesn't have to appear because it's a typescript which doesn't allow type mismatches, but the configuration itself is not correct.
And this is 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()
{
}
// GET: odata/Entity
[EnableQuery]
public IQueryable<T> Get(ODataQueryOptions<T> queryOptions)
{
try
{
queryOptions.Validate(_validationSettings);
}
catch (ODataException ex)
{
Trace.WriteLine(ex.Message);
return null;
}
return repo.All();
}
// GET: odata/Entity(5)
[EnableQuery]
public SingleResult<T> Get([FromODataUri] long key, ODataQueryOptions<T> queryOptions)
{
try
{
queryOptions.Validate(_validationSettings);
}
catch (ODataException ex)
{
Trace.WriteLine(ex.Message);
return null;
}
return SingleResult.Create(repo.All().Where(x=>x._id == key));
}
//ommitted
}
And lastly this is 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 purpose i have this working backed OData service at http://twine.azurewebsites.net/odata/Tag
, (currently no restrictions by CORS, feel free) last entity can be changed to other name based on webApi configuration Build
method. Please feel free to ask any other information. If someone need whole source, im willing to publish on github
Update
Forget to mension, problem is in method Get
of ODataService. I cannot bind metadata from server to breeze, method All works fine. But query fetchByEntityKey
throws errors as described above
OdataService.ts
, how to configure breeze? By documentation, my setup is right – Luckin