Reputation: 85
I have an API gateway that sends an appsettings file as a string, I update some keys in my UI and then I want to submit it back to the gateway to replace the settings on the server. I'm getting an error 415 Unsupported media type when I submit the JSON string back to the API.
Here is the endpoint
[HttpPost("{app}/set")] // POST /api/settings/{app}/set
public bool Set(string app, [FromBody] string content)
{
_logger.LogInformation($"recieved request on settings/{app}/set, id: {_requestId}");
var response = false;
try
{
System.IO.File.WriteAllText(GetAppSettingsPath(app), content, Encoding.UTF8);
_logger.LogInformation($"Completed request for requestId: {_requestId}");
response = true;
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error on requestId, {_requestId}");
}
return response;
}
And here is my client service
public ApiService(ILogger<ApiService> logger, IOptions<AppSettings> appsettings, HttpClient client)
{
_logger = logger;
_baseUri = new Uri(appsettings.Value.GatewayBaseURL);
client.DefaultRequestHeaders.Accept.Clear();
client.Timeout = Timeout.InfiniteTimeSpan;
_client = client;
}
public async Task<bool> SetAppSettings(string app, string content)
{
var response = false; //always fails by default
try
{
var httpRequest = new HttpRequestMessage { Method = HttpMethod.Post, RequestUri = new Uri(_baseUri, string.Concat("api/settings/", app, "/set")), Content = new StringContent(content, Encoding.UTF8) };
httpRequest.Headers.Add("content-type", "text/plain");
var httpResponse = await _client.SendAsync(httpRequest).ConfigureAwait(false);
httpResponse.EnsureSuccessStatusCode();
var responseBody = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
response = bool.TryParse(responseBody, out var parseValue) ? parseValue : false;
}
catch (Exception ex)
{
_logger.LogError(ex, $"Failed to set the settings for application, {app}");
}
return response;
}
I've read on some stack answer trying to fix this, but I'm not sure if I need to alter the endpoint, the client, the requestMessage or all of them. I'd also appreciate some guidance on which header to use and how to properly declare it. Most of these say to apply "application/json" but I'm not sure if that's right for my case. 1 2 3 4
Update I have altered my client to use a WebClient instead with the fllowing code. Now I am getting a 400 bad request instead of the 415 Unsupported Media Type error.
WebClient client = new WebClient();
client.Headers[HttpRequestHeader.ContentType] = "application/json";
var url = new Uri(_baseUri, string.Concat("api/settings/", app, "/set"));
var responseString = client.UploadString(url, "POST", content);
response = bool.TryParse(responseString, out var result) && result;
Upvotes: 0
Views: 2005
Reputation: 85
I figured it out. The media type I wanted to use for "text/plain" required different handling, and the parameter in the signature of the endpoint caused issues. This article helped.
Updated endpoint:
[HttpPost("{app}/set")] // POST /api/settings/{app}/set
public bool Set(string app)
{
string jsonString = null;
using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
{
jsonString = reader.ReadToEndAsync().Result;
}
System.IO.File.WriteAllText(GetAppSettingsPath(app), jsonString, Encoding.UTF8);
}
Updated client:
WebClient client = new WebClient();
client.Headers[HttpRequestHeader.ContentType] = "text/plain";
var url = new Uri(_baseUri, string.Concat("api/settings/", app, "/set"));
var responseString = client.UploadString(url, "POST", content);
response = bool.TryParse(responseString, out var result) && result;
Upvotes: 1