Identifier in DTO when POSTing in Web API? - api

I have a Web API and I am using DTOs to abstract the underlying data model from the client. I have [at the moment] one DTO per controller. This DTO in all cases contains the database id of the data being passed about. On a GET, PUT, DELETE this makes sense (although DELETE and GET just use the id and not the DTO on the request obviously), but on the POST it doesn't make sense as the new data being added has no id yet.
In other words I am asking the client to pass to the API a structure that includes an Id field but I will ignore the content of that Id field. Is this acceptable or should I create an UpdateDTO and a RetrieveDto?

Keep the data structure you have. Make the Id field optional. If the value of Id is set when a POST comes in, return an error.

Related

How to create relationships in a RESTful API

I have 2 tables, User table and User_token table, they are one to one/none relatonship, not sure how to create this RESTful API.
i prefer to setup
# to get user attributes
GET /users/123
# to get user's token
GET /users/123/token
or should i create
# to get user attributes and token by JOIN the table
GET /users/123
the argument we have here, if we are doing the first setup, which i like it, it takes thousands of API requests compare to second one
that is depend you requirement.
for example if you need User Attributes and Token every time than
# to get user attributes and token by JOIN the table
GET /users/123
is better.
other wise another approach is good to get required data when needed.
REST has nothing to do with your database structure.
Your resources can contain properties or sub-resources. Every resource has at least one resource identifier (URL).
So in your case the GET /users/123 is a valid solution.

Include count of linked records in OData result

