Response body is not returning from custom error responses in swagger Swashbuckle - asp.net-web-api

I have integrated swagger to a dot.net core API application using Swashbuckle. When I execute an API via Swagger UI without providing credentials it is returning a "401- Unauthorized" response as expected.
But it is not showing the error response which I have configured to return as a custom error response as the body. It does returns the header as below image.
When I execute the same API via Postman it does return the custom error response as below.
What I need is, I need to see the custom error response body in the swagger UI as well.
In Postman,
In Swagger,
Same scenario with the 403 and 404 status codes.

After struggling a lot I have found the root cause to the issue.It is due to not having configure the Response Content type in the "app.UseStatusCodePages" middle ware.
// Custom status handling
app.UseStatusCodePages(async (StatusCodeContext context) =>
{
var settings = new JsonSerializerSettings();
settings.NullValueHandling = NullValueHandling.Ignore;
settings.Formatting = Formatting.Indented;
int statusCode = context.HttpContext.Response.StatusCode;
***context.HttpContext.Response.ContentType = "application/json";*** // Added this line to solve the issue
await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(
new ErrorResponse((HttpStatusCode)statusCode,
ReasonPhrases.GetReasonPhrase(statusCode)
), settings));
});
Had to add "context.HttpContext.Response.ContentType = "application/json";" to fix the issue.

Related

CORS error with UnityWebRequest from ASP.NET Web API 6.0 with CORS enabled

I'm working on a WebGL game with Unity in which I am attempting to call a custom built ASP.NET Web API that's built specifically to work with the game. I've added the code I thought was necessary to get CORS working for making the API requests from the browser, but I keep getting the same error: "Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource."
I've tried several different variations of how to implement CORS with the API in the program.cs script. I tried:
builder.Services.AddCors(p => p.AddPolicy("corspolicy", build =>
{
build.WithOrigins("*").AllowAnyMethod().AllowAnyHeader();
}));
And
builder.Services.AddCors(o =>
{
o.AddPolicy("corspolicy", build =>
build.WithOrigins("*")
.AllowAnyMethod()
.AllowAnyHeader()
});
Of course, I also included:
app.UseHttpsRedirection();
app.UseCors();
app.UseAuthorization();
app.MapControllers();
app.Run();
According to the documentation and the tutorials I followed, it looks like I added the correct code in the correct places, but when I publish the API to Azure and try to call it from the WebGL game, I always get that same error that I listed above.
I also tried using the AddDefaultPolicy() with just UseCors(), but that had the same result.
I've tried plugging the URL into Postman and HTTPie along with the header: "Origin": "http://127.0.0.1:5500", to mimic the game running on my local machine, and when I include that, it does return an "Acces-Control-Allow-Origin" header in the response set to either "*" or "http://127.0.0.1:5500" (I've tried both), depending on what I used in WithOrigins().
In Unity I'm making the API call like this:
public void MakeAPIRequest()
{
_webRequest = CreateRequest($"https://apiurl...");
_APICallType = APICallType.login;
_webRequestAsyncOperation = _webRequest.SendWebRequest();
_webRequestAsyncOperation.completed += GetRequestAsyncOperation_completed;
}
private UnityWebRequest CreateRequest(string path, RequestType type = RequestType.GET, object data = null)
{
var request = new UnityWebRequest(path, type.ToString());
if (data != null)
{
var bodyRaw = Encoding.UTF8.GetBytes(JsonUtility.ToJson(data));
request.uploadHandler = new UploadHandlerRaw(bodyRaw);
}
request.downloadHandler = new DownloadHandlerBuffer();
request.SetRequestHeader("Content-Type", "application/json");
return request;
}
I'm currently at a loss for how to get this working, so if anyone here has any advice about what to try or look into, I would really appreciate it.

.net core 3 status code 405 in response when using httpClient and Fiddler?

Why am I getting status code 405 in response when using httpClient or Fiddler?
I am getting a status code 405 response when tyring to access a net core 3.1 wepapi action method that accepts json string sent in the body as shown below.
The status code 405 occurs when the request is sent in a net core 3.1 console app using httpClient.
In Fiddler the request works fine.
The webapi action code is
[RequireHttps]
[HttpPut("setkdatainformation/{id:int:min(0):max(5)}/{info}")]
[Authorize(Roles = "Admin")]
public async Task<string> SetKDataInformation(int id, string info, [FromBody] string kinfo)
{
The request is sent from a .net core 3.1 console app using http client as shown below
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(newMediaTypeWithQualityHeaderValue($"application/json"));
var dData = $"{q}kdata test{q}";
var content = new StringContent(dData, System.Text.Encoding.UTF8, "application/json");
var response = await httpClient.PutAsync(${url}api/v1.0/KDataServer/setkdatainformation/{connectionId}/{headerLoginName}", content);
The status code 405 occurs when the request is sent in a net core 3.1 console app using httpClient.
I did a test based on the code snippet you shared, which work well on my side. If possible, you can try to create a new project and create controller with only this action method then test if it can work well.
var q = "\"";
var connectionId = 2;
var headerLoginName = "test";
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue($"application/json"));
var dData = $"{q}kdata test{q}";
var content = new StringContent(dData, System.Text.Encoding.UTF8, "application/json");
var response = await httpClient.PutAsync($"https://xxxx/setkdatainformation/{connectionId}/{headerLoginName}", content);
In Fiddler the request works fine
You mentioned the request could be processed fine if you make it via fiddler, to troubleshoot the issue, you can capture the request that you sent from console app using fiddler, then compare the request url, header(s) and body etc with that working one you sent through fiddler and make sure you are making request(s) to same endpoint from both fiddler and console app.

Calling Micro-service using WebClient Sprint 5 reactor web

I am calling a micro-service in my rest controller. It works fine when ever there is a successful response from the Micro-service but if there is some error response I fails to pass on the error response back to user. Below is the sample code.
#GetMapping("/{id}/users/all")
public Mono<Employee> findAllProfiles(#PathVariable("id") UUID organisationId,
#RequestHeader(name = "Authorization", required = false) String oauthJwt) {
return webClient.get().uri(prepareUrl("{id}/users/all"), organisationId)
.header("Authorization", oauthJwt).accept(MediaType.APPLICATION_JSON)
.exchange().then(response -> response.bodyToMono(Employee.class));
}
Now if there is any JSON response with error code then web client does not pass on the error response to the controller due to which no information is propagated to the api end user.
You should be able to chain methods from the Mono API. Look for "onError" to see a number of options which allow you to define the behavior when there is an error.
For example, if you wanted to return an "empty" Employee, you could do the following:
.exchange()
.then(response -> response.bodyToMono(Employee.class))
.onErrorReturn(new Employee());

Get "API key is missing" error when querying account details to Mailchimp API 3.0 using RestSharp

When using RestSharp to query account details in your MailChimp account I get a "401: unauthorized" with "API key is missing", even though it clearly isn't!
We're using the same method to create our RestClient with several different methods, and in all requests it is working flawlessly. However, when we're trying to request the account details, meaning the RestRequest URI is empty, we get this weird error and message.
Examples:
private static RestClient CreateApi3Client(string apikey)
{
var client = new RestClient("https://us2.api.mailchimp.com/3.0");
client.Authenticator = new HttpBasicAuthenticator(null, apiKey);
return client;
}
public void TestCases() {
var client = CreateApi3Client(_account.MailChimpApiKey);
var req1 = new RestRequest($"lists/{_account.MailChimpList}/webhooks", Method.GET);
var res1 = client.Execute(req1); // works perfectly
var req2 = new RestRequest($"automations/{account.MailChimpTriggerEmail}/emails", Method.GET);
var res2 = client.Execute(req2); // no problem
var req3 = new RestRequest(Method.GET);
var res3 = client.Execute(req3); // will give 401, api key missing
var req4 = new RestRequest(string.Empty, Method.GET);
var res4 = client.Execute(req4); // same here, 401
}
When trying the api call in Postman all is well. https://us2.api.mailchimp.com/3.0, GET with basic auth gives me all the account information and when debugging in c# all looks identical.
I'm trying to decide whether to point blame to a bug in either RestSharp or MailChimp API. Has anyone had a similar problem?
After several hours we finally found what was causing this..
When RestSharp is making the request to https://us2.api.mailchimp.com/3.0/ it's opting to omit the trailing '/'
(even if you specifically add this in the RestRequest, like: new RestRequest("/", Method.GET))
so the request was made to https://us2.api.mailchimp.com/3.0
This caused a serverside redirect to 'https://us2.api.mailchimp.com/3.0/' (with the trailing '/') and for some reason this redirect scrubbed away the authentication header.
So we tried making a
new RestRequest("/", Method.GET)
with some parameters (req.AddParameter("fields", "email")) to make it not scrub the trailing '/', but this to was failing.
The only way we were able to "fool" RestSharp was to write it a bit less sexy like:
new RestRequest("/?fields=email", Method.GET)

How to change Web Api Core unauthorized behavior

The default ASP.NET Web Api Core behaviour for unauthorized request is to send 401/403 error with empty content. I'd like to change it by specifying some kind of Json response specifying the error.
But I struggle to find a right place where I can introduce these changes. Official documentation is of no help (read it all). I had a guess that may be I could catch UnathorizedException in my exception filter / middleware but it didn't work out (I guess it gets handled at authorization level or even not thrown at all).
So my question is how can I customize response behavior in case of unauthorized request.
With .Net Core 3 (or may be earlier as well) you can write a middleware to check if the context.Response has a status of 40x and then return a custom object. Below is roughly how I did it:
if (context.Response.StatusCode == (int)HttpStatusCode.Unauthorized)
{
var result = new MyStandardApiResponseDto
{
Error = new MyErrorDto
{
Title = "Unauthorized",
Messages = new List<string> { "You are not authorized to access the resource. Please login again." },
},
Result = null
};
await context.Response.WriteAsync(JsonConvert.SerializeObject(result));
}

Resources