6
votes

I am looking in to using breezejs and have a few questions in terms of its capabilities and the best practices that come with it.

  1. Does server side metada have to exist? If I have a non EF WebApi controller do I still have to wrap it with the ProviderContext and implement metadata? If so, what is the format of the metadata?
  2. If I am able to omit metadata on the server side and just implement the queryable actionfilter, can I still write client side code to define the metadata? Where would I find information on how to do this?
  3. I have a server Model class called Job with an id and name, which are simple properties and an object property called Company which points to a server side model class called Company which has an id and name. Job(s) can be confidential (through a boolean IsConfidential property on Job) in which case even though they still have a companyId, that property should not be sent to the client. Instead there should be a server-side computed property called CompanyName (basically Company.Name for non-confidential Jobs and "Confidential" for confidential jobs) that is sent to the client. Admin roled users should be able to see and edit CompanyId but regular users should not be able see or post/put that value. How do you accomplish this in breeze? Does breeze deal well with sending and receiving non-Model ViewModels (less properties and some computed properties)?
  4. Is the source for the source code for the ODataActionFilter something I can use and change for any purpose I want?
  5. How difficult would it be to create WebApi Controllers for something other than EF - maybe like Telerik OpenAccess?

Thanks

3

3 Answers

6
votes

Pawel's post is correct that you should start by calling

breeze.config.initializeAdapterInstances

To actually create the client side metadata you would write something like this. ( A simple example).

initializeMetadataStore(myEntityManager.metadataStore);

function initializeMetadataStore(metadataStore) {
    var et = new EntityType({
        shortName: "Person",
        namespace: "Sample_WebApi.Models"
    });
    et.addProperty( new DataProperty({
        name: "personId",
        dataType: DataType.Int32,
        isNullable: false,
        isPartOfKey: true,
    }));
    et.addProperty(new DataProperty({
        name: "firstName",
        dataType: DataType.String,
        isNullable: false,
    }));
    et.addProperty(new DataProperty({
        name: "lastName",
        dataType: DataType.String,
        isNullable: false,
    }));
    et.addProperty(new DataProperty({
        name: "birthDate",
        dataType: DataType.DateTime,
        isNullable: true
    }));
    et.addProperty(new NavigationProperty({
        name: "meals",
        entityTypeName: "Meal",
        isScalar: false,
        associationName: "personMeals"
    }));
    metadataStore.addEntityType(et);

    et = new EntityType({
        shortName: "Meal",
        namespace: "Sample_WebApi.Models"
    });
    et.addProperty(new DataProperty({
        name: "mealId",
        dataType: DataType.Int32,
        isNullable: false,
        isPartOfKey: true,
    }));
    et.addProperty(new DataProperty({
        name: "personId",
        dataType: DataType.Int32,
        isNullable: false,
    }));
    et.addProperty(new DataProperty({
        name: "dateConsumed",
        dataType: DataType.DateTime,
        isNullable: false,
    }));
    et.addProperty(new NavigationProperty({
        name: "person",
        entityTypeName: "Person",
        isScalar: true,
        associationName: "personMeals",
        foreignKeyNames: ["personId"]
    }));
    et.addProperty(new NavigationProperty({
        name: "dishes",
        entityTypeName: "Dish",
        isScalar: false,
        associationName: "mealDishes",
    }));
    metadataStore.addEntityType(et);

    et = new EntityType({
        shortName: "Dish",
        namespace: "Sample_WebApi.Models"
    });
    et.addProperty(new DataProperty({
        name: "dishId",
        dataType: DataType.Int32,
        isNullable: false,
        isPartOfKey: true,
    }));
    et.addProperty(new DataProperty({
        name: "foodName",
        dataType: DataType.String,
        isNullable: false,
    }));
    et.addProperty(new DataProperty({
        name: "servingSize",
        dataType: DataType.Double,
        isNullable: false,
    }));
    et.addProperty(new NavigationProperty({
        name: "food",
        entityTypeName: "Food",
        isScalar: true,
        associationName: "DishFood",
        foreignKeyNames: ["foodName"]
    }));
    metadataStore.addEntityType(et);

    et = new EntityType({
        shortName: "Food",
        namespace: "Sample_WebApi.Models"
    });
    et.addProperty(new DataProperty({
        name: "foodName",
        dataType: DataType.String,
        isNullable: false,
        isPartOfKey: true,
    }));
    et.addProperty(new DataProperty({
        name: "calories",
        dataType: DataType.Int32,
        isNullable: false,
    }));
    metadataStore.addEntityType(et);
}
2
votes

1 You can configure metadata on the client. To turn off server metadata try this:

config.initializeAdapterInstances(
    new DataService({ 
        serviceName: "yourServiceNameHere",
        hasServerMetadata: false }));

2 Please look at the Breeze docs and api. Start here EntityType and here Extending Entities

2
votes

Per question 3: There are several possible approaches to this.

The first is that you can return objects that are not 'entities' to the client and these can be of virtually any shape. So you can determine what properties to include or exclude from them. Basically any object returned from the server for which matching client side metadata cannot be found will be returned as an anon json object. Note that these anon objects will not be wrapped by any binding library, i.e. ko, backbone, angular etc, and these objects will not be added to the entityManager cache.

A 2nd alternative is to use the json.net serialization interception points. (see the json.net help). This will allow you to conditionally suppress the serialization of selected properties. Be careful with this because if you try to resave any entities that have been returned to the client after having been "sanitized" you will need to restore these properties to their original values (on the server) before completing the save.

Per question 4: breeze is open source and available on github. You can use the source freely.

Per question 5: In the most recent versions of the breeze.webApi.dll we already refactored our EF specific code from our base webApi functionality for exactly this purpose. We haven't completed documenting this yet, but you can take a look at the "ContextProvider" and "EFContextProvider" classes in the Breeze.webApi project to see what another provider might look. We plan on showing a NoSQL provider for something like mongodb sometime in the near future. Please vote on the breeze user voice for any specific suggestions in this area.