简体   繁体   中英

c# HttpResponseMessage.Content does not return MemoryStream correctly to HttpClient but using byte[] for return works

I am trying to use HttpClient.PostAsync to submit data to a Controller and then return a Bitmap in Memorystream created by QRCoder to HttpClient via IActionResult .

If the Controller returns byte[] , the response.Content.ReadAsStringAsync().Result gets the correct MemoryStream data.

However, if the Controller returns IActionResult , neither response.Content.ReadAsStringAsync().Result , response.Content.ReadAsByteArrayAsync().Result , response.Content.ReadStreamAsync() provides the expected data.

I can't figure out where it goes wrong when I use the IActionResult .

namespace PLMLJS.Controllers
{
    [Route("api/[controller]")]
    public class QRCoder2Controller : Controller
    {
        private readonly IQRCoderService _service;
        String _save2Path;

        public QRCoder2Controller(
            IQRCoderService service)
        {
            _service = service;
            _save2Path = "c:\\Temp";
        }

        // The return byte[] successfully return the Bitmap data to HttpClient
        [HttpPost]  // Create QRCode
        [Route("createQRCode_retByteArray")]
        public byte[] CreateQRCode_retByteArray([FromBody] CountriesView data2QRCodeObj)
        {   
            string data2QRCode = "";
            Bitmap qrCodeBitmap = null;
            string fileName = Path.GetRandomFileName() + ".jpg"; 

            data2QRCode = "'Name':" + "'" + data2QRCodeObj.Name + "',";
            data2QRCode += "'ISO2':" + "'" + data2QRCodeObj.ISO2 + "'";

            // Returns Bitmap 
            qrCodeBitmap = _service.RenderQrCode(data2QRCode);

            Byte[] qrCodeBitmapByteArray;

            if (qrCodeBitmap != null)
            {
                // save to file to verify QRCode is successfully created
                string file = _save2Path + "\\" + fileName;
                qrCodeBitmap.Save(file, ImageFormat.Jpeg);

                var memoryStream = new MemoryStream();
                qrCodeBitmap.Save(memoryStream, ImageFormat.Jpeg);
                memoryStream.Seek(0, SeekOrigin.Begin);
                HttpResponseMessage response = new HttpResponseMessage();
                response.Content = new StreamContent(memoryStream);
                response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpg");
                qrCodeBitmapByteArray = memoryStream.ToArray();
                return qrCodeBitmapByteArray;
            }

            return null;
        }

        // The return IActionResult does not return the Bitmap data to HttpClient
        [HttpPost]  // Create QRCode
        [Route("createQRCode_retIActionResult")]
        public IActionResult CreateQRCode_retIActionResult([FromBody] CountriesView data2QRCodeObj)
        {   
            string data2QRCode = "";
            Bitmap qrCodeBitmap = null;
            string fileName = Path.GetRandomFileName() + ".jpg";

            data2QRCode = "'Name':" + "'" + data2QRCodeObj.Name + "',";
            data2QRCode += "'ISO2':" + "'" + data2QRCodeObj.ISO2 + "'";

            // Returns Bitmap 
            qrCodeBitmap = _service.RenderQrCode(data2QRCode);
            var memoryStream = new MemoryStream();
            qrCodeBitmap.Save(memoryStream, ImageFormat.Jpeg);
            memoryStream.Seek(0, SeekOrigin.Begin);
            HttpResponseMessage response = new HttpResponseMessage();

            // response.Content = new StreamContent(memoryStream);

            // tested failed
            response.Content = new ByteArrayContent(memoryStream.ToArray());
            // response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpg");        // tested not working
            //// response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
            return Ok(response);
        }
    }
}

Integration tests used to verify data returned to HttpClient .

namespace PLMLJS.Test
{
    [TestClass]
    public class TestQRCoder2Controller
    {
        private HttpClient _httpClient;
        private string _url;

        [TestInitialize]
        public void TestInit()
        {
            if (_httpClient != null)
                _httpClient.Dispose();
            _httpClient = new HttpClient();
            _url = Settings.ServerURL + "/api/qrcoder2";   
        }

        [TestCleanup]
        public void TestCleanup()
        {
            if (_httpClient != null)
                _httpClient.Dispose();
            _url = null;
        }

