Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any AngularJS + ASP.NET-WebApi + OData + Breeze.js + Typescript examples or did someone try to combine those

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

like image 899
Medet Tleukabiluly Avatar asked Mar 15 '15 08:03

Medet Tleukabiluly


3 Answers

evc, please take a look at the following article under AngularJs Apps/Projects. You'll find sample projects that you can actually follow and learn using AngularJs, Breeze, Asp.net Web api. You're right, there's a lot of material out there but there not that effective. Hope it helps. http://www.learn-angularjs-apps-projects.com/

like image 176
Danial Lokman Avatar answered Sep 28 '22 03:09

Danial Lokman


Have a look at the Breeze samples, especially WEB Api OData and Breeze. It's sample tutorial for a angularjs+webapi+odata+breeze, no typescript (but isn't javascript just typescript :). For your WEB Api controllers you should definitely install this nuget package :

PM> Install-Package Breeze.Server.WebApi2

This will allow you to build a breeze aware api controller and expose breeze odata metada easily using the Breeze.Server.ContextProviderClass.

like image 22
Eric H. Avatar answered Sep 28 '22 01:09

Eric H.


Also you can check the excelent but paid training from Pluralsight. It covers SPA from scratch using JavaScript, Angular, and Breeze.

http://www.pluralsight.com/courses/build-apps-angular-breeze

like image 23
Iezekiel Avatar answered Sep 28 '22 03:09

Iezekiel