Как изменить Content-Type во Flurl?

У меня есть приложение.NET Core 2.0 WebApi, в которое я добавил пакет NuGet "Flurl.Http" (версия 2.1.0) в мой проект.

Я пытаюсь использовать Flurl, чтобы сделать простой вызов REST API для одной из конечных точек Api Visual Studio Team Services (VSTS).

Однако конкретная конечная точка API VSTS, которую я вызываю, требует, чтобы тип контента был установлен на "application/json-patch+json" вместо типичного "application/json".

В моем вызове Flurl я использую метод WithHeader(), чтобы попытаться установить Content-Type в заголовке запроса, но он не работает. Flurl, похоже, не позволяет мне переопределить стандартный или стандартный Content-Type, встроенный в метод PostJsonAsync.

Кто-нибудь знает, как изменить Content-Type запроса с помощью Flurl? Или как правильно переопределить поведение по умолчанию для Content-Type в конфигурации Flurl?

Заранее спасибо!

Мой код:

public bool CreateNewBug(NewBugRequest newBugRequest)
{
    return _apiUrlToCreateNewBug.WithHeader("Authorization", "Basic Base64PersonalAccessTokenGoesHere")
                                .WithHeader("Content-Type", "application/json-patch+json")
                                .PostJsonAsync(newBugRequest.Fields)
                                .Result
                                .IsSuccessStatusCode;
}

(Этот код работает, но ответ от API VSTS заключается в том, что Content-Type недопустим и его необходимо изменить на "application/json-patch+json", что я и попытался установить в заголовке.)

3 ответа

Решение

ОБНОВЛЕНИЕ: ошибка исправлена ​​с Flurl.Http 2.3.1, поэтому этот обходной путь больше не требуется.

Короткий ответ: я думаю, что вы обнаружили ошибку. PostJsonAsync действительно устанавливает заголовок Content-Type, но я думаю, что он должен оставить его в покое, если вы уже установили его самостоятельно. Если бы вы могли сообщить об этом здесь, я бы смог исправить это в следующем выпуске.

Обходной путь довольно прост. Вам просто нужно сделать пару дополнительных шагов, чтобы создать контент, а затем опубликовать его, используя PostAsync вместо PostJsonAsync,

var json = FlurlHttp.GlobalSettings.JsonSerializer.Serialize(newBugRequest.Fields);
var content = new CapturedStringContent(json, Encoding.UTF8, "application/json-patch+json");

return _apiUrlToCreateNewBug
    .WithHeader("Authorization", "Basic Base64PersonalAccessTokenGoesHere")
    .PostAsync(content);

Если вам нужно сделать это много, вы можете заключить это в метод расширения (PostJsonPatchAsync или аналогичный), так что вы можете назвать это свободно. Смотрите здесь для правильного способа сделать это.

Новый ответ: Обновление до последней версии Flurl.Http. Эта проблема была исправлена ​​в 2.3.1, поэтому код, размещенный в вопросе (самый чистый подход), теперь должен работать так, как ожидалось.

Я смог понять это и найти рабочее решение моей проблемы.

Вот обновленная версия моего рабочего кода:

public HttpResponseMessage CreateNewBug(NewBugRequest newBugRequest)
{
    return _apiUrlToCreateNewBug.AllowAnyHttpStatus()
                                .WithBasicAuth("", _personalAccessTokenForBasicAuth)
                                .PostAsync(new StringContent(JsonConvert.SerializeObject(newBugRequest.Fields), Encoding.UTF8, "application/json-patch+json"))
                                .Result;
}

Метод PostAsync принимает объект HttpContent. HttpContent - абстрактный класс. Как только я выяснил все конкретные классы, которые реализуют абстрактный класс HttpContent, я выбрал тот, который лучше всего подходит для моей ситуации, и подключил его к методу PostAsync.

В этом случае класс StringContent лучше всего подходил мне. Один из конструкторов StringContent принимает Content-Type в качестве одного из своих параметров. Так что я передал свой собственный Content-Type, и все заработало, как и ожидалось.

Другие вопросы по тегам