Reputation: 1068
I am trying to submit a request to a web API. I am coding a web API with Azure App Services using C#. This code does the request:
_objClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("basic", credential);
var multipartFormContent = new MultipartFormDataContent();
multipartFormContent.Add(new StringContent(product.Name), name: "name");
multipartFormContent.Add(new StringContent(product.Price), name: "price");
MemoryStream ms = new(product.catalogue);
var fileStreamContent = new StreamContent(ms);
fileStreamContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
multipartFormContent.Add(fileStreamContent, name: "content", fileName: product.Name);
var response = _objClient.PostAsync(_settings.UploadProductCatalogueUrl, multipartFormContent).GetAwaiter().GetResult();
Invoking the PostAsync method returns this error:
Exception message: The SSL connection could not be established, see inner exception.
Inner exception: The remote certificate is invalid because of errors in the certificate chain: UntrustedRoot.
Stack trace: at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, CancellationToken cancellationToken)\r\n at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n at System.Net.Http.HttpConnectionPool.AddHttp11ConnectionAsync(HttpRequestMessage request)\r\n at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellationAsync(CancellationToken cancellationToken)\r\n at System.Net.Http.HttpConnectionPool.GetHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)\r\n at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)\r\n at Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n at System.Net.Http.HttpClient.g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)\r\n at ProductCatalogue.UploadProductCatalogue(CatalogueDto catalogue)
It does work when running it locally, this only fails when deployed to Azure.
Upvotes: 0
Views: 1890
Reputation: 1068
What worked for me was to invoke the ConfigurePrimaryHttpMessageHandler for the HttpClient, and overload the ServerCertificateCustomValidationCallback method, to return true:
private static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpClient("ProductCatalogueClient",
client =>
{
client.BaseAddress = new Uri(builder.Configuration["Settings:productCatalogueUrl"]);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json));
}
)
.ConfigurePrimaryHttpMessageHandler(configure =>
new HttpClientHandler()
{
ServerCertificateCustomValidationCallback = (message, cert, chain, sslPolicyErrors) =>
{
return true;
}
});
Be aware this bypasses the certificate validation, in our case this was OK, but it might generate a security issue in your case.
Upvotes: 0