2

I have a WS that I call like this:

HttpResponseMessage response = await client.PostAsync(url, new StringContent(json));

the WS will throw an Exception (Forbidden) and in my Blazor application that made the PostAsync call, I will get an HttpResponseMessage with response code 405, not sure why its 405, it should be 403 (Postman returns 403).

I have enabled CORS (ServiceStack code):

Plugins.Add(new CorsFeature(allowedOrigins: "*",
  allowedMethods: "GET, POST, PUT, DELETE, OPTIONS",
  allowedHeaders: "*",
  allowCredentials: true));

This is some Console.Writeline I did, just before the PostAsync:

enter image description here

Failed to load resource: the server responded with a status of 405 ()

** UPDATED **

This are the two methods:

    public async Task<TResponse> PostAsync<TResponse, TRequest>(string requestUri, TRequest request)
    {
        string url = GetUrl(requestUri);
        Console.WriteLine("URI: " + url);
        string json = JsonConvert.SerializeObject(request);
        Console.WriteLine($"{url} | {json}");
        HttpResponseMessage response = await client.PostAsync(url, new StringContent(json));
        return await GetResponseOrThrowHttpException<TResponse>(response);
    }


    private async Task<T> GetResponseOrThrowHttpException<T>(HttpResponseMessage response)
    {
        Console.WriteLine($"GetResponseOrThrowHttpException: {response.StatusCode}");
        string responseString = await response.Content.ReadAsStringAsync();
        Console.WriteLine($"GetResponseOrThrowHttpException ContentStringResult: |{responseString}|");
        if (!response.IsSuccessStatusCode)
        {
            Newtonsoft.Json.Linq.JObject jsonObject = Newtonsoft.Json.Linq.JObject.Parse(responseString);
            string responseStatusString = jsonObject["ResponseStatus"].ToString();

            Console.WriteLine($"GetResponseOrThrowHttpException 4: {responseStatusString}");
            ResponseStatus responseStatus = JsonConvert.DeserializeObject<ResponseStatus>(responseStatusString);
            Console.WriteLine($"Throwing HttpException: {response.StatusCode} {responseStatus.Message}");
            throw new HttpException(response.StatusCode, responseStatus.Message);
        }
        return JsonConvert.DeserializeObject<T>(responseString);
    }

When I try to get the string value of the response, it is empty:

string responseString = await response.Content.ReadAsStringAsync();

and the responseString is an empty (length 0) string.

If I run the exact same request in Postman, I get a valid response:

enter image description here

So, the response JSON, seen at the bottom in the image above, is what I want to work with in the Blazor app, and parse it as a JSON object and move on from there. I also note that I get here a 403 error, which I expected, and in the Blazor app, I get a 405.

Is this a CORS issue even though I have enabled CORS on the WS side?

Ted
  • 19,727
  • 35
  • 96
  • 154
  • 3
    status code 405: Method not allowed, this indicates that possibly what you think is the same is not, could you debug and post what is in the `url` and `json` in your`PostAsync` – JohnChris Jun 14 '19 at 11:48
  • Yeah, its interesting with the 405. I updated the answer, a little more code and console.writelines as well as URLs (masked a little). THey are the same, and both are POST. CORS is enabled, I get the expected exception in the WS. – Ted Jun 14 '19 at 11:57
  • There seem to be a lot of headers on your postman request, are those by chance necessary for your request on the server? I don't see you adding them – Mark C. Jun 14 '19 at 12:01
  • Hmm, there are 8 auto-added headers in Postman, that I cant seem to remove. However, in both cases, through postman or Blazor, the same exception (that I expect and want) is thrown in the server, so the request reaches the same thing. The error message "din version...." is also what I generate on the WS-side, so it behaves the same as far as the WS goes. The 8 auto-added headers are not relevant for the WS. – Ted Jun 14 '19 at 12:07
  • Oh, Postman says "These headers are auto-generated by Postman and not saved with your request" :-) – Ted Jun 14 '19 at 12:08
  • Ok, it seems that the DTO (the Login object) is not correct when sent from Blazor (the proprties are all NULL), but in Postman, they are OK. This is probably the issue. – Ted Jun 14 '19 at 12:21
  • Got it - it was a missing content-type in the Blazor app. It was default to plain/text when it was supposed to be `application/json` – Ted Jun 14 '19 at 12:46

2 Answers2

3

I guess your content should be posted like that:

new StringContent(json, Encoding.UTF8, "application/json")

Even if this is not the cause of your suffering, it's better to use this so...

Hope this helps...

enet
  • 41,195
  • 5
  • 76
  • 113
  • Yep, I was led in the right direction by JohnChris and codevision and figured it out. Thanks =) – Ted Jun 14 '19 at 12:53
  • You could have used the Blazor extension method public static Task PostJsonAsync(this HttpClient httpClient, string requestUri, object content), which could have saved you this headache. – enet Jun 14 '19 at 12:55
  • Thanks. Yeah, I know about that one, but for some reason I cannot remember now, I chose not to use it, or it didnt work... or something... Cant remember =) – Ted Jun 14 '19 at 13:18
2

Verify that you have setup proper CORS configuration for the domain. Looks like you made call to another domain:port combination from your Blazor application. Even if this C#, all security rules inside browser still applies.

codevision
  • 5,165
  • 38
  • 50
  • Thanks, CORS is setup and working. I have other requests that are allowed and working fine (before this login test). – Ted Jun 14 '19 at 11:50
  • 1
    Do you able to run Fiddler and check what's actually send to the server? That way you will actually see what response happens? The nothing specific to Blazor, same rules as with JS `fetch`. Very likely that this still CORS issue, other alternative is that you could not read content response if server return 405 and this is exactly response which you want to have.If 405 is not expected by you, then look for CORS. – codevision Jun 14 '19 at 11:59
  • I am expecting a 403, not 405... Postman gives me a 403 back, but the Blazor app gives me 405. – Ted Jun 14 '19 at 12:11
  • Ok, it seems that the DTO (the Login object) is not correct when sent from Blazor (the proprties are all NULL), but in Postman, they are OK. This is probably the issue. – Ted Jun 14 '19 at 12:21
  • You led me in the right direction; it was the "Content-Type" =) default is `plain/text` instead of the required `application/json`. This created the 405. If u prefer, create an answer on that =) – Ted Jun 14 '19 at 12:46