I am moving most / all of my API in a project over to Odata from "pure" WCF and using an OWIN hosted Odata enpoint for this.
The one element I am stuck with at the moment are files. I have 2 areas where I need to upload a ZIP file to the server for processing. In one case that is attached to an Entity (called a "Repository") and contains binary content that is not exposed via Odata (it is just uploaded). In the other hand this is for an unbound action and the ZIP file contains configuration files which will crate/change a number of entities.
Is that feasible with OData, or should I ignore Odata for this and go with "Manually configured" standard endpoints? I really would love to keep this in Odata due to the exposed metadata.
Before anyone comments - I have been trying to find documentation via google, but I keep getting no relevant answers. The answers I do get indicate this is possible, but all have code examples that point to the old WCF level API, while I use WebApi. The documentation at http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/create-an-odata-v4-endpoint does not go into too many details. It does not show the allowed types for a Parameter configuration for an action and how to configure it to accept the file via http post from a web form (and a client because I will need both).
Here is a useful link with documentation about Media Resource Support for OData in Web API: https://blogs.msdn.microsoft.com/mrtechnocal/2013/10/31/media-resource-support-for-odata-in-web-api/
You can simplify a little bit the implementation proposed in the link, but for sure, you will need to:
So, for the controller, you can have:
public abstract class YourMediaResourceODataController<TEntity, TKey>
: ODataController where TEntity : class
{
}
And then the real controller:
public class YourController : YourMediaResourceODataController<YourZIPObjectEntity, string>
{
// This would be the post
public async Task<IHttpActionResult> Post()
{
var stream = await Request.Content.ReadAsStreamAsync();
// Manage the stream
}
// The get (if you want it, you will need to code the custom EntityRoutingConvention).
[HttpGet]
public HttpResponseMessage GetMediaResource(string key)
{
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
var theZIPFile = yourZIPFileService.GetZIPFileByKey(key);
StreamContent contentResult;
using(var ms = new MemoryStream(theZIPFile.theByteArray)
{
contentResult = new StreamContent(ms);
}
result.Content = contentResult;
return result;
}
}
You will need to have an entity YourZIPObjectEntity
with a Stream/byte[]/string property, depending on how you manage the binary file. (In the documentation example this is the Image
class). And for that entity you will need to specify that it has a stream in the ODataConfig (see the "Setting Up the Web API Configuration" section in the documentation).
I think that is pretty much all.
Then, you can, from code, POST your ZIP files as a StreamContent:
using(var requestContent = new MemoryStream(yourByteArray))
using(var request = new HttpRequestMessage(HttpMethod.POST, yourPOSTUri)
{
request.Content = new StreamContent(requestContent);
// Set headers and send the request...
}
I hope this is the solution you are looking for, or at least an approach to it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With