Based on the information here http://docs.valence.desire2learn.com/res/course.html#actions I would expect that to 'update' a courseOffering I would specify a PUT with a CourseOfferingInfo block, which only contains a few attributes. Every time I try this, I get a 404, not found - even using the same route for a successful GET (404 says org doesn't exist OR org is not an offering - neither is true). However, if I specify a CreateCourseOffering block (directly from a previous GET), the PUT works fine. Is this correct and the documentation not? Or are there other things I should look for in this scenario? The documentation says use CreateCourseOffering for the POST to create an offering… I simply want to update one attribute of that offering and as such thought the PUT was the way to go.
If you use the "create" POST route with a CreateCourseOffering block, this will create a new course offering, and send back the CourseOffering block for the newly created course offering (this will include the org unit ID value for the new org unit you've built).
If you want to update an existing course offering, you should, as you suspected, use the "update" PUT route with a CourseOfferingInfo block. Note that you must provide valid information for all the fields in this block, since when used successfully, the LMS will use all the properties you specify in that block for new values for the org unit. The StartDate and EndDate fields are particularly finicky: you must provide either a valid UTCDateTime value (notice that the three-digit millisecond specifier in these values is mandatory) or a JSON null value if the field is not applicable.
Why a 404? What you're seeing with the 404s and the data you're passing is likely down to the way the back-end service is doing data binding. It tries to de-serialize your provided JSON data (and query parameters) into data objects it can read/manipulate -- if you provide a JSON block that contains a superset of the properties it's expecting, then this may work (for example, if you provide a CourseOffering block when you're expected to provide a CourseOfferingInfo) as the binding layer may ignore fields it doesn't need. If the binding process fails, because you provide a value for a property that can't be bound to the data type expected, or because you fail to provide a JSON property field it expects, then this can cause the service to return a 404 (because binding/de-serializing incoming parameterized data happens at the same time as matching the URL route to an underlying service handler).
If you provide a JSON structure (and query parameters) that the web-service can bind to its expected data objects, but the values you provide are invalid or nonsensical, then this can cause the underlying service handler to respond with a 400 (signalling an Invalid Request). But in order to get this far, your parameterized data still needs to get properly deserialized and bound into data objects for the underlying service to examine.
We'll be updating the documentation to more explicitly draw out this fact. The safest policy from the calling client perspective is to pass valid JSON structures that are exactly what's expected by the individual routes, especially since the underlying back-end service implementation might change how it handles incoming requests.
Related
We have DTO POCO types that represent the JSON request message structure/schema for our REST APIs.
I noticed just now that content/properties in request JSON that doesn't have a corresponding property on a DTO are being silently ignored. Is there a way to make a request report these as a binding failure?
The reasoning being that I think it's a bad pattern to silently ignore data in a request, because it might be that the caller, e.g. has a type in a property name, and in that scenario the data they thought was being saved is not, and they may not discover this problem until much later when the retrieve the resource.
I'm having trouble getting my head around how to use Falcor for a particular use case.
Basically I need to take a few fields from a page and execute server side validation business logic. The page should just display whether the validation was successful or not and if not, the reason.
I could technically use a falcor get query, but they don't seem suited to multi-parameter calls
I could try and use a Falcor 'call', which would allow me to easily pass through multiple parameters, but is not suited to returning transient data.
Is this just a use case that Falcor should not really be used for or am I missing something?
All the data returned by a Falcor server is part of the model, transient or not.
A get is appropriate here because you want to read data. call are appropriate to make black box modifications to the model.
gets are always multi-parameters because you give the entire path of the data which can enclose whatever you want. Let's say we want to validate a URL. We could do something like:
getValue('updateProfileForm.website["http://example.com"].valid')
And that would return true of false depending on the URL. The result can be kept in cache eternally since it will never change (a URL is either always valid or it is not).
If the validation process needs to know the value of multiple fields at once, like password confirmation, you can do something like this:
getValue('updateProfileForm.password["new password"].confirm["new password"].valid')
If the validation depends on something external to the form, like what time it is, include this parameter in the path to maximize cache-ability.
Is it possible to map the different objects to the same url and use different post params to differentiate between the return types?
My API isn't really rest. Everything flows through the same URL but has a parameter "Type" that differentiates the result that should be returned.
'Probably' - it would be nice it you added a few examples to the question (requests and associated responses).
Sending the requests is fine, though you will need to explicitly specify the path / route name to use.
For the response, you will most likely need to use an RKDynamicMapping which will inspect the incoming data and return the appropriate mapping to use.
If you can't tell the 'type' from the response data (instead, you can only tell because of the URL that was requested) then you may need to try mapping into all types and rejecting invalid content using KVC validation, or you might want to change your data model (not enough information in the question to determine which...).
I'm getting up to speed with the WCF Web API. I want to expose an endpoint that can accept notes, via the POST method. My issue is, I want to support multiple representations for notes. For example, I might want to accept a note using a custom XML serialization that we're using elsewhere, or as an atom:entry element. I already have formatters that can deserialize these into a Note class (our own custom class) or as a SyndicationItem.
The question comes though, how do I define the method? I've currently got this:
[WebInvoke(UriTemplate = GetNotesUriRoot,Method="POST")]
public HttpResponseMessage PostNote(ObjectContent item,HttpRequestMessage request)
Which fails when starting up:
The service operation 'PostNote' will never receive a value for the input parameter 'item' of type 'ObjectContent'. Ensure that a request HttpOperationHandler has an output parameter with a type assignable to 'ObjectContent'.
I initially tried having two separate methods (with appropriately typed parameters), but they can't share the same endpoint name. The current effort (using ObjectContent) was based on other posts I could find that suggested that it could be a parameter. There is no common base type or interface between Note and SyndicationItem
We're using v0.6.0 of the WCF Web API
You need to have a parameter / return type of type Note and your formatters will (de-)serialize it to / from the required representation.
[WebInvoke(UriTemplate = GetNotesUriRoot,Method="POST")]
public HttpResponseMessage PostNote(Note note)
then in your request the content-type header will determine how the object is deserialised. You don't need to worry about deciding how to deserialise, the decision is made for you, as long as the relevant formatter exists (I've not delved in to formatters yet as json/xml have been enough for me so far)
I'm using Openrasta for my RESTful webservice and I've a small doubt with regards to the method parameters and URI
For example: I've following Setup for user entity.
Configuration:
ResourceSpace.Has.ResourcesOfType<User>()
.AtUri("/user")
.And.AtUri("/user/{userId}")
.HandledBy<UserHandler>()
.AsJsonDataContract()
.And.AsXmlDataContract();
Handler method for PUT:
public OperationResult Put(long userId, User user){}
URI for the same will be http://localhost/User/1
Request body will contain a JSON as below:
{
"userId":1,
"userName":"FirstName"
}
Here, my question is: Defining the PUT method with two parameters is correct or not? If it is right way to do that, then userId parameter in the PUT method will contain same value as User entity property UserId.
And, in the PUT method I need to verify whether these two values are same or not and if they are not same I return BadRequest stating that URI doesn't match with the entity provided in request. Why should we do this explicitly why not it can be handled while processing the request and have PUT method take only User entity as parameter? Am I missing anything drastically or is my understanding about this design completely wrong? Any thoughts or opinions please?
There's a few reasons for it.
First, it's a technical limitation of how URI parameters are processed and matched to inputs one variable at a time. The same gets applied to key/values codecs, so that ought to let you have one User object. but when you use a json codec, we get back a full object, so that would end up overriding User alltogether.
The second one is that I never tried to fix that problem, mostly because combining uri parameters and response bodies leads to a whole bunch of hidden security issues you probably want to stay well clear of.
Last and not least, from a modeling perspective a ReST API ought to use URIs as identifiers and links instead of foreign keys, so if you already have your identifier (the URI), there's little reason why that should be modeled in your entity body.