WebApi& Odata - 适合文件管理?

时间:2016-04-12 12:18:39

标签: c# asp.net-web-api odata

我正在将一个项目中的大部分/全部API移动到来自"纯粹"的Odata。 WCF并使用OWIN托管Odata enpoint。

目前我坚持的一个元素是文件。我有2个区域需要将ZIP文件上传到服务器进行处理。在一个附加到实体的情况下(称为"存储库")并包含未通过Odata公开的二进制内容(它刚刚上传)。另一方面,这是针对未绑定的操作,ZIP文件包含将包含/更改多个实体的配置文件。

OData是否可行,或者我应该忽略Odata并使用"手动配置"标准端点?由于暴露的元数据,我真的很想在Odata中保留它。

在发表评论之前 - 我一直试图通过谷歌找到文档,但我一直没有得到相关答案。我得到的答案表明这是可能的,但所有代码示例都指向旧的WCF级API,而我使用WebApi。 http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/create-an-odata-v4-endpoint上的文档没有涉及太多细节。它没有显示操作的参数配置的允许类型,以及如何将其配置为通过Web表单(以及客户端的http post)接受文件,因为我需要两者。

2 个答案:

答案 0 :(得分:3)

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.

答案 1 :(得分:-1)

对于具有简单二进制内容的文件,您可以使用WebApi而不是OData。除非您有想要提供给消费者的文件存储库。

如果您必须上传zip文件并手动处理它们以修改实体,您也不需要使用OData。但WebApi OData确实提供了批处理事务支持。您可以按照本教程:https://blogs.msdn.microsoft.com/webdev/2013/11/01/introducing-batch-support-in-web-api-and-web-api-odata/

如果你有大批量而不是发送zip文件,请使用gZip压缩。这是关于WebApi gZip支持的简洁帖子:https://damienbod.com/2014/07/16/web-api-using-gzip-compression/