WebApi & Odata - suitable for file management?

2019-07-26 05:57发布

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

2条回答
祖国的老花朵
2楼-- · 2019-07-26 06:19

For files with simple binary content you could use WebApi rather than OData. Unless there's a repository of files that you want to serve to the consumer.

If you must upload zip files and processing them manually in order to modify entities you don't need to use OData either. However WebApi OData does provide batch transactions support. You could follow this tutorial: https://blogs.msdn.microsoft.com/webdev/2013/11/01/introducing-batch-support-in-web-api-and-web-api-odata/

Again if you have large batches rather than sending zip files use gZip compression. Here's a neat post about WebApi gZip support: https://damienbod.com/2014/07/16/web-api-using-gzip-compression/

查看更多
倾城 Initia
3楼-- · 2019-07-26 06:22

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.

查看更多
登录 后发表回答