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()
Related
I've just integrated RestKit with a Mac application for communicating with a web service. After much confusion, I have successfully got requests and responses working using it.
The problem I am now finding is that when I want to make a POST request.
I have created a RKRequestDescriptor with a mapping for a whole number of properties and all of the properties are being sent as parameters for the query. I want a way of dynamically changing the parameters that are sent, for example not sending some parameters where the property is nil.
Is this possible as part of the built-in functionality of RestKit? And if so, how?
You would need to use RestKit's Dynamic mapping class to handle mapping at run time.
Dynamic Object Mapping
RestKit supports such use cases via the RKDynamicMapping class.
RKDynamicMapping is a sibling class to RKObjectMapping and can be
added to RKRequestDescriptor and RKResponseDescriptor objects and used
to configure RKMappingOperation instances. RKDynamicMapping allows you
to hook into the mapping process and determine an appropriate concrete
RKObjectMapping to use on a per-object basis.
Or you could not use RestKit and set the POST body yourself. Create the required dictionary by adding only required parameters. Serialize this object with help of NSJSONSerialization and set this NSData object as HTTP Body in the request instance.
We are building a real-estate portal. We have Services, Mappers and Entites. At the stage we are allowing users to either
Create a property via a form.
Upload a batch file containing 1 or more properties.
So if he create a property via the form we can validate the form and if its a valid property, we can add it into our system. But if he upload via a batch file, we think that the responsibility of the form is
to validate that the user provided a file
the file type is valid
and the file size is within the allowed limits.
After this it should hand over the file to the controller or service.
Now the pending tasks are
Process the file and retrieve the contents
Validate the contents
If validated, save the properties or display an error.
So which part(s) are responsible for the above tasks?
I am thinking that the controller should do the initial file processing and pass the data to the service. This means that we will create/fetch the form object in the controller and validate the form within the controller.
Now the next section is to validate the contents, which is actually a collection of entities. So we have following ideas for this stage
Service will validate the data and create the entities, it will save them.
Or service will create the entity with the provided data and then call the validation function of the entity.
Or the service will try to create an entity with the provided data (send the data to the entity constructor), and if the data is valid, the entity will be created or will generate an error etc.
The possible issues I can think about above approaches are
If the service is validating the data, it means the service will know the inner structure of the entity, so if down the road we need to update the entity structure, we have to update the service as well. Which will introduce some sort of dependency.
In the 2nd approach, I don't think that an entity should be created at first place if it isn't valid.
In the 3rd approach, we are creating a functionality within entity's constructor, so making the entity dependent on the data. So when we need to fetch the entity from persistent, we need to provide some stub data.
Or am I over-thinking??
Now the next section is to validate the contents, which is actually a collection of entities.
The Contents, that Controller sends to Service, is a graph of objects / a structure / a plain string in the simplest case, but never a collection of business entities.
If the service is validating the data, it means the service will know the inner structure of the entity
What exactly is Service validating?
Service is validating the data means that Service ensures invariant of every structure / object that it receives.
For example, if F(T) is service method and T is structure with properties { A, B, C } that represents a triangle with three edges, then Service has to ensure the invariants (the length of each site is greater then zero and the sum of the lengths of any two sides must be greater than the length of the third side) of this structure after this structure has been deserialized.
This validation has to be done because deserializer doesn't use constructors to ensure invariants during deserialization.
When these validations are done, all objects passed to Service are valid and can be freely used in business layer directly or converted to objects (for example, entities) known to business layer.
if down the road we need to update the entity structure, we have to update the service as well. Which will introduce some sort of dependency.
This dependency is inavoidable. Since Transfer Objects and Entity Objects are separated, there always exists mapper that knows how to convert them.
Service will validate the data and create the entities, it will save them.
I'd go with this. Service validates data, converts into business layer objects, invokes business layer functions, persists changes.
It depends on what kind of constraints you're validating.
1.parameter validation like notEmpty property name or max length etc.
In this case you could extract the validation logic to a Validator object. This is useful when you have multiple property creating form(web form, file uploading), the validator may be invoked by multiple "client", but the validation logic keeps in one object.
2.business rule validation.
I prefer using domain models, you may have a look at the PhoneNumber example in this presentation
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?
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.
I want to save the state of application on deactivation because some how my application crashes when i activate the application after deactivating the application,the value for some object is not saved during tombstoned process during deactivation. So i come up with the solution to serialize the objects on deactivation and deserialize them on activation. I followed the article http://onishimura.com/2010/07/25/windows-phone-7-tutorial-creating-a-simple-notes-app-with-silverlight-part-1/.
On serializing file, it gives an exception InvalidDataContractException showing the message:
"Type 'System.Windows.UIElement' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute."
The class object which i want to save is also have some objects of PhoneApplicationPage and Usercontrols. So how can i fix this?
You can't serialize any arbitrary C# object type, and especially not any Silverlight UI objects - that's by design. You should really only serialize the actual data you rely on in building up the UI, and then retrieve this data as needed when your page is created or navigated to (*).
The linked example doesn't contain any UIElements in its DataContract, just strings which are serializable.
(*) Part 2 of that tutorial actually deals with loading the data in this way.