Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebApi & Odata - suitable for file management?

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).

like image 586
TomTom Avatar asked Apr 12 '16 12:04

TomTom


Video Answer


1 Answers

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:

  • Create an OData Media Resource controller. It can be simpler than the one proposed in the document. See below.
  • Create a custom EntityRoutingConvention to route properly to the Get methods that will return the ZIP files (in case you have that use case, if you only need to POST them, you may not need the custom routing convention).

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.

like image 106
elbecita Avatar answered Sep 20 '22 13:09

elbecita