I've got a table "Events" with a linked table "Registrations", and I want to create an OData service that returns records from the Events table, plus the number of registrations for each event. The data will be consumed client-side in JavaScript, so I want to keep the size of the returned data down and not include all linked registration records completely.
For example:
ID Title Date Regs
1 Breakfast 01.01.01 12:00 4
2 Party 01.01.01 20:00 20
I'm building the service with ASP.NET MVC4. The tables are in an MSSQL database. I am really just getting started with OData and LINQ.
I tried using the WebAPI OData system first (using classes of EntitySetController) but was getting cryptic server errors as soon as I included the Registrations table in the entity set. ("The complex type 'Models.Registration' refers to the entity type 'Models.Event' through the property 'Event'.")
I had more success building a WCF OData system, and can request event information and information on related registrations.
However, I have no clue how to include the aggregate count information in the event result set. Do I need to create a custom entity set that will be the source for the OData service? I probably included too litte information here for finding a solution, but I don't really know where to look. Can somebody help me?
If you're willing to make an extra request per Event, you could query http://.../YourService.svc/Events(<key>)/Registrations/$count (or http://.../YourService.svc/Events(<key>)/$links/Registrations?$inlinecount=allpages if you're also using the links to the Registration entities).
Examples of both of these approaches on a public service:
http://services.odata.org/V3/OData/OData.svc/Suppliers(0)/Products/$count
http://services.odata.org/V3/OData/OData.svc/Suppliers(0)/$links/Products?$inlinecount=allpages&$format=json
I'm guessing that you'd prefer this information to come bundled together with the rest of the Events response though. It's not ideal, but you could issue a query along these lines:
http://services.odata.org/V3/OData/OData.svc/Suppliers?$format=json&$expand=Products&$select=Products/ID,*
I'm expanding Products (analogous to your Registrations) and selecting Products/ID in order to force the response to include an array that is the same size as the nested Products collection. I don't care about ID -- I just chose a piece of data that would be small. With this JSON response, your javascript client can get the length of the Products array and use that as the number of Products that are linked to the given Supplier.
(Note: to have your service support $select queries using WCF Data Services, you'll need to include this line when you initialize the service: config.DataServiceBehavior.AcceptProjectionRequests = true;)
Edit to add: The approach using $expand and $select won't be guaranteed to give you the correct count if your server does server-driving paging. In general, there isn't a simple single-response way to do what you're asking for in OData v3, but in OData v4, this will be possible with the new expand/select syntax.
i'm using oData v4 and i used this syntax :
var url = '.../odata/clients?$expand=Orders($count=true)';
// ...
a field called Orders#odata.count has been added to the response entity which contains the correct count.
and now to access the JSON property containing a dash you have to do it like this :
var ordersCount = response.value['Orders#odata.count'];
hope this helps.
Can you edit your Event model and add a RegistrationCount property? That'd be the simplest way I think
What I ended up doing was actually very simple; I created a View in SQL Server that returns the table including the registration counts. Never thought about using a view, since I've never used them before...
I used this to get the child count without returning the entities:
/Parents$expand=Children($count=true;$top=0)

How to design RESTful URL with many input parameters

I am working to create a Java based RESTful API that uses Spring MVC.
Now for some of the API endpoints-- multiple different parameters are required... I am not talking about a list of values-- more like parameter1, parameter2, parameter3, parameter4 and so on-- where all the 4 (or more) parameters are of different data types as well.
How do I design the API endpoint URL for the above scenario, eg for 4 separate input parameters? Is there any recommended way/best practice for doing this? Or do I simply concatenate the 4 values, with ach pair of values separated by a delimiter like "/"?
EDIT from user comment:
Example: I have to retrieve a custom object(a 'file') based on 4 input parameters--(Integer) userid, (Integer) fileid, (String) type, and (String) usertype. Should I simply create a REST Endpoint like "getfile/{userid}/{fileid}/{type}/{usertype}-- or is there a better (or recommended way) to construct such REST endpoints?
In REST start by thinking about the resource and coming up with immutable permalinks (doesn't change)to identify that resource.
So, in your example (in comment), you said you want to retrieve a file resource for a user and type (file type or user type?)
So, start with just enough information to identify the resource. If the id is unique, then this is enough to identify the resource regardless of the user who owns the file:
/files/{fileId}
That's also important as the url if a file could change owners - remember we want to identify the resource with just the components needed so it can be a permalink.
You could also list the files for a specific user:
/users/{userId}/files/
The response would contain a list of files and each of those items in the list would contain links to the files (/files/{fileId})
If for some reason the file id is not unique but is unique only in the context of a user (files don't change owners and id increments within a user - wierd) then you would need these components to identify the resource:
/users/{userId}/files/{fileId}
Also note the order based on the description. In that wierd case, we said the files are logically contained and IDed by the user and that's also the containment in the url structure.
Hope that helps.
A GET request to file/{usertype}/{user}/{type}/{fileid} sounds good

ddd: Entity or VO

Suppose I have a Passenger object that should contains Passport (government id) object. I am getting Passenger from PassengerRepository. PassengerRepository create request to server and obtain data (json) than parse received data and store inside repository.
I have confused because I want to store Passport as Entity and put it to PassportRepository but all information about password contains inside json than i received above.
I guess that I should use Passport as VO and put it inside Passenger (aggregate) object. Or I can create a PassengerService that will be include PassengerRepository and PassportRepository.
Any ideas?
Value objects are objects that are defined by their attributes - two instances with the same attribute values are essentially the same value. If this is correct for your Passport type, then it should be a VO.
If it is indeed a VO, then you are sorted - it can only be accessed via the aggregate.
If, however, this is not the case and a passport, in your domain, has an identity that remains constant regardless of attribute changes (someone changes their name, for instance), then you need to think whether, in your domain do Passport entities only have meaning when attached to a Person or not. If they do only have meaning in this context, then they also should only be accessed via the aggregate.
I would say that the Passport is a VO. A person can replace her passport which means a new passport (new serial) is issued. I think the Passport is an entity only for the government as it needs to keep track of each unique entity. For the rest of us, we don't care if the new passport has the same id as the old one. We care about having a valid passport.

Create Salesforce Case object with nested relationships using REST API

I am attempting to create a new Case object using the REST API but need to find out how to format the JSON body to pass in nested SObjects.
It's not apparent in the Docs, and I can't seem to find any examples. Anyone have any pointers or have done this before?
The SF web UI uses a text lookup field to set the (related) Contact and Account, and I need to figure out how to either bypass the need for a lookup or embed the SObjects of the related records in the JSON.
[{"message":"The value provided for foreign key reference Contact is not a nested SObject","errorCode":"INVALID_FIELD"}]
Figured it out by simply setting the AccountId and ContactId attributes on the new Case object.
I also haven't seen any documentation about this, but if you look at the object metadata returned by the REST API for any standard object, it seems that the suffix 'Id' is appended to any field of type "reference". For example, Case has OwnerId, LastModifiedById, CreatedById, etc. This suffix is not present in the field names displayed in the browser interface. The WSDL for the SOAP API includes both the ID as a simple element of type "ID", as well as a complex child element for nesting the actual record.