2

I created a .net 4.7 web api project with a simple Action that returns a string

[System.Web.Http.Route("api/GetData")]
[System.Web.Http.HttpGet]
public async Task<System.Net.Http.HttpResponseMessage> GetData()
{
    string result = await Task.FromResult("test data");
    var content = new System.Net.Http.StringContent(result);
    return new System.Net.Http.HttpResponseMessage() { Content = content };
}

When querying this route I get a result of "test data". As soon as I add a NetStandard 2.0 package ("System.Threading.Tasks.Extensions" for example) and re-query the route my result looks completely different

{
    "Version": {
        "_Major": 1,
        "_Minor": 1,
        "_Build": -1,
        "_Revision": -1
    },
    "Content": {
        "Headers": [{
            "Key": "Content-Type",
            "Value": ["text/plain; charset=utf-8"]
        }]
    },
    "StatusCode": 200,
    "ReasonPhrase": "OK",
    "Headers": [],
    "RequestMessage": null,
    "IsSuccessStatusCode": true
}

The strange thing is before the NuGet reference System.Net.Http is v4.0.0.0 Location "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.7\System.Net.Http.dll" after I add the reference the version changes to v4.2.0.0 location "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\Microsoft\Microsoft.NET.Build.Extensions\net461\lib\System.Net.Http.dll"

Does anyone have any ideas why this is and how to fix it?

Koenyn
  • 694
  • 4
  • 16
  • 1
    I'm getting the same issue at the moment. My endpoint returns a stream which works great normally but the same kind of result as yours. – Ben Thomson Jan 30 '18 at 05:08

3 Answers3

1

I was having this issue and have been battling with it all day but thanks to this post by Nkosi I've been able to solve it:

How to return a file (FileContentResult) in ASP.NET WebAPI

So I did as Nkosi recommended and changed it to return an IHttpActionResult with a custom response so my code looks like (you could also create a custom IHttpActionResult as someone else suggests):

[HttpGet]
public IHttpActionResult GenerateReport(int reportId)
{
    var reportMemoryStream = _reportService.GenerateStream(reportId)
    var result = new HttpResponseMessage(HttpStatusCode.OK)
    {
        Content = new ByteArrayContent(reportMemoryStream.ToArray())
    };

    result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
    {
        FileName = "ExecutiveReport.docx"
    };

    result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

    return ResponseMessage(result);
}

However, this gave me another issue as follows:

Method not found: 'System.Web.Http.Results.ResponseMessageResult'

To solve this I followed the advice in Namespace System.Web.Http.Results not found within asp.net web api application and ran

Update-Package Microsoft.AspNet.WebApi -reinstall

And then everything worked a charm. Hope that helps you and any other that come to this question and haven't found the other answers I did.

Ben Thomson
  • 1,083
  • 13
  • 29
  • Hi, thanks for the input. I managed to solve this using the TextPlainFormatter implementation in this answer below. I think it might be a better fit for what we're doing. https://stackoverflow.com/questions/11581697/is-there-a-way-to-force-asp-net-web-api-to-return-plain-text/12871025#12871025 – Koenyn Jan 31 '18 at 05:42
0

For anyone stumbling upon this post, the best solution I could find out there was this answer Is there a way to force ASP.NET Web API to return plain text?

basically you implement

public class TextPlainFormatter : MediaTypeFormatter
{
    public TextPlainFormatter()
    {
        this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain"));
    }

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

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

    public override Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContentHeaders contentHeaders, TransportContext transportContext)
    {
        return Task.Factory.StartNew(() => {
            StreamWriter writer = new StreamWriter(stream);
            writer.Write(value);
            writer.Flush();
        });
    }

    public override Task<object> ReadFromStreamAsync(Type type, Stream stream, HttpContentHeaders contentHeaders, IFormatterLogger formatterLogger)
    {
        return Task.Factory.StartNew(() => {
            StreamReader reader = new StreamReader(stream);
            return (object)reader.ReadToEnd();
        });
    }
}

Then you register your formatter in your webapi config

config.Formatters.Add(new TextPlainFormatter());

Then return the result from you action as follows

this.Request.CreateResponse(HttpStatusCode.OK, "some text", "text/plain");
Koenyn
  • 694
  • 4
  • 16
0

Ran across this myself and came up with a working solution!

Funny enough your note about your System.Net.Http.dll reference changing is what led me to my solution.

In my case it would work for local debug but would fail when deployed live.

So, I added the following binding redirect to my web.config to force it to use the version of my choosing:

<dependentAssembly>
        <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>

This does the trick for me!

Those numbers are wonky (v 5.0.0.0 is not even a thing) but it gets the job done. Feel free to modify as needed.

TheLostBrain
  • 651
  • 7
  • 9