I have a client who has a web service providing several different top-level entities. Let's say there are three which are of particular interest: Organisations, Sectors and Activities.
The client wants to be able to search for a term across all three of these entities simultaneously without have to make three separate calls. For example, "return all records whose name contains bread".
While the expand keyword would seem to be the solution at first glance, this only provides a view into the parent entity.
My suspicion is that this cannot be done by virtue of the way in which OData is designed to work, but I need to have a conclusive answer before going back to the client.
Unless the server provides a service operation for this exact purpose (and that would be pretty tricky to design anyway, what type should it return?), then it's not possible in one query.
On the other hand the client can send three queries inside one batch request. So that it's just a single roundtrip to the server. Might be good enough.
You could add a webget to the service to perform this function. You would have to wrap the response objects though.
Related
I have a resource, as an example a 'book'.
I want to create a REST POST endpoint to allow consumers to create a new book.
However, some of the properties are required and computed by API, and others were actually taken as they are
Book
{
name,
color,
author # computed
}
Let's say the author is somehow calculated in API based on the book name.
I can think of these solutions each has its drawbacks:
enforce consumer to provide the author and just filter it (do not take into account as an input) # bad because it is very unpredictable why the author was changed
allow the user to provide author # same problem
do not allow the user to provide an author and show an exception if the user provides it
The last solution seems to be the most obvious one. The main problem I can see is that it is inconsistent and can be bizarre for consumers to see the author later on GET request.
I want my POST endpoint to be as expressive as possible. So the POST and GET data transfer objects will look almost the same.
Are there any simple, expressive, and predictable patterns to consider?
Personally I'm a big fan of using the same format for a GET request as well as a PUT.
This makes it possible for a client to do a GET request, add a property to the object they received and immediately PUT again. If your API and clients follow this pattern, it also means it can easily add new properties to GET requests and not break clients.
However, while this is a nice pattern I don't really think that same expectation exists at much for 'creation'. There's usually many things that make less less to require as a property when creating new items (think 'id' for example), so I usually:
Define a schema for PUT and GET.
Define a separate schema for POST that only contains the relevant properties for creation.
If users supply properties not in the schema, always error with a 422.
some of the properties are required and computed by API
Computed properties are neither required nor optional, by definition. No reason to ask consumers to pass such properties.
do not allow the user to provide an author and show an exception if the user provides it
Indeed, DTO should not contain author-property. Consumers can send over network whatever they want, however it is the responsibility of the API-provider to publish contract (DTO) for consumers to use properly. API-provider controls over what properties to consider, and no exception should be thrown, as the number of "bad" properties that can be sent by consumers is endless.
So the POST and GET data transfer objects will look almost the same
Making DTOs of the same resource look the same is not a goal. In many cases, get-operation exposes a lot more properties than post-operation for the same resource, especially when designing domain-driven APIs.
Are there any simple, expressive, and predictable patterns to consider?
If you want your API to express the fact that author is computed, you can have the following endpoints:
POST http://.../author-computed-books
GET http://.../books/1
Personally, I wouldn't implement that way since it does not look natural, however you can get the idea.
I want my POST endpoint to be as expressive as possible. So the POST
and GET data transfer objects will look almost the same.
Maybe just document it instead of relying explicit stuff like it must be almost the same as the GET endpoint.
E.g. my POST endpoint is POST /number "1011" and my GET endpoint is GET /number -> 11. If I don't document that I expect binary and I serve decimal, then nobody will know and they would guess for example decimal for both. Beyond documentation another way of doing this and to be more explicit is changing the response for GET to include the base {"base":10, value:"11"} or changing the GET endpoint GET /number/decimal -> 11.
As of the computed author I don't understand how you would compute it. I mean either a book is registered and the consumer shouldn't register it again or you don't know much about the author of it. If the latter, then you can guess e.g. based on google results for the title, but it will be a guess, not necessarily true. The same with consumer data, but at least that is what the consumers provided. There is no certainty. So for me it would be a complex property not just a primitive one if the source of the information matters. Something like "author": {name: "John Wayne", "source": "consumer/service"} normally it is complex too, because authors tend to have ids, names, other books, etc.
Another thought that if it is weird for the consumers instead of expected, then I have no idea why it is a feature at all. If author guessing is a service, then a possible solution is making the property mandatory and adding a guessing service GET /author?by-book-name={book-name}, so they can use the service if they want to. Or the same with a completely optional property. This way you give back the control to the consumers on whether they want to use this service or not.
I've been looking into some Node ORMs for use with PostgreSQL lately, and would like to expose some type of flexible filtering on the front end.
I'm quite enjoying the flexibility provided by Sequelize's where/include filtering (e.g. filtering a model based on some relation N levels deep).
Is the filtering mechanism safe at all to expose to any front end API? I haven't had much experience with it, so I"m not sure what types of fields can be passed through to the filter query.
Otherwise, for more complex querying I may go with something like Knex instead.
Generally if you need to ask if it is safe to expose where/include parameter passing directly to your frontend, I would suggest you shouldn't do it. If you don't know how it will behave you'll end up fast leaking all your users and password hashes to the world.
So you'll be better covered by validating incoming filtering parameters and only after that pass them to the query. You can use for example json schema to validate the incoming parameters.
For example in objection.js ORM this thing is handled in a way that you can give the query inside your code certain pattern what data user can include to response, and then incoming user input is automatically reduced to that subset (this works only when one requests additional relations to the requested row).
var houseWithPossiblePetsAndOwner = await House.query()
.allowEager('[pets, owner]')
.eager(eagerParamDirectlyFromEndUser)
.where('id', id);
You could extend your preferred ORM to support that kind of extra method, which allows you to declare for the query which parameters can be passed to it from the user input.
I am creating a brand new application, including the database, and I'm going to use Entity Framework Code First. This will also use WCF for services which also opens it up for multiple UI's for different devices, as well as making the services API usable from other unknown apps.
I have seen this batted around in several posts here on SO but I don't see direct questions or answers pertaining to Code First, although there are a few mentioning POCOs. I am going to ask the question again so here it goes - do I really need DTOs with Entity Framework Code First or can I use the model as a set of common entities for all boundaries? I am really trying to follow the YAGNI train of thought so while I have a clean sheet of paper I figured that I would get this out of the way first.
Thanks,
Paul Speranza
There is no definite answer to this problem and it is also the reason why you didn't find any.
Are you going to build services providing CRUD operations? It generally means that your services will be able to return, insert, update and delete entities as they are = you will always expose whole entity or single exactly defined serializable part of the entity to all clients. But once you do this it probably worth to check WCF Data Services.
Are you going to expose business facade working with entities? The facade will provide real business methods instead of just CRUD operations. These buisness methods will get some data object and decompose it to multiple entities in wrapped business logic. Here it makes sense to use specific DTO for every operation. DTO will transfer only data needed for the operation and return only date allowed to the client.
Very simple example. Suppose that your entities keep information like LastModifiedBy. This is probably information you want to pass back to the client. In the first scenario you have single serializable set so you will pass it back to the client and client pass it modified back to the service. Now you must verify that client didn't change the field because he probably didn't have permissions to do that. You must do it with every single field which client didn't have permission to change. In the second scenario your DTO with updated data will simply not include this property (= specialized DTO for your operation) so client will not be able to send you a new value at all.
It can be somehow related to the way how you want to work with data and where your real logic will be applied. Will it be on the service or on the client? How will you ensure that client will not post invalid data? Do you want to restrict passing invalid data by logic or by specific transferred objects?
I strongly recommend a dedicated view model.
Doing this means:
You can design the UI (and iterate on it) without having to wait to design the data model first.
There is less friction when you want to change the UI.
You can avoid security problems with auto-mapping/model binding "accidentally" updating fields which shouldn't be editable by the user -- just don't put them in the view model.
However, with a WCF Data Service, it's hard to ignore the advantage of being able to write the service in essentially one line when you expose entities directly. So that might make the most sense for the WCF/server side.
But when it comes to UI, you're "gonna need it."
do I really need DTOs with Entity Framework Code First or can I use the model as a set of common entities for all boundaries?
Yes, the same set of POCOs / entities can be used for all boundaries.
But a set of mappers / converters / configurators will be needed to adapt entities to some generic structures of each layer.
For example, when entities are configured with DataContract and DataMember attributes, WCF is able to transfer domain objects' state without creating any special classes.
Similarly, when entities are mapped using Entity Framework fluent mapping api, EF is able to persist domain objects' state in database without creating any special classes.
The same way, entities can be configured to be used in any layer by means of the layer infrastructure without creating any special classes.
I’m having a little bit of difficulty understanding some architectural principles when developing a service. If you make a call to a WCF service and it returns a collection of items(Orders) (which are custom made classes made up From LINQ-to-SQL entity data) to a client and each item has a collection of items(OrderItems) (one-to-many) that are also made up from the same LINQ-to-SQL context. If I make another call to the service and request a particular OrderItem and modify its details on the client side, how then does the first collection of Items realise that one of its Orders OrderItem has changed from the client side. I am taking the approach of when changing the OrderItem I send the OrderItem object to the WCF service for storage via LINQ-to-SQL commands but to update the collection that the client first called I use IList interface to search and replace each instance of the OrderItem. Also subscribing each item to the PropertyChanged event give some control. This does work with certain obvious limitations but how would one 'more correctly' approach this by perhaps managing all of the data changing from the service itself.. ORM? static classes? If this is too difficult question to answer, perhaps some link or even chat group that I can discuss this as I understand that this site is geared for quick Q/A type topics rather than guided tutorial discussions.
Thanks all the same.
Chris Leach
If you have multiple clients changing the same data at the same time, at the end of the day you system must implement some sort of Concurrency Control. Broadly thats going to fall into one of two categories: pessimistic or optimistic.
In your case it sounds like you are venturing down the optimistic route, whereby anyone can access the resource via the service - it does not get locked or accessed exclusively. What that means is ultimately you need to detect and resolve conflicts that will arise when one client changes the data before another.
The second architectural requirement you seem to be describing is some way to synchronize changes between clients. This is a very difficult problem. One way is to build some sort of publish/subscribe system whereby, after a client retrieves some resources from the service, it also subscribes to get updates to changes to resource. You can do this either in a push or pull based fashion (pull is probably simpler, i.e. just poll for changes).
Fundamentally you are trying to solve a reasonably complex problem, but its also one which pops up quite frequently in software.
First of all, I'll clarify some words: when I use the word "user" you have to understand "application user" and the "patient" is an "item" from the model layer.
Let's now explain the context:
A client application has a button "get patient" and "update", a text box "patient name" and a grid to display the patient returned after the click on the "Get patient" button.
At server side I've got a WCF method GetPatient(string name) that searches the reclaimed patient and does some business logic to a PatientEntity used with nHibernate. That method returns a PatientDto (a mapping from PatientEntity). And I've got an Update(PatientDto patient) method to update the modified patient.
The user can modify the returned PatientDto and click on the "Update" button.
So far I have two ideas to manage a "session" through this senario:
First idea: I expose an "ID" property in my DTO so when the user clicks on update, I search, at server side, the "patient" with the specified ID using nHibernate's "GetByID()", I update the result with the data from PatientDto and call the nHibernate's "Update()" method.
Second idea: I create manually at server side a CustomSession (I use this name for clarity) class that encapsulates an ISession and exposes a session's unique id that will travel between the client and the server. So, when the client sends to the server the PatientDto and the unique session id, I can get the CutsomSession and update the patient with the Update() methods of the ISession
I don't like these ideas. Because the first is a lot of overhead and it doesn't use the features of nHibernate. And the second idea demands to the developer to manage himself the id of the CustomSession between the calls: It is error prone.
Furthermore, I'm sure nHibernate provides such a mechanism although I googled and found nothing about this.
Then my questions are:
What mechanism (pattern) should I use? Of course, the mechanism should support an entity's object graph and not a single entity!"
Does nHibenrate provides such a mechanism?*
Thank you in advance for your help,
I don't think this is a Hibernate issue and in my opinion is a common misunderstanding. Hibernate is a OR-Mapper and therefor handles your database objects and provides basic transactional support. Thats almost it.
The solution for Sessionmanagement in Client-Server environments is for example the use e.g. Spring.net which does provide solutions (Search for OpenSessionInView) for your problem and integrates quite well with NHibernate.
The stateless approach you mentioned offers many advantages compared to a session-based solution. For example think about concurrency. If your comitt is stateless you can simply react on a failed Save() operation on the client side for example by reloading the view.
Besides your 2 good arguments for the use of Hibernae is, if done right, security aggainst SQL-Injection.
One reason that I usually don't bother with ORM tools/frameworks in client-server programming is that you land at, usually, your first solution with them. It helps in making the server side more stateless (and thus more scalable) at the expense of some reasonably cheap database calls (a fetch-by-PK is usually very cheap, and if you immediate write it anyway, guess what the database is likely to do first on a write? Grab the old record - so SELECT/UPDATE may be only marginally slower than just UPDATE because it seeds the cache).
Yes, you're doing stuff manually that you want to push out to the ORM - such is life. And don't fret over performance until you've measured it - for this particular case, I wonder if you really can measure it.
Here's a sumary of what has been said:
A nHibernate session lasts the time of the service call. That's, the time of the call of "GetPatient(string name)" no more.
The server works with entities and returns DTO's to the client.
The client displays and update DTO's. And calls the service "Update(PatientDto patient)"
When the client triggers the service "Update(PatientDto patient)", the mapper gets the patient entities thanks to the ID contained in the DTO with a "GetById(int id)" and updates the properties which has to be.
And finally, the server calls the nHibernate's "Update()" to persists all the changes.