Versioning of media types in OpenRasta - api

What is the proper way to version media types in openrasta? Up to this point on one of our rest api's we specified custom media types with the version number in them:
application/vnd.company.Entity-v1+xml
Currently all of these media types are just being passed to a custom codec that we defined to remove some of the default tags and ns tags that XmlSerializer puts in on serialization. At the top of that codec we have:
[MediaType("application/vnd.company.Entity-v1+xml")]
Now we're to the point where we have clients that want custom attributes and elements in the xml and have thus created a new entity that handles those attributes and elements that derive from Entity. We now have the task of moving specific clients up to the new entity (EntityV2), however I'm not sure how to handle this in the context of OpenRasta when it comes to getting this new entity type into the handlers. Here's what we've thought about thus far:
Add another POST method to our handler to handle the derived type
Create a completely new url to handle the new entity
Create a new media type and then route the requests somehow to a new handler. This would be the most effort as we are trying to reuse the same handler with a small amount of decision logic to determine what needs to be done with the new elements/attributes.
Any advice would be greatly appreciated!

I'm an OpenRasta noob, but I think the best approach might be to use the same handler for both versions of the requests, and just introduce a new codec for the new versions of the entity.
I believe if you create a new codec and decorate it with [MediaType("application/vnd.company.Entity-v2+xml")] it should use that codec to deserialize the request instead of the v1 codec. The OR content negotiation should take care of using the proper codec, so your handler wouldn't change.
This depends on whether your clients can be expected to use the "Accept" HTTP header to indicate which version of the entity they are using. If that's not the case, you can still create a new URL and just configure it with your existing handler and the new codec.
Make sense?

Related

NullValueHandling must be an optional parameter for the JsonFormatter attribute

Hope developers team wouldn't miss my message. NullValueHandling must be an optional parameter for the JsonFormatter attribute because there are a lot of cases when properties of the object required on client side independently of their value.
And I personally got some troubles trying to identify why my object doesn't have half of it properties.
By the way limitation for DbConext and entity namespace to make the entity observerable on client side is not good too.
Thanks.
Breeze currently sets NullValueHandling to 'Ignore', so as to minimize payloads by not sending any 'null' values. We did not think that this would be an issue because the json serialized objects are materialized into 'breeze' entities on the client and breeze has metadata to determine what the valid properties for each entity are.
What is the use case for actually sending 'nulls' to the client? This is an relatively easy enhancement to make if we have a good use case. The only one that comes to mind is with anonymous objects queried from the server for which metadata will not exist. Is this what you are encountering?

Better Approach for Creating Temp Object for Core Data with Restkit

In my app, I have this scenario where I need to post an object to remoter server and get an object key back and then store the object locally. I have Core data and Restkit implemented in my app.
The object value are collected from user input. I couldn't figure out a great way to prepare the object before posting it to remote server. This object is an entity of type NSManagedObject, and I don't want to store it before I get the object id from server.
I came across this which suggested to use a transient object to handle this situation. But as discussed in that thread, this causes issue with code maintenance.
Is there a better way to handle this scenario? Thanks.
Make your core data model class adhere to the RKRequestSerializable protocol.
Then when the user input is validated, create an entity as normal and set it as the params value to the RKRequest, this will send your object as the HTTP body. Look inside RKParams.m for an example.
Also set the newly created entity as the targetObject for the RKObjectLoader. That way, when your web service returns the information (like the new unique ID), it will target the new object and save the new unique ID to this object without creating a duplicate.
Clear as mud?
PS: Oh and be careful mixing autogenerated core data classes with custom code! I recommend mogen to help you not lose code each time you make a change.

How can I cleanly write abstractions for interacting with RESTful resources?

I have a simple REST client that works well. In my application code I do something like this:
restClient = new RestClient(configurationData)
restClient.get('/person/1') //Get Person
restClient.get('/equipment/auto/3') //Get an Auto
restClient.get('/house/7') //Get a House
That works well but things are getting more complicated and I would like to divorce the application code from the specific resource locations.
I'd like to be able to write a wrapper around the service, which will store the resource locations and not require me to put them in my application code. I would expect my code to start looking more like this:
restClient = new RestClient(configurationData)
restClient.getPerson(1) //Get Person
restClient.getAuto(3) //Get an Auto
restClient.getHouse(7) //Get a House
I started adding these wrappers inside of my RestClient class but it got very bloated very fast, and it felt that the abstraction should be at a higher level. Mixing Resource-specifics with my client also felt wrong.
So, instead I subclassed RestClient, and each resource has its own class. The problem is that now I have to instantiate a new client for every different resource type:
personRestClient = new PersonRestClient(configurationData)
personRestClient.get(1);
autoRestClient = new AutoRestClient(configurationData)
autoRestClient.get(3);
housesRestClient = new HousesRestClient(configurationData)
housesRestClient.get(7);
But now I've created a new Client class for each Resource and I am fairly certain that is a very bad thing to do. It's also a pain because I have to tie my connection configuration data to each one, when this should only happen once.
Is there a good example or pattern I should be following when I want to write abstractions for my Resources? My base RestClient works fine but I dislike having to put the server-side API locations in my application code. But I also don't want to have to instantiate one specialized client class for each Resource I want to interact with.
I am in a similar situation, and have what I consider to be a good implementation with the appropriate abstractions. Whether my solution is the best practice or not, I cannot guarantee it, but it is fairly lightweight. Here is how I have it architected:
My UI layer needs to make calls into my REST service, so I created an abstraction called ServiceManagers.Interfaces.IAccountManager. The interface has methods called GetAccounts(Int64 userId).
Then I created a Rest.AccountManager that implemented this Interface, and injected that into my AccountController. The Rest.AccountManager is what wraps the REST specifics (URL, get/post/put..., parameters, etc).
So, now my UI code only has to call accountManager.GetAccounts(userId). You can create an all-encompassing interface so that you only have a Get, but I feel that is less expressive. It is ok to have many different interfaces for each component(ie: PersonManager, HouseManager, AutoManager), because each are a separate concern returning different data. Do not be afraid of having a lot of interfaces and classes, as long as your names are expressive.
In my example, my UI has a different manager for each controller, and the calls made fit each controller appropriately (ie. GetAccounts for AccountController, GetPeople for PeopleController).
Also, as to the root configuration data, you can just use a configurationCreationFactory class or something. That way all implementations have the appropriate configuration with the core logic in one location.
This can be a hard thing to explain, and I know I did not do a perfect job, but hopefully this helps a little. I will try to go back through and clean it up later, especially if you do not get my point :)
I am thinking something like this, again some way of mapping your end points to the client. You can have the mapping as an xml or a properties file which can be loaded and cached during the app start. The file should have key value pairs
PERSON_ENDPOINT=/person/
AUTO_ENDPOINT=/equipment/auto/...
The client should pass this key to the factory may be ClientFactory which has this xml cache and retrieves the end point from the cached file. The parameters can be passed to the factory as custom object or a map. The factory gives back the complete end point say "/person/1" which you can pass to your client. This way you dont need to have different classes for the client. If you dont like the xml or a file you can have it as a static map with key value pairs. If its an xml or file you dont need a code change every time that is the advantage.
Hope this helps you.

Can WCF Data Service be used to return a File?

I Want to use WCF Data Service to return mp3 files, along with other data types already served by WCF.
Is this possible?
[12/29] I do have the mp3 binary data in sql (~10 seconds each). I'd like to use html audio tag with it:
<audio src="/server/svc/id" type="audio/mpeg" />
Javascript will change the id. Not sure how this will work with WCF returning binary array...
[12/30] It works.... after setting mimetype in CSDL.
Sure, you can do this in three possible ways:
Include it as a binary property on an existing entity (usually the service hosts entities representing each audio file in this case, which would have one of its properties being the actual audio mp3). In code this is just to declare a property of type byte[] (And fill it in). The upside is that this is really easy to setup. The downside is that when you GET such entity the entire mp3 gets downloaded and it's transferred as BASE64 encoded text, so it's big on the wire.
Similar setup as above, but instead of storing the mp3 in a binary property you make the entity a Media Resource Entry, you make it have a default stream value. This is described in this blog post in more detail: http://blogs.msdn.com/b/astoriateam/archive/2010/08/04/data-services-streaming-provider-series-implementing-a-streaming-provider-part-1.aspx and http://blogs.msdn.com/b/astoriateam/archive/2010/09/08/data-services-streaming-provider-series-part-2-accessing-a-media-resource-stream-from-the-client.aspx.
In the latest CTP WCF DS also supports stream properties. Which is similar to #2 above but a single entity can have multiple streams each accessible by its name.
To access the raw value of the audio stream you can use URL (depends on the method you use to expose the stream):
urltotheentity/MyBinaryProperty/$value
urltotheentity/$value
urltotheentity/StreamPropertyName/$value
Note that in #1 the default MIME type of the stream will be application/octet-stream, to change it you need to add an attribute MimeType for the property (reflection provider) or attribute into the CSDL for that property (EF provider).
In #2 and #3 the mime type is determined via a call to the stream provider.

Reading BLOBS: Media Link Entry in OData

For reading BLOBS in a OData Service, I am using the DataServiceContext.GetReadStream()
The GetReadStream method synchronously requests a data stream that contains the binary property of the requested entity.
In the AtomPub protocol, the entity is a Media Link Entry and the binary property is the associated Media Resource.
In the code I am using the proxy generated using Datasvcutil.exe. The proxy generates many classes for the entities. Is there any property to detect whether the given entity has binary stream or not.
Currently I call dataSvcContext.GetReadStream(customer) and getting ArgumentException for an entity that does not have Media Link property or binary property.
Is there any method available to detect whether entity has binary property or not?
Maybe you can check whether your entity contains the following attribute:
System.Data.Services.Common.HasStreamAttribute()