        [TestMethod]
        public async Task Test_createQRCode_retByteArray()
        {   // This function works.  
            // Successfully receives Bitmap(byte[]) returned from controller (createQRCode_retByteArray)

            CountriesView countriesView = new CountriesView();
            countriesView.Name = "United States";
            countriesView.ISO2 = "US";

            TestInit();

            using (var client = new HttpClient())
            {
                var data = JsonConvert.SerializeObject(countriesView);
                var buffer = System.Text.Encoding.UTF8.GetBytes(data);
                var byteContent = new ByteArrayContent(buffer);
                byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                HttpResponseMessage response = null;

                try
                {
                    response = await _httpClient.PostAsync(_url + "/createQRCode_retByteArray/", byteContent);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Exception: TargetSite=" + e.TargetSite + "   Error messsage=" + e.Message);
                }

                if (response.IsSuccessStatusCode)
                {   // if return Ok(Bitmap qrCodeBitmap) then the following 2 lines work.

                    var result = response.Content.ReadAsStringAsync().Result;
                    // result:   (expected result value)
                    // "\"/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBk....."

                    result = result.Replace("\"", string.Empty);
                    byte[] bytearray = Convert.FromBase64String(result);

                    File.WriteAllBytes("c:\\temp\\img\\Ret_ByteArray_" + Path.GetRandomFileName() + ".jpg", bytearray);
                }

                Assert.AreEqual((int)HttpStatusCode.OK, (int)response.StatusCode);
            }

            TestCleanup();
        }

        [TestMethod]
        public async Task Test_createQRCode_retIActionResult()
        {   // This function fails.  
            // Neither anyone below at Controller sends memoryStream back
            // response.Content = new ByteArrayContent(memoryStream.ToArray());
            // response.Content = new StreamContent(memoryStream);

            CountriesView countriesView = new CountriesView();
            countriesView.Name = "United States";
            countriesView.ISO2 = "US";

            TestInit();

            using (var client = new HttpClient())
            {
                var data = JsonConvert.SerializeObject(countriesView);
                var buffer = System.Text.Encoding.UTF8.GetBytes(data);
                var byteContent = new ByteArrayContent(buffer);
                byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                HttpResponseMessage response = null;

                try
                {
                    response = await _httpClient.PostAsync(_url + "/createQRCode_retIActionResult/", byteContent);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Exception: TargetSite=" + e.TargetSite + "   Error messsage=" + e.Message);
                }

                if (response.IsSuccessStatusCode)
                {   
                    // var result = response.Content.ReadAsByteArrayAsync().Result;     fails

                    var result = response.Content.ReadAsStringAsync().Result.Replace("\"", string.Empty);  //What went wrong here?????
                    // result:    (unexpected result value)
                    // "{version:{major:1,minor:1,build:-1,revision:-1,majorRevision:-1,minorRevision:-1},
                    // content:{headers:[]},statusCode:200,reasonPhrase:OK,headers:[],requestMessage:null,
                    // isSuccessStatusCode:true}"

                    byte[] byteArray = Convert.FromBase64String(result);

                    File.WriteAllBytes("c:\\temp\\img\\Ret_IActionResult_" + Path.GetRandomFileName() + ".jpg", byteArray);
                }

                Assert.AreEqual((int)HttpStatusCode.OK, (int)response.StatusCode);
            }

            TestCleanup();
        }
    }

}

On the server side Asp.Net Core no longer uses HttpResponseMessage

You need to use the appropriate action result to return the desired data.

You are already storing the data in a stream so using FileStreamResult with a proper mine type and file name should suit your needs.

[HttpPost]  // Create QRCode
[Route("createQRCode_retIActionResult")]
public IActionResult CreateQRCode_retIActionResult([FromBody] CountriesView data2QRCodeObj) {   

    var data2QRCode = "'Name':" + "'" + data2QRCodeObj.Name + "',";
    data2QRCode += "'ISO2':" + "'" + data2QRCodeObj.ISO2 + "'";

    // Returns Bitmap 
    Bitmap qrCodeBitmap = _service.RenderQrCode(data2QRCode);
    var memoryStream = new MemoryStream();
    qrCodeBitmap.Save(memoryStream, ImageFormat.Jpeg);
    memoryStream.Seek(0, SeekOrigin.Begin);

    var fileName = Path.GetRandomFileName() + ".jpg";
    var mimeType = "image/jpg";

    //return the data stream as a file
    return File(memoryStream, mimeType, fileName); //<-- returns a FileStreamResult
}

The above will return a file stream that should provide the desired data to the client.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM