1

I'm building my first website and know emberassingly little. I want to get a list of players in form of a csv string for a game from my server. In my C# server code I have

[HttpGet("[action]")]
public HttpResponseMessage GetPlayers()
{
    // string csv = String.Join(",", PLAYERS_DB.Keys);
    string csv = "test";
    // I plan to replace "test" with a csv later. For this problem,
    // it's probably enough to handle this test string.
    var resp = new HttpResponseMessage(HttpStatusCode.Accepted);
    resp.Content = new StringContent(csv, System.Text.Encoding.UTF8, "text/plain");
    return resp;
}

I call this in javascript via

callApiGET() {
    return fetch("api/Test/GetPlayers", {
        method: "GET"
    }).then(
        response => response.text()
        // Here I hava also tried to work with response.json()
        // Reading the statusCode from json works flawlessly
    ).then(
        text => {
            console.log(text)
        }
    )
        .catch(error => {
            console.error(error)
            alert(error)
        });
}

(Yes, my class is called TestController.) The console then says:

{
  "version": {
    "major": 1,
    "minor": 1,
    "build": -1,
    "revision": -1,
    "majorRevision": -1,
    "minorRevision": -1
  },
  "content": {
    "headers": [{
      "key": "Content-Type",
      "value": ["text/plain; charset=utf-8"]
    }]
  },
  "statusCode": 202,
  "reasonPhrase": "Accepted",
  "headers": [],
  "requestMessage": null,
  "isSuccessStatusCode": true
}    

I expect the important part of the above to be

"content":{"headers":[{"key":"Content-Type","value":["text/plain; charset=utf-8"]}]}

Here I would expect to read "test" somewhere, but I can't. So here is my question:

TL;DR: If my server returns a HttpResponseMessage, how do I send a string together with it, and how do I fetch it properly in Javascript?

I hope that I didn't include any typos. I've cut down my code to the necessary parts. If I find any mistakes, I'll edit the question.

stuartd
  • 70,509
  • 14
  • 132
  • 163
