Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC or Web API transfer byte[] the most efficient approach

After achieving successful implementation of ajax POST, uploading model objects and even complex objects thanks to this nice post, the new goal is to have an implementation for even little more complicated scenario.

I have tried to implement the task in question via code examples searching google without a concrete and correct answer

The goal is to have multi purpose (multi data-type) data transfer from client side to server (without use of a form or HttpRequestBase) passing raw byte array in the most efficient way (i know that it is possible to implement a new protocol HTTP/2 or googles Protocol Buffers - Google's data interchange format

[HttpPost]
public JsonResult UploadFiles(byte[] parUploadBytearry)
{
}

preferably a model which one of it's properties is a byte[]

[HttpPost]
public [JsonResult / ActionResult] Upload(SomeClassWithByteArray parDataModel)
{
}

The ajax http Post Signature :

Log("AajaxNoPostBack preparing post-> " + targetUrl);
$.ajax({
    type: 'POST',
    url: targetUrl,
    data: mods,
    contentType: "application/json; charset=utf-8",
    dataType: "json",

    success:  function for Success..
});

I also desperately tried this workaround

public JsonResult UploadFiles(object parUploadBytearry)
{
    if (parUploadBytearry== null)
        return null;
    System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
    var pathtosSave = System.IO.Path.Combine(Server.MapPath("~/Content/uploaded"), "Test11.png");
    using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
    {
        bf.Serialize(ms, parUploadFiles);
        var Barr =  ms.ToArray();
        var s = new System.Web.Utils.FileFromBar(pathtosSave, BR);
    }
}

as it did post and received data all the way to saving the data (.png) successfully to a file in system, the data was not legit.

And the last sane try before the object to byte array attempt was this msdn Code example 1

What is the correct way to pass a byte array that C# will understand?

(in case of documents raw byte[] or files like png images)

like image 634
כרמי רפאל Avatar asked Mar 13 '16 08:03

כרמי רפאל


People also ask

Why We Use Web API over MVC?

Asp.Net Web API VS Asp.Net MVC Asp.Net MVC is used to create web applications that return both views and data but Asp.Net Web API is used to create full-blown HTTP services with an easy and simple way that returns only data, not view.

How can Web API improve performance?

Compress the Result of Web API In the Web, the data transfers through the network in packages (data packets), increasing the size of the data package, which will increase the size as well as increase the response time of the Web API. Thus, reducing the data packet size improves the load performance of Web API.


1 Answers

What is the correct way to pass a byte array

The easiest way of reading a byte[] from WebAPI without writing custom MediaTypeFormatter for "application/octet-stream" is by simply reading it from the request stream manually:

[HttpPost]
public async Task<JsonResult> UploadFiles()
{
    byte[] bytes = await Request.Content.ReadAsByteArrayAsync();
}

In another post, I described how to utilize the built in formatter for BSON (Binary JSON) which exists in WebAPI 2.1.

If you do want to go down the read and write a BinaryMediaTypeFormatter which answers "application/octet-stream", a naive implementation would look like this:

public class BinaryMediaTypeFormatter : MediaTypeFormatter
{
    private static readonly Type supportedType = typeof(byte[]);

    public BinaryMediaTypeFormatter()
    {
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/octet-stream"));
    }

    public override bool CanReadType(Type type)
    {
        return type == supportedType;
    }

    public override bool CanWriteType(Type type)
    {
        return type == supportedType;
    }

    public override async Task<object> ReadFromStreamAsync(Type type, Stream stream,
        HttpContent content, IFormatterLogger formatterLogger)
    {
        using (var memoryStream = new MemoryStream())
        {
            await stream.CopyToAsync(memoryStream);
            return memoryStream.ToArray();
        }
    }

    public override Task WriteToStreamAsync(Type type, object value, Stream stream,
        HttpContent content, TransportContext transportContext)
    {
        if (value == null)
            throw new ArgumentNullException("value");
        if (!type.IsSerializable)
            throw new SerializationException(
                $"Type {type} is not marked as serializable");

        var binaryFormatter = new BinaryFormatter();
        binaryFormatter.Serialize(stream, value);
        return Task.FromResult(true);
    }
}
like image 127
Yuval Itzchakov Avatar answered Sep 21 '22 05:09

Yuval Itzchakov