Response Code is 0 when using Status404NotFound - c#

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.

Related

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

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

AWS AppSync - GraphQL API Mapping Template Error

I am trying to integrate my GraphQL Web API with AppSync. But I am getting the following error
"errorType": "MappingTemplate",
"message": "Template transformation yielded an empty response."
My Data Source HTTP end Point is : https://mybooking123.com
My Query is:
mutation
{
Booking(ID:111,BusNumber:"AAAA1", comment:"None")
{
BusNumber
PassngerName
TravelDate
TravelTime
ValidityDate
ValidaityTime
ErrorCode
}
}: [BookingResponse]
Schema
type Mutation {
Booking(
ID: Int!,
BusNumber: String,
comment: String
): [BookingResponse]
}
type BookingResponse
{
BusNumber: String
PassngerName: String
BookingDate: String
BookingTime: String
ValidityDate: String
ValidaityTime: String
ErrorCode: Int
}
AppSync - Request Mapping Template
{
"version": "2018-05-29",
"method": "POST",
"resourcePath": "/GraphQL",
"params":{
"query":$util.toJson($ctx.args),
"headers": {
"Authorization": "$ctx.request.headers.Authorization"
}
}
}
AppSync - Response Mapping Template
## Raise a GraphQL field error in case of a datasource invocation error
#if($ctx.error)
$util.error($ctx.error.message, $ctx.error.type)
#end
## If the response is not 200 then return an error. Else return the body **
#if($ctx.result.statusCode == 200)
#set($body = $util.parseJson($ctx.result.body))
$util.toJson($body) ##make it $body.data depending on the return on your rest api
#else
$utils.appendError($ctx.result.body, "$ctx.result.statusCode")
#end
My GraphQL API is working with out AppSync. But I want to implement AppSync to access the GraphQL API. I am not sure what's wrong with the template mapping. Thanks for your help.
The problem can be with the $utils.appendError VTL method (line 10 of the Response Mapping Template).
Based on your Response mapping template, if there is an error in the Velocity parsing, AppSync will throw an error (line 2).
If there is no error, the Velocity parser will evaluate the response ($ctx.result) and send back the body if the statusCode is equal to 200. So far so good. The problem is if the statusCode is different from 200 (line 9).
In that case, AppSync should also throw an error. But you are using the $util.appendError. In that case, VTL will add error information to the context and will keep working to generate the result template. But because it does not do anything after this step, the generated template is empty (Template transformation yielded an empty response.).
the info from AppSync Resolver Mapping Util docs:
$util.appendError(String)
Appends a custom error. This can be used in request or response mapping templates if the template detects an error with the request or with the invocation result. Unlike $util.error(String), the template evaluation will not be interrupted, so that data can be returned to the caller.
In GraphQL is possible to have a response that has a part that was successful and a part that was an error. That happens because the response probably is coming from two different resolvers. If one of them worked in the other doesn't, you can get the response both responses in the final GraphQL response. In that scenario, AppSync will add the success response to the expected GraphQL field and add the error to the context.
To solve your issue, instead of using $util.appendError use $util.error in line 10. With that, if your call failed, AppSync will add the error information and halt the VLT execution instead of try to perform the next steps to yield the result.

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.

System.AggregateException on GetStringAsync in asp.net

I am trying to call an API like this:
var client = new HttpClient();
client.DefaultRequestHeaders.Add("apiKey", Token);
**var result = await client.GetStringAsync(GetUrl($"accounts/{accountID}/menu?skip=0&limit=1"));**
var menuList = JsonConvert.DeserializeObject<List<Menu>>(result);
but getting System.AggregateException on GetStringAsync, error CS0103: The name 'InnerExceptionCount' does not exist in the current context
and Exception Message
One or more errors occurred. (Response status code does not indicate success: 404 (Not Found).)
I see that this is returned in result
Status = WaitingForActivation, Method = "{null}", Result = "{Not yet computed}
I tried to make call using postman with same url and apikey in header and I see the results.
Can you please suggest what is wrong with above code. Api key expects only an apiKey in header.
Thanks.
Anytime that an async call fails you'll get an AggregateException, what's important is the inner exception within that.
It looks like your inner exception is 404 Not Found, which means that you're not calling the correct URL.
You said it's working in postman, that's great. To find the root cause I suggest the following:
Start Fiddler
Make the call through postman, view the request in Fiddler
Make the call through your C# code, view the request in Fiddler
Comparing the Postman request against the C# request should tell you where the error is.

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