简体   繁体   中英

.NET 4.7 web api returning HttpResponseMessage object info instead of StringContent when including a NetStandard 2.0 package

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?

I was having this issue and have been battling with it all day but thanks to this post byNkosi 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.

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");

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.

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