Breezee and linqtosql - breeze

I'm new on Breezee, I'm looking the examples and Breezee has good support for EntityFramework.
readonly EFContextProvider<TodosContext> _contextProvider =
new EFContextProvider<TodosContext>();
// ~/breeze/todos/Metadata
[HttpGet]
public string Metadata() {
return _contextProvider.Metadata();
}
But actually my data model is LinqToSql. Can I use Breezee with LinqToSql? How do I configure the metadata?
Thanks

You will need to either
1) construct the metadata yourself on the server in json format and return that. See Metadata format.
or
2) create the metadata on the client using the MetadataStore api and then configure your dataservice so that it does not expect server side metadata. The Edmunds example in the Breeze zip shows an example of doing something like this.
var dataService = new DataService({
serviceName: "MyServiceName",
hasServerMetadata: false
});
ver myEntityManager = new EntityManager({
dataService: dataService,
});

Related

How to add another parameter to formdata in AngularJS

I am sending a file object to my server from angularJS like this -
var fd = new FormData();
fd.append('file', file);
var deferred = $q.defer();
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
}).success(function(data, status, headers, config){
deferred.resolve(data);
})
.error(function(data, status, headers, config){
deferred.reject('some error occurred');
});
This is my Asp.Net MVC controller -
public HttpResponseMessage Post([FromBody]HttpPostedFileBase file)
I want to send one more parameter (say userId) with the same request. Is it possible to do so? How should I recieve it at the server end. I tried adding fd.append('userId', userId) to the formdata object, but it didn't work. Please tell how to achieve this.
Thanks in advance.
Edit1: When I do bind like I mention, I get below error:
Can't bind multiple parameters ('file' and 'userId') to the request'scontent.
Edit2: I also tried creating an object like so -
public class PostedInfo{
public HttpPostedFileBase file {get;set;}
public string userId {get;set;}
}
and changed post method to -
public HttpResponseMessage Post([FromBody]PostedInfo fd)
But, now this error is thrown, which is quite obvious as the request is json -
The request entity's media type 'multipart/form-data' is not supported for this resource.
Not sure how to tell tell that fd.file is a multipart/form-data entity.
I finally figured this out. The issue is that HttpPostedFileBase seems to not work quite well with webapi, so instead one should use MultipartFormDataStreamProvider for this. Code below -
[HttpPost]
public async Task<HttpResponseMessage> Post()
{
if (Request.Content.IsMimeMultipartContent())
{
string path = HttpContext.Current.Server.MapPath("~/Resources");
var provider = new MultipartFormDataStreamProvider(path);
await Request.Content.ReadAsMultipartAsync(provider);
// get the additional parameter
var userId = provider.FormData.GetValues("userId").FirstOrDefault();
string filepath = provider.FileData[0].LocalFileName;
return <your_custom_response_here>;
}
Here, you can see, I also got the userId in the server code apart from uploading the file.
Well, MultipartFormDataStreamProvider will save the file with a cryptic name (BodyPart_...). You can get rid of that by building your own CustomMultipartFormDataStreamProvider. Found an awesome link as to how to format the file name while saving. Worth a read.

manager.fetchMetadata() error in breeze

My goal is to create new entity of a new type and push it to manager.
I've created new entity type:
var newType = new breeze.EntityType({
shortName: "input"
});
To be able to create new entity of this type I need to fetch metadata first:
var entityManager = new breeze.EntityManager('api/Db');
entityManager.fetchMetadata(success, failed);
function success(){
var newEntity = entityManager.createEntity('input', {});
}
function failed(){}
The problem is that I have an error on the line entityManager.fetchMetadata(): "TypeError: Cannot call method 'then' of undefined"
Why I'm seeing this error?
does fetchMetadata() tries to http: GET metadata from somewhere? I don't have it anywhere.. How to create the metadata then?
UPDATE:
following suggestions I've rewrite code into:
//create new entity type
var newType = new breeze.EntityType({
shortName: "input",
autoGeneratedKeyType: breeze.AutoGeneratedKeyType.KeyGenerator
});
//add property
var info = new breeze.DataProperty({
name: "text",
dataType: breeze.DataType.String,
isNullable: true,
isPartOfKey: true,
maxLength: 20
});
newType.addProperty(info);
//create metadata on fly
var metadataStore = new breeze.MetadataStore();
metadataStore.addEntityType(newType);
var dataService = new breeze.DataService({
serviceName: 'isdataservice',
hasServerMetadata: false
});
var entityManager = new breeze.EntityManager({
dataService: dataService,
metadataStore: metadataStore
});
//create entry
var entity = entityManager.createEntity('input', { name: "nnn" });
Breeze metadata is information about all the objects you have to work with. You can fetch metadata from server-side or you can create metadata by yourself and work with it.
If you want to work with your server-side objects in breeze you create an entity manager with var entityManager = new breeze.EntityManager('api/Db'); where api/db is your asp.net controller. This controller should have a Metadata() method which returns repository.Metadata(). In js you call entityManager.fetchMetadata().then(success, failed); After the promise of fetchMetadata() is resolved, breeze metadata of variable entityManager is full-filled and you can start working with your server-side objects in js with breeze!
But you can also work without any metadata from server-side and create it on the fly in your js code. You create your own metadataStore, attach it to entitymanager. Pseudo code:
var myMetadataStore = new breeze.MetadataStore();
myMetadataStore.addEntityType({...});
var dataService = new breeze.DataService({
serviceName: 'demo',
hasServerMetadata: false
});
var entityManager = new breeze.EntityManager({
dataService: dataService,
myMetadataStore: store
});
var entity = manager.createEntity(...);
Here is a working sample from breeze with on-the-fly metadata http://www.breezejs.com/breeze-labs/breezedirectivesvalidation
You click on code button or just go to http://plnkr.co/edit/lxPAbIJmRaLmyagXQAFC?p=info to see sources
Also take a look at this link in breeze docs http://www.breezejs.com/documentation/metadata

Why does the Breeze Web API implementation respond to metadata requests with a string instead of a JSON object?

Is there any reason that the Breeze Web API implementation of the response to any metadata requests returns a string instead of a JSON object?
Sending metadata as text adds a lot of overhead over the network (due " encoding) and on clientside due manual JSON.parse.
I think that your controller can simply return the Metadata as JSON by specifying the contentType header:
i.e.
[HttpGet]
public HttpResponseMessage Metadata()
{
var result = new HttpResponseMessage { Content = new StringContent(_contextProvider.Metadata())};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
return result;
}
As of v 1.2.7, the BreezeController attribute now does this automatically.... and thanks for the idea.

Breeze is making request to get metadata from server even if we import metadata at client-side

We are setting breeze metadata via metadataStore and we were using this approach for months now. But the other day we realized even if we use metadataStore to set metadata, breeze makes a request to server to get metadata-it was not making this request a few versions back (I'm not sure which version, but I can trace back).
I coded a T4 template to generate a slightly modified metadata, but breeze doesn't use this, always loads metadata from server and overrides mine.
Here how we set our metadata;
var core = breeze.core,
entityModel = breeze.entityModel,
serviceName = 'api/Service',
metadataStore = new entityModel.MetadataStore();
metadataStore.importMetadata($.toJSON(metadata));
var createManager = function () {
return new entityModel.EntityManager({
serviceName: serviceName,
metadataStore: metadataStore
});
};
Thanks in advance.
You need to create a DataService with 'hasServerMetadata' set to false:
var dataService = new DataService({
serviceName: serviceName,
hasServerMetadata: false
});
return new EntityManager({
dataService: dataService,
metadataStore: metadataStore
});
Hope this helps.

Breezejs EntityManager MetadataStore and fetchEntityByKey

I have a SPA application (durandaljs), and I have a specific route where I map the "id" of the entity that I want to fetch.
The template is "/#/todoDetail/:id".
For example, "/#/todoDetail/232" or "/#/todoDetail/19".
On the activate function of viewmodel, I get the route info so I can grab the id. Then I create a new instance of breezejs EntityManager to get the entity with the given id.
The problem is when I call manager.fetchEntityByKey("Todos", id), the EntityManager doesn't have yet the metadata from the server, so it throwing exception "Unable to locate an 'Type' by the name: Todos".
It only works if first I execute a query against the store (manager.executeQuery), prior to calling fetchEntityByKey.
Is this an expected behavior or a bug ? Is there any way to auto-fecth the metadata during instantiation of EntityManager ?
note: I believe it's hard to use a shared EntityManager in my case, because I want to allow the user directly type the route on the browser.
EDIT: As a temporary workaround, I'm doing this:
BreezeService.prototype.get = function (id, callback) {
var self = this;
function queryFailed(error) {
app.showMessage(error.message);
callback({});
}
/* first checking if metadatastore was already loaded */
if (self.manager.metadataStore.isEmpty()) {
return self.manager.fetchMetadata()
.then(function (rawMetadata) {
return executeQuery();
}).fail(queryFailed);
} else {
return executeQuery();
}
/* Now I can fetch */
function executeQuery() {
return self.manager.fetchEntityByKey(self.entityType, id, true)
.then(callback)
.fail(queryFailed);
}
};
You've learned about fetchMetadata. That's important. If you application can begin without issuing a query, you have to use fetchMetadata and wait for it to return before you can perform any operations directly on the cache (e.g., checking for an entity by key in the cache before falling back to a database query).
But I sense something else going on because you mentioned multiple managers. By default a new manager doesn't know the metadata from any other manager. But did you know that you can share a single metadataStore among managers? You can.
What I often do (and you'll see it in the metadata tests in the DocCode sample), is get a metadataStore for the application, write an EntityManager factory function that creates new managers with that metadataStore, and then use the factory whenever I'm making new managers ... as you seem to be doing when you spin up a ViewModel to review the TodoDetail.
Coming from a Silverlight background where I used a lot of WCF RIA Services combined with Caliburn Micro, I used this approach for integrating Breeze with Durandal.
I created a sub folder called services in the App folder of the application. In that folder I created a javascript file called datacontext.js. Here is a subset of my datacontext:
define(function (require) {
var breeze = require('lib/breeze'); // path to breeze
var app = require('durandal/app'); // path to durandal
breeze.NamingConvention.camelCase.setAsDefault();
// service name is route to the Web API controller
var serviceName = 'api/TeamData',
// manager is the service gateway and cache holder
manager = new breeze.EntityManager(serviceName),
store = manager.metadataStore;
function queryFailed(error) {
app.showMessage("Query failed: " + error.message);
}
// constructor overrides here
// included one example query here
return datacontext = {
getSponsors: function (queryCompleted) {
var query = breeze.EntityQuery.from("Sponsors");
return manager
.executeQuery(query)
.then(queryCompleted)
.fail(queryFailed)
}
};
}
Then in your durandal view models you can just require the services/datacontext. For example, here is part of a sample view model from my app:
define(function (require) {
var datacontext = require('services/datacontext');
var ctor = function () {
this.displayName = 'Sponsors',
this.sponsors = ko.observable(false)
};
ctor.prototype.activate = function () {
var that = this;
return datacontext.getSponsors(function (data) { that.sponsors(data.results) });
}
return ctor;
});
This will allow you to not worry about initializing the metadata store in every view model since it is all done in one place.

Resources