My entity name is "Products" but in my WebApi the route is defined as "GetProducts" so in default it will query against /api/Products? instead of /api/GetProducts, is there any way to specify where it should fetch the data from the server if it can't find what i want in the cache.
So far i got this
manager.fetchEntityByKey("Products", productId, true)
.then(fetchSucceeded)
.fail(queryFailed);
This will call http://localhost:1990/breeze/Products?$filter=Id%20eq%201
But i want it to call http://localhost:1990/breeze/GetProducts?$filter=Id%20eq%201 instead
There's also another option to specify this on the server. With WebApi 2, you can use the RouteAttribute on your controller action to customize the routing.
See http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2
EDIT:
On the client, the Breeze EntityType has a property called defaultResourceName which you can modify as well to tell Breeze which default resource name to use if only an entity type name is specified.
var productType = metadataStore.getEntityType('Products');
productType.defaultResourceName = 'GetProducts';
//Will create fetch request to breeze/GetProducts
manager.fetchEntityByKey('Products', productId);
You can change entity's default resourceName(that hits the breeze webapi method name) with
manager.metadataStore.setEntityTypeForResourceName("GetProducts", "Product")
But be sure the code above is executed when promise of manager.fetchMetadata() is resolved:
manager.fetchMetadata().then(function(){
manager.metadataStore.setEntityTypeForResourceName(...);
})
If setEntityTypeForResourceName is called before metadata has loaded you will get an error, i.e
Unable to locate 'entityTypeName' of: Product
You can set the Resource for the given entity type which would hit the resource instead -
manager.metadataStore.setEntityTypeForResourceName('GetProducts', 'Products');
But as a note it seems like a design flaw to name your entity Products instead of Product.
Related
How do I get handle of the OData query parameters in a Brezze WebApi controller?
I have a endpoint where only a single entity will be queried at a time. The controller just calls a repository that returns a context.Set().AsQueryable();
I want to be able to get the entity ID out of the parameters and update(plain EF) a count property on it before querying it for the response.
Thanks
I found what I needed.
By adding a ODataQueryOptions<T> odataQueryOptions argument to the endpoint I was able to access the OData query parameters and get the ID I needed by getting this property:
var where = odataQueryOptions.RawValues.Filter;
Filter value in my case looks like this: Id eq 'dd3d6cb2-bc7a-467e-9730-c43c333b6fda'
Edit:
If you use .withParameters() on your breeze query object, you can pass additional parameters to your end-point without bothering to deal with OData.
I am using an OData model for a table, but the data is not loaded. The OData model is created by constructor in the following way:
new sap.ui.model.odata.ODataModel("/XMII/IlluminatorOData/QueryTemplate?QueryTemplate=testTemplate", {annotationURI: "/XMII/IlluminatorOData/$metadata"});
I cannot use the root URI of the OData service, because I need to specify a QueryTemplate.
After setting the model to the table, bindRows method is invoked with parameter "/Row".
table.bindRows("/Row")
The template for a column is a TextField.
template: new sap.ui.commons.TextField().bindProperty("value", "PROJECT")
The data is not shown and not even requested. Only metadata is fetched. What am I doing wrong with OData model? If I fetch the URI which was passed to the model with a get request, content is available.
Are you sure the URL is right?
Shouldn't it be something like "/XMII/IlluminatorOData/?QueryTemplate=testTemplate"
The ODataModel needs to load the metadata in order to work, this means it fetches it from "[ServiceUrl]$metadata", which would be "/XMII/IlluminatorOData/QueryTemplate/$metadata" in your case. But you also use the metadata as annotation source - there you use a different URL, so I guess you first one is wrong...?
in ASP.NET MVC application I want to verify entity ownership on edit action (already on get).
I have implemented custom IPrincipal, so I have actual user ID, but how to compare it with entity property?
The only way I see is to load the entity and compare it, which makes bunch of if conditions in every action method.
Ideal would be some attribute, but inside the attribute I have only the entity ID, not the entity itself and you can't pass any object (nor entity neither repository) to attribute.
How do you solve this?
Thanks
I solved this by extension method over the EntityBase implementing interface IOwnedEntity (with two properties: Id and OwnerId).
In this extension method I compare the IOwnedEntity.OwnerId with actual user Id (got from cookies) and if not equal I throw my own typed exception (NotAuthorizedException).
I'm attempting to create an instance of an entity and two child entities at the same time.
If I post the following JSON to the /user_objects resource it happily creates the parent user_object entity and the linked User_object_attribute entity. The only problem is that I can't seem to expand the result set to include the new user_object_attribute so I effectively have the most uptodate version of the user_object but I have to then go and read from the OData service i.e. another server hit in order to retrieve the user_object_attributes.
Upon returning I have the id that would go neatly into the child user_object_attribute object but what if the child had a further server-side generated field like created_date? Then I still have to hit the OData repo again?
I've tried the correct $expand query ?$expand=user_objects_attributes and while the creation succeeds I still am not returned the expanded result set.
Would anyone have any idea if this is possible? Or is it a case that it isn't because hte only way to do it would be to return all the child user_object_attributes?
{
"annotator_id":1,
"content_type":"content_type",
"created_date":"2013-02-15T17:20:09.191",
"guid":"GUID",
"size_kb":100,
"title":"Title",
"updated_date":null,
"url":"URL",
"user_object_id":0,
"user_objects_attributes":[
{
"attribute_id":0,
"name":"name191",
"user_object_id":0,
"value":"value191"
}
]
}
Thanks,
Mark.
Looking at the OData V3 specification here:
In version 1.0 and version 2.0, if the insert succeeds in full, the
server MUST return a response with a 201 (Created) status code and a
response body that conforms to the syntax specified in InsertEntity
Request (section 2.2.7.1.1). The response body MUST contain the values
of the inserted resource after the server has executed all its
server-specific data processing rules (validation, and so on). The
server MAY alter the values of the resource received from the client
before the resource is inserted on the server.
In version 3.0, the response MAY have a 204 status code, as specified
in [RFC2616], based on the client preference (see Prefer (section
2.2.5.9)) on the InsertEntity Request.
Not super clear what a server should do... return just the top level created entity, or that entity and all of it's expanded links as well.
I'm not surprised that $expand would have no effect on POST (or any CUD requests). WCF DS probably ignores it if it isn't a query. And by the spec, this is probably correct.
Quite frankly, I think with WCF DS Server you can't get anything else back. In V3 you either get a 201 with your entity (only), or a 204 no content if you specify the header saying that you want no content.
Whether that is OData compliant or not... not totally sure :-). Regardless, I don't think you can get what you want on the WCF DS stack at this point in time.
I was able to return navigation properties after a POST to create a new entity using OData v4's $expand query option without issues.
Make sure your method is decorated with [EnableQuery] and you call Include with the name of the navigation property.
For example:
[EnableQuery]
public IHttpActionResult Post(user_object user)
{
if (!this.ModelState.IsValid)
{
return this.BadRequest(this.ModelState);
}
this.db.user_objects.Add(user);
this.db.SaveChanges();
user = this.db.user_objects.Include("user_objects_attributes").Single(x => x.user_object_id == user.user_object_id));
return this.Created(user);
}
The POST URL query string should include ?$expand=user_objects_attributes.
Also see:
https://github.com/OData/WebApi/issues/356
I'm new to MVC and I've been looking through a bunch of examples.
For the HttpPost on some edits they call UpdateModel(entity).
In other examples such as:
http://www.asp.net/mvc/tutorials/mvc-music-store-part-5
UpdateModel(entity) isn't called at all.
What's the point of calling this function when it appear unneccessary in MVCMusicStore?
Apparently it " Updates the specified model instance using values from the controller's current value provider."
However I've found from the MVCMusicStore example the updated values are already posted through?
Could someone please explain this to me?
There should be no reason for you to use UpdateModel in the newer version of ASP.NET MVC
Originally it was provided because when you posted your data back to the action on your controller, a FormsCollection would be passed in to to the action and then a call to UpdateModel(entity) would be required.
However in newer versions of ASP.NET MVC the concept of ModelBinding has been introduced which will allow your actions to define a .net object to be passed in to your action methods and the model binder will take care of "binding" the values to the model.
To be completely honest, I'm not sure why they don't just deprecate the UpdateModel() method because AFAIK it's completely redundant.
Use UpdateModel for PATCH semantics. From RFC5789:
The PATCH method requests that a set of changes described in the
request entity be applied to the resource identified by the
Request-URI.
This means you are making modifications to an existing resource (e.g. from the database).
Use the object as action method parameter for PUT semantics.
The difference between the PUT and PATCH requests is reflected in the
way the server processes the enclosed entity to modify the resource
identified by the Request-URI. In a PUT request, the enclosed entity
is considered to be a modified version of the resource stored on the
origin server, and the client is requesting that the stored version be
replaced.
In practice, there's not much difference if the request contains values for all of the resource members. But if the request only contains values for a subset of the resource members, in PATCH the other members are left unmodified, and in PUT are set to their default value (usually NULL).
i don't think ModelBinding is only introduced in newest version of asp.net mvc (newest version is 3). it was present at least in v-2 so far as i can tell. when you call the updatemodel you call Modelbinding explicitly. when you receive at as action method parameter Modelbinder is called implicitly.
In Edit scenario updateModel is used when we fetch original entity from db and tell controller to update it using UpdateModel like
public ActionResult Edit(int id)
{
var entity = db.GetEntity(id);
UpdateModel(entity);
db.SaveChanges();
}
Other scenario is when you are not fetching db entity but ModelBinder gives you an entity created from form fields etc. and you tell you db that object is already there and it has been modified outside the db and you better sync with it like in MusicStore tutorial.