Fred
  • 13
  • 4
  • What actual response do you see in the network tab? – SLaks Jun 08 '18 at 16:26
  • 1
    It sounds like you're mixing MVC versions and returning `HttpResponseMessage` as a JSON object instead of as a response. – SLaks Jun 08 '18 at 16:27
  • @SLaks I'm not sure, this is the answer you want. I clicked on network and after I made the request on the newly added GetPlayers in the Name tab. Then I clicked on Response in the tab next to it. There I get `{"version":{"major":1,"minor":1,"build":-1,"revision":-1,"majorRevision":-1,"minorRevision":-1},"content":{"headers":[{"key":"Content-Type","value":["text/plain; charset=utf-8"]}]},"statusCode":202,"reasonPhrase":"Accepted","headers":[],"requestMessage":null,"isSuccessStatusCode":true}` – Fred Jun 08 '18 at 16:31
  • You shouldn't be returning HttpStatusCode.Accepted here - _"The request has been accepted for processing, but the processing has not been completed. The request might or might not be eventually acted upon, and may be disallowed when processing occurs"_ – stuartd Jun 08 '18 at 16:32
  • @stuartd What should I return instead? – Fred Jun 08 '18 at 16:33
  • Just leave it as the default, which is "OK" (200) – stuartd Jun 08 '18 at 16:35
  • Your actual problem comes from the server; check your versions of MVC / Web API. What `HttpResponseMessage` class are you returning? – SLaks Jun 08 '18 at 16:36
  • I'm afraid to admit, but I don't know where to get those informations. How do I quickly check all those things? I'm using VS Code and the Cmder console. I know the following versions: `node -v v8.11.1`, `npm -v 5.6.0` and `dotnet --version 2.1.104` – Fred Jun 08 '18 at 16:43
  • https://stackoverflow.com/q/41992033/34397 – SLaks Jun 08 '18 at 16:46
  • @stuartd Was this supposed to solve the main issue, or is it just conventions? Anyway, I've changed it, but it doesn't change anything (at least I don't see any changes except for the statusCode). – Fred Jun 08 '18 at 16:46
  • https://koukia.ca/asp-net-web-api-is-dead-long-live-asp-net-core-bd852de1369d – SLaks Jun 08 '18 at 16:47
  • @SLaks This works. Thank you very much! I'll have a deeper look into what else is written here (because I want to understand what I'm doing as much as possible), but the problem is solved. – Fred Jun 08 '18 at 16:51
  • @Fred it's unrelated to the issue, sorry I should have mentioned that. It's a bit more than just a convention as end users of your app might expect a 200 response to a get request. See [this question](https://stackoverflow.com/questions/4099869/is-it-wrong-to-return-202-accepted-in-response-to-http-get) for some detail. – stuartd Jun 08 '18 at 16:51
  • @stuartd I see. Thank you very much! I'm glad to know that now. – Fred Jun 08 '18 at 16:53

5 Answers5

2

Add .AddWebApiConventions() to your Startup class to register an output formatter that recognizes actions that return HttpResponseMessage.

Or change your actions to return ActionResults instead.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • Yes, `ActionResult` works flawlessly. Thank you very much! Since @cwharris in his answer also states that I don't need HttpResponseMessage and since I don't have any reason to use that class, I will not use `.AddWebApiConventions()`. Thank you, however, for that suggestion, too. – Fred Jun 08 '18 at 17:08
0

You don’t need to return an HttpResponseMessage from your Controller actions. That will cause MVC to serialize the HttpResponseMessage, not actually use it as the response message. You just need to return the type of object you want MVC to process using content negotiation. Content negotiation is how MVC figures out how to serialize your response object and convert it to an HTML response. For ViewResults, this means rendering stuff (usually Razor views). For JsonResult this means converting the returned object to JSON and then returning an OK response with that JSON as the body. For POCOs, that usually means acting just like a JsonResult. Try this:

public ActionResult GetPlayers()
{
    return Json(“test”);
}

Or

public string GetPlayers()
{
    return “test”;
}
cwharris
  • 17,835
  • 4
  • 44
  • 64
  • 1
    Thank you very much! After @Slaks 's comment I've tried this, and now it works. I actually now use it the way it's explained in the link posted in the comments of the main question: [link](https://stackoverflow.com/questions/41992033/asp-net-core-webapi-httpresponsemessage-create-custom-message) – Fred Jun 08 '18 at 17:10
0

I use this library https://www.nuget.org/packages/Fetch_dotNET/

// TOKEN JWT
var fetchOptions2 = "{" +
    "'method': 'GET'," +
    "'headers': {" +
        "'Accept': 'application/json'," +
        "'Content-Type': 'application/json'," +
        "'Authorization': 'Bearer " + jwt + "'," +
        "'User-Agent': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/6.0;)'" +
    "}," +
    "'timeout': 3000" + // 3 second timeout
"}";


// method: 'GET WITH TOKEN JWT'
Console.WriteLine("> GET WITH TOKEN JWT");
var httpResponseJWT = await HttpClient.FetchAsync(address, fetchOptions2, data);
Console.WriteLine("response:");
Console.WriteLine(httpResponseJWT);
DisplayResponseStatus(httpResponseJWT);
-1

Try this syntax:

$.ajax({
  url: "api/Test/GetPlayers",
  method: "GET"
})
  .done(function( data ) {
      console.log(data);
  });
-1

To write raw text to output, you may handle HttpResponse directly instead of return the value, like this:

    [HttpGet("[action]")]
    public void GetRawString()
    {
        string csv = "a,c,d";
        Response.ContentType = "text/plain; charset=UTF-8";
        Response.Body.Write(Encoding.UTF8.GetBytes(csv));
    }
Matheus Neder
  • 109
  • 1
  • 2
  • 7