Hi I'm trying to get Breeze to create a metadata store but its failing with the message
NamingConvention for this server property name does not roundtrip properly
I had the same self referencing loop with the out of the box Web API and was able to solve but setting
json.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
Any help or solutions would be greatly appreciated.
Thanks
Ok so I solved my own question. My table names all started with lower case, so when I got the round trip error it was because it would look at an entity such as refLookup which was being seen as RefLookup by Breeze but was also referenced an entity as refLookup (no camel case as thats the name of the entity). So I just named all my tables in the database with upper case characters. Hope that helps some one in the future.
The Breeze NamingConvention facility supports property aliasing, not entity type name aliasing. Therefore the spelling of the entity type name must match the server-side type name exactly ... even if you choose the camelCasing NamingConvention or create your own custom NamingConvention plug in.
That's why I'm surprised that you had any difficulty with the table/entity class name casing.
I am unable to reproduce this error. Here is what I tried
Added a 'foo' table to my database
Created a corresponding foo class
Exposed it from the Web API controller as a foos query action method
Queried on the Breeze client for all foos
Breeze client had no trouble returning my (two) foo entities.
Note that I did not try to mess with the NamingConvention on the client. I kept the default ... which is that every client entity property name is the same as its corresponding server property name. As I said, the NamingConvention doesn't do anything with the entity type name and there is no representation in the metadata for a difference between server and client entity type names.
Do you think otherwise? Can you provide a sample?
A strong word of caution: Do NOT change the Json.NET property naming convention. All name aliasing must be done by Breeze on the client.
In general, one should not change a Json.NET configuration setting if the [BreezeController] attribute set that value. The only exception I can think of is null value handling; Breeze tells Json.NET to ignore nulls. I think that is a mistake ... and you can tell Json.NET to send null values if you wish.
I had the same issue when using two managers. I found that if you are using the global
breeze.NamingConvention.{whateverYouUse}.setAsDefault();
it needs to be set prior to creating the manager. Also if you are forcing the json serialization to a specific naming convention on the server the naming convention on the client should match. I am using the breezecontext and as long as its set prior to the manager all works as planned..maybe you don't need the server side setting?
Related
A little background of my problem. I have a set of the following services:
AdapterService - intended for loading certain products from an external system
ApiGateway - accepts requests from UI. In particular, now there is only one request that receives product data to display product in UI from Product Service
ProductService - data storage service for various products. The service itself does not specifically know what kind of product it specifically stores. All types of products are created dynamically by other services that are responsible for these products. Product data is stored as a key-value map (technically it is a json string in DB column)
There is a schema for service interations
So, services in BLUE zone are mine (they can be changed in any way). RED zone describes services of another team (they can't be changed).
Whats the problem
To load product from external system I want to use SpecialProductDto which will store product data. I can use some validation features like Spring annotations and so on. Then to load the product from Adapter Service to ProductService I must transform SpecialProductDto to Map<String, Object> because ProductSerivcie requires it via API.
When I would get product info for UI through ApiGateway, I will need to call ProductService api for getting product that return attribues in Map<String, Object> and then transform this data to some UIReponse which contains some part of product data (because I dont need all product information, just only name and price for example).
But I also want to use SpecialProductDto in my ApiGateway service, because it seems working with Map<String, Object> is error prone... I practically need to fetch data blindly from Map to construct UIResponse. And what if some attribute names will be changed? With Map I only will know it when the request would be made from UI but using special DTO I get such exception in compilation time.
Question
So, what is the best practiсe or maybe patterт should I use in such situation? At the moment I see the following solutions:
Duplicate DTOs in both AdapterService and ApiGateway services. So, any changes in one class must be supported in another
Use Map<String, Object> at my own peril and risk, hoping that nothing will change there
Share SpecialProductDTO between ApiGateway and AdapterSerivce in some separate library and service (seems to be antipattern because of sharing someting can make a lot of problems)
Сan anyone help?
In my opinion, there's nothing wrong on duplicating DTOs.
Also, there's nothing wrong on providing the DTO in a separate library to be imported on each project, you will only be sharing the ProductService's contract and that's it. It does not cause any tight coupling between the Api Gateway and the Adapter. If the contract changes, then it must be changed on all of it's consumers (api gateway and adapter), simple as that.
About using Maps: usually I don't recommend this, because, like you said, you will not be able to take advantages of the built-in Bean Validations that Spring (and other frameworks) provides, but not only that, you'll also, depending on the situation, be using lots of casts and type conversions, which is not good and can be prevented by using DTOs.
Also, be aware that a DTO, in my opinion, should not be named with the suffix of 'DTO'. That's because a name like SpecialProductDTO doesn't clearly states where this object is being used or should be used.
Instead, prefer a something like CreateSpecialProductRequest - this indicates that this object is used when creating a Special Product. Another example is CreateSpecialProductResponse which just represents the response (if needed) after a Special Product creation. Take a look at this StackOverflow answer: Java data transfer object naming convention?
I’m trying to go against a Web API Patch method that accepts a Delta. My entity has a navigational property that is a collection. The domain model is trivial, I have a team (entity) and a collection of members (navigational property).
I’m using HttpClient directly instead of the OData client.
The problem I’m running into is that when I send a patch request with the payload = a Team, the Delta deserialized in my controller is null when I include the navigational property collection in my payload.
Eg (ignore that the missing quotes, this is typed in}:
{ Name: Foo } -> serializes to Delta successfully.
{Name: Foo, Members : [] } -> fails to serialize and Delta is null.
Is this supported? I could not find concrete documentation online about whether you can supply navigational properties as an entire collection on patch (not looking for merge support, just want full replace of the collection.)
I also tried tweaking my client to directly send a Delta payload, but the default JsonMediaTypeFormatter is unable to serialize this into a valid request body (always produces empty Json), and the ODataMediaTypeFormatter throws an exception saying it cannot write an object of type Delta, although I have initialized it with every ODataPayloadKind.
I’m sure I’m either doing something wrong or missing something basic, assuming using Delta + patch with HttpClient is not this challenging.
For OData spec, it says:
11.4.3 Update an Entity
...
The entity MUST NOT contain related entities as inline content. It MAY contain binding information for navigation properties. For single-valued navigation properties this replaces the relationship. For collection-valued navigation properties this adds to the relationship.
That is you can't put the navigation properties in the Patch request content.
From Web API OData, it has these codes and these codes. It means that it doesn't allow to patch navigation property form entity.
However, you can shoot your target by following steps:
Patch the principal entity (team)
Patch the dependent entities (members)
use the $ref to update the link
You can refer to my simple test project.
In order to allow us dynamic control over labels and error messages, we created a custom DataAnnotationsModelMetadataProvider. In a Display attribute we store the key in the Name property and using the custom DataAnnotationsModelMetadataProvider we substitute the key for a string value from our custom CMS. The problem is that we now have two sets of values. One for Web views and one for mobile views. At runtime we check if the client is on a mobile device and substitute the values accordingly.
After test running this setup I came across a strange issue. When the AppDomain is first created and the Name properties of the different data annotations are replaced with the string values, everything works fine. In debug, when I enter the custom DataAnnotationsModelMetadataProvider for a second time, I see the name properties already populated with the values I had substituted the previous run. This was strange to me, since it was my understanding that data annotation propeties could not be chnaged at runtime. It now seems like there is a model metadata cache happening somewhere. Since I based my custom solution on replacing the values each time the DataAnnotationsModelMetadataProvider is called upon, I would like to disable this caching, if possible.
For now I started using the ShortName property as my key storing property and I replace the Name property, and this way I can repopulate the strings on each run. But this was not the initial design and I don't have such a key store property for ValidationAttributes.
So is there a way to disable this cache? I don't need the cache for the sake of caching, since all CMS data is cached in memory in another layer anyway.
I have created a create view within my MVC 2.0 Application and by default it included a field for the integer ID Column.
This is definitely a field i do not need.
If i remove the field and use updatemodel when trying to create the object in code, will something break because it doesnt see my ID column data being passed in, even though it is auto increment?
Also, i noticed that in the NerdDinner example, updatemodel was used and after that the repository.save method was called.
I thought that updatemodel would save the object to the database..why then call the .save method afterwards? Or have i missed something?
Any help with this would be appreciated.
Cheers
As I understand it, the UpdateModel method will blow away all data in the object. This is because MVC is round-trip based. Anything that goes out should come back if you need to keep state. See this question for more details.
A better way to handle this scenario in my opinion is to have an input model class as an Action parameter which is passed to a service call to update the domain entity in the DB. (Or this mapping code could be right in the action method if you really want.)
Also please be aware of the security vulnerabilities that could be introduced by binding directly to your DB model.
I want to create a base object that has only methods. The object would be QUEUABLE_OBJECT_TYPE and it will have an ENQUEUE method(s). The Payload of these messages (properties) would be added by subtyping this object.
I get an error that makes it sound like you cannot:
PLS-00589: no attributes found in object type "QUEUABLE_OBJECT_TYPE"
Does anyone know a way around this error? Or is it possible in the subtypes to hide this property of the supertype?
Either would be an acceptable answer.
Everything I've read suggests it is not possible to create a type without any attributes. Nor is it possible to hide a dummy attribute in a subtype. You may simply have to have an attribute in the master type, and utilise it - e.g. by making it identify the version of the type.
Oracle does provide some generic types, see documentation for details