Why do I get different status code depending on expressions order? - c#

I'm using ASP.NET Core 3. This is the simple code of my endpoint:
await context.Response.WriteAsync("Not Found");
context.Response.StatusCode = StatusCodes.Status404NotFound;
I expected to get 400 status code, but I got 200. However, if I change the code strings order:
context.Response.StatusCode = StatusCodes.Status404NotFound;
await context.Response.WriteAsync("Not Found");
then I get 404 status code. Why does the status code value depend on the order of expressions?

The WriteAsync method actually sends out the response, so in the 1st example you are sending the response with the default status code (i.e. 200), and then modifying the status code of the response variable which is then not used further

Related

How can i retrieve the http response status code from an url?

I am automating a test for a page that contains a URL that needs to be then tested.
I created a method that I believed was giving me the http status code:
public string ContentUrlHttpRequest()
{
HttpWebRequest protocolWebRequest = (HttpWebRequest)WebRequest.Create(ContentUrl());
protocolWebRequest.Method = "GET";
HttpWebResponse response = (HttpWebResponse)protocolWebRequest.GetResponse();
return response.Headers.ToString();
}
ContentUrl() is another method i created to find the element on the page with the url to be tested and gets it's value.
I have also tried return response.StatusCode.ToString(); but the response i received was "OK".
I know that the response from that url needs to be = 200. I have this assertion that compares the response from the ContentUrlHttpRequest() to the expected results (200):
Assert.AreEqual("200", ContentUrlHttpRequest(), "The Url is not live. Http response = " + ContentUrlHttpRequest());
The response i am getting from ContentUrlHttpRequest() is not the status code but:"Date: Mon, 03 May 2021 09:07:13 GMT".
I understand why it is happening, it is getting the header of the page that is searching. But how could I get the status code? Is it possible with Selenium? Is there something wrong with my method and instead of Headers I need to use something different?
Unfortunately i am not able to provide with the urls that i am testing, or the platform with the url as they are confidential. Hopefully my issue is clear and you guys can give me some guidance.
You are not returning the response status code. You are returning the headers.
You should replace the return statement with this:
return ((int)response.StatusCode).ToString();
I guess you should use response.Status.ToString(); instead of response.Headers.ToString();
But the status contains not only the number like 200 or 401 but also text.
So if you are going to use response.Status.ToString(); you should Assert.True(ContentUrlHttpRequest().contains("200"))
Or you can use response.StatusCode.ToString(); this will give you the status number itself String without additional texts.

WebAssembly.JSException: TypeError: Failed to fetch when server does not response

I want to write code for case when server does not response.
I purposely shutdown backend to simulate this situation. HttpClient throws WebAssembly.JSException with message
TypeError: Failed to fetch
Is it OK?
I think it is confusing.
I afraid if I will depend from this behavior, there will be problems.
How can I properly handle this case?
The following code snippet describes how you perform an HTTP GET call to a Web Api endpoint, querying the value of IsSuccessStatusCode which indicates whether the HTTP response was successful or not. If successful, the code retrieves the data stream, deserialize it into a List<Contact>, and returns it to the calling code.
If not successful (else clause), handle failure...here you can place whatever checking you want to make, logging errors, displaying messages, etc.
What I'm trying to show here is the direction how to solve not only that issue of yours, but other exception such as NotFound ( 404 ) exception, etc.
You may also use the response.EnsureSuccessStatusCode(); in a try/catch block and handles exceptions according to your needs.
You can do all this in various manners...
public async Task<List<Contact>> GetContactsAsync()
{
var response = await httpClient.GetAsync("api/contacts");
// response.EnsureSuccessStatusCode();
if (response.IsSuccessStatusCode)
{
// Handle success
var responseContent = await response.Content.ReadAsStreamAsync();
return await JsonSerializer.DeserializeAsync<List<Contact>>(responseContent);
}
else
{
// Handle failure
}
}

IEnumerable that throws exception returns invalid Json when passed into OkResult in ASP.NET Core Web API

Start up a new ASP.NET Core Web API project in Visual Studio.
Now change the ValuesController.Get() action to be this:
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
var results = new[] {"hi"}.Select<string, string>(x => throw new ArgumentException());
return Ok(results);
}
When you hit this you get a 200 response with a response body of just [
Now if you now change it to enumerate the erroring Select before passing to Ok() it will raise an error correctly and return 500 with details of the error as expected in the default ASP.NET API template:
var results = new[] {"hi"}.Select<string, string>(x => throw new ArgumentException());
results.ToList();
return Ok(results);
What is happening here?
In the first example, the status code and response headers are sent to the client before the JSON serialisation starts. Giving the JSON serialiser an IEnumerable<string> results in deferred creation of the collection, which ends up being performed during the serialisation process. This means that the 200 status code and response headers are sent before the exception is thrown. Because the status code has already been sent, it cannot be changed from 200. The response cannot be "undone" either - it's a forward-only stream of data.
In the second example, the collection is created before the JSON serialisation process runs. In this case, the exception is thrown before the call to return Ok(results) can be reached. Whatever you're using for global exception handling catches this exception and writes out a response with a status code of 500.

Response Code is 0 when using Status404NotFound

I'm using AspNetCore 1.1.3 to create some endpoints and swagger to check them.
When using Resonse codes:
Status401Unauthorized
Status403Forbidden
Swagger tells me the response code is 401/403 like i would expect.
But when i use Status404NotFound swagger shows 0 as the response code and body is:
{
"error": "no response from server"
}
I'm using the following lines to return status code and body. There is no other change.
Response.StatusCode = StatusCodes.Status404NotFound; // or Status403Forbidden
return new JsonResult("{\"statusCode\":404}"); // 403
Is this expected behaviour? I would like to use the response codes in my application for error handling and 404 returning empty statuscode/body is not really useful.

Why changing the status code after writing to the body returns 504?

In ASP.NET 5 I've seem that the following code gives an error 504 in the response:
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Use((next) => {
return async (context) => {
context.Response.StatusCode = 200;
await context.Response.WriteAsync("Hello World");
context.Response.StatusCode = 201;
await context.Response.WriteAsync("Status code changed");
};
});
}
}
I know we shouldn't change the status code in this arbitrary manner, but my question here is: why changing it gives a problem? The fact is that, commenting the line that changes the status code, and using Response.WriteAsync twice, doesn't give any kind of problem, but changing the status code gives.
When we do it this returns a 504 status code. I believe it has to do with the way the response is sent to the client. It happens because when we call Respose.WriteAsync the response message starts being sent already? What's the reason for this error to occur?
Headers are sent the moment content is written to the response body stream and so you cannot change the headers again...so if you are setting the status code again, then probably an exception is being thrown in the middleware to indicate this...
BTW this exception would cause the 504 that you are seeing(like currently there is no response buffering layer which could catch these kind of exceptions and returns a 500 Internal Server with an error message)...you can put a try-catch block to capture the exception message and see what it says..

Categories