cell cell - 3 months ago 15
JSON Question

Return a byte[] array from controller class in ASP.NET

I have a Controller class (in

C#
) which has to return a byte array from its login method. Please find the below source code of my Controller class for my Login functionality.

[RoutePrefix("Account")]
public class AccountsController : ApiController
{
[Route("Login")]
[HttpPost]
public byte[] Login()
{
byte[] mSessionID = new Session().getmSessionID();
return mSessionID;
}
}


While Testing, the web service returns a base64Encoded string value as "
LVpgqWBYkyXX1FlDg95vlA==
". I want my Web service to return a byte array response (which is in JSON response).

Answer

If you want to get the response in this format:

{
  "Numbers": [
    2,
    3,
    4,
    5,
    6,
    7,
    8,
    9,
    10,
    1,
    11,
    12,
    13,
    14,
    15,
    2,
    45
  ]
}

Solution 1: JSON Formatters

You need to modify the way that JSON is serialized. WebAPI uses JSON.Net unser the hood to format WebAPI responses as JSON. We can override the byte[] formatter as follows:

Create a custom formatter

public class ByteArrayFormatter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(byte[]);
    }
    public override bool CanRead
    {
        get
        {
            return false;
        }
    }
    public override bool CanWrite
    {
        get
        {
            return true;
        }
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var byteArray = (byte[])value;
        writer.WriteStartArray();
        if (byteArray != null && byteArray.Length > 0)
        {
            foreach (var b in byteArray)
            {
                writer.WriteValue(b);
            }
        }
        writer.WriteEndArray();
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

Register the formatter globally in the Application_Start method in Global.asax.cs (note that ALL byte[] types will be serialised this way):

var formatters = GlobalConfiguration.Configuration.Formatters;
var jsonFormatter = formatters.JsonFormatter;
jsonFormatter.SerializerSettings.Converters.Add(new ByteArrayFormatter());

Create a model so that your JSON response has a Numbers property:

public class NumbersModelByte
{
    public byte[] Numbers { get; set; }
}

Modify your controller to use this model:

[Route("login")]
[System.Web.Http.AcceptVerbs("GET")]
[System.Web.Http.HttpGet]
public NumbersModelByte Login()
{
    byte[] mSessionID = new Session().getmSessionID();
    return new NumbersModelByte
    {
        Numbers = mSessionID
    };
}

Solution 2: The quick and dirty

You will need to return an object (a model).

NumbersModelInt.cs (notice the int[] type)

public class NumbersModelInt
{
    public int[] Numbers { get; set; }
}

Then you need to cast all of your bytes in your byte array to ints in the response:

[Route("Login")]
[HttpPost]   
public byte[] Login()
{
    byte[] mSessionID = new Session().getmSessionID();
    return new NumbersModelInt
    {
        Numbers = mSessionID.Select(b => (int) b).ToArray()
    };
}