Se eu desejar enviar uma solicitação de obtenção http usando System.Net.HttpClient, parece não haver API para adicionar parâmetros, isso está correto?
Existe alguma API simples disponível para criar a string de consulta que não envolva a criação de uma coleção de valores de nomes e URLs que codifiquem esses itens e, finalmente, concatená-los? Eu esperava usar algo como a API do RestSharp (por exemplo, AddParameter (..))
Respostas:
Sim.
Certo:
lhe dará o resultado esperado:
Você também pode achar
UriBuilder
útil a classe:lhe dará o resultado esperado:
que você poderia alimentar com mais segurança o seu
HttpClient.GetAsync
método.fonte
#
) para você usar a propriedade Fragment. Eu já vi tantas pessoas cometendo o erro de manipular manualmente os URLs em vez de usar as ferramentas internas.NameValueCollection.ToString()
normalmente não cria seqüências de caracteres de consulta, e não há documentação declarando que fazer umToString
no resultado deParseQueryString
resultará em uma nova sequência de caracteres de consulta, portanto, pode ser interrompida a qualquer momento, pois não há garantia nessa funcionalidade.Para aqueles que não desejam incluir
System.Web
em projetos que ainda não o utilizam, você pode usar aFormUrlEncodedContent
partir deSystem.Net.Http
e fazer algo como o seguinte:keyvaluepair version
versão do dicionário
fonte
dispose
? Eu sempre descarto a menos que tenha um bom motivo para não fazê-lo, como reutilizarHttpClient
.TL; DR: não use a versão aceita, pois está completamente corrompida em relação ao tratamento de caracteres unicode e nunca use a API interna
Na verdade, eu encontrei um problema estranho de codificação dupla com a solução aceita:
Portanto, se você estiver lidando com caracteres que precisam ser codificados, a solução aceita levará à codificação dupla:
NameValueCollection
indexador ( e isso usaUrlEncodeUnicode
, não o esperado regularmenteUrlEncode
(!) )uriBuilder.Uri
, cria um novoUri
construtor usando, que codifica mais uma vez (codificação de URL normal)uriBuilder.ToString()
(mesmo que isso retorne correto,Uri
qual IMO é pelo menos inconsistente, talvez um bug, mas essa é outra questão) e, em seguida, usando oHttpClient
método de aceitação de string - o cliente ainda criaUri
sua string passada da seguinte maneira:new Uri(uri, UriKind.RelativeOrAbsolute)
Repro pequeno, mas completo:
Resultado:
Como você pode ver, não importa se você faz
uribuilder.ToString()
+httpClient.GetStringAsync(string)
ouuriBuilder.Uri
+httpClient.GetStringAsync(Uri)
você acaba enviando parâmetro codificado duploExemplo fixo pode ser:
Mas isso usa construtor obsoleto
Uri
PS no meu .NET mais recente no Windows Server,
Uri
construtor com comentário bool doc diz "obsoleto, o dontEscape é sempre falso", mas realmente funciona conforme o esperado (ignora a fuga)Então parece outro bug ...
E mesmo isso está completamente errado - ele envia UrlEncodedUnicode para o servidor, não apenas UrlEncoded o que o servidor espera
Atualização: mais uma coisa é que NameValueCollection realmente faz UrlEncodeUnicode, que não deve mais ser usado e é incompatível com url.encode / decode regular (consulte NameValueCollection to URL Query? ).
Portanto, o ponto principal é: nunca use esse hack,
NameValueCollection query = HttpUtility.ParseQueryString(builder.Query);
pois isso interferirá nos parâmetros de consulta unicode. Basta criar a consulta manualmente e atribuí-la àUriBuilder.Query
codificação necessária e, em seguida, obter o UriUriBuilder.Uri
.Exemplo excelente de se machucar usando código que não deve ser usado assim
fonte
var namedValues = HttpUtility.ParseQueryString(builder.Query)
, mas, em vez de usar o NameValueCollection retornado, converta-o imediatamente em um Dicionário da seguinte forma:var dic = values.ToDictionary(x => x, x => values[x]);
Adicione novos valores ao dicionário, passe-o para o construtorFormUrlEncodedContent
e ligueReadAsStringAsync().Result
-o. Isso fornece uma string de consulta codificada corretamente, que você pode atribuir de volta ao UriBuilder.<add key="aspnet:DontUsePercentUUrlEncoding" value="true" />
. Como eu não dependeria desse comportamento, é melhor usar a classe FormUrlEncodedContent, como demonstrado por uma resposta anterior: stackoverflow.com/a/26744471/88409Em um projeto ASP.NET Core, você pode usar a classe QueryHelpers.
fonte
Você pode conferir o Flurl [divulgação: sou o autor], um construtor de URLs fluente com lib complementar opcional que o estende a um cliente REST completo.
Confira os documentos para mais detalhes. O pacote completo está disponível no NuGet:
PM> Install-Package Flurl.Http
ou apenas o construtor de URL independente:
PM> Install-Package Flurl
fonte
Uri
ou começar com sua própria classe em vez destring
?Url
classe. O acima é equivalente anew Url("https://api.com").AppendPathSegment...
Pessoalmente, prefiro as extensões de string devido a menos pressionamentos de tecla e padronizadas nos documentos, mas você pode fazê-lo de qualquer maneira.Na mesma linha da postagem de Rostov, se você não deseja incluir uma referência
System.Web
em seu projeto, pode usar aFormDataCollection
partir deSystem.Net.Http.Formatting
e fazer algo como o seguinte:Usando
System.Net.Http.Formatting.FormDataCollection
fonte
Darin ofereceu uma solução interessante e inteligente, e aqui está algo que pode ser outra opção:
e, portanto, ao usá-lo, você pode fazer o seguinte:
fonte
kvp.Key
ekvp.Value
separadamente dentro do loop for, não na string de consulta completa (portanto, não codificando os caracteres&
e=
).server.UrlEncode
pode ser substituído porWebUtility.UrlEncode
Ou simplesmente usando minha extensão Uri
Código
Uso
Resultado
fonte
A biblioteca de modelos de URI RFC 6570 que estou desenvolvendo é capaz de executar esta operação. Toda a codificação é manipulada para você de acordo com essa RFC. No momento da redação deste artigo, uma versão beta está disponível e a única razão pela qual não é considerada uma versão 1.0 estável é que a documentação não atende totalmente às minhas expectativas (consulte as edições 17 , 18 , 32 e 43 ).
Você pode criar uma string de consulta sozinha:
Ou você pode criar um URI completo:
fonte
Como tenho que reutilizar esse período de tempo, criei essa classe que simplesmente ajuda a abstrair como a string de consulta é composta.
O uso será simplificado para algo como isto:
que retornará a URL : http://example.com/?foo=bar%3c%3e%26-baz&bar=second
fonte
Para evitar o problema de codificação dupla descrito na resposta do taras.roshko e manter a possibilidade de trabalhar facilmente com os parâmetros de consulta, você pode usar em
uriBuilder.Uri.ParseQueryString()
vez deHttpUtility.ParseQueryString()
.fonte
Boa parte da resposta aceita foi modificada para usar UriBuilder.Uri.ParseQueryString () em vez de HttpUtility.ParseQueryString ():
fonte
ParseQueryString()
método de extensão não está dentroSystem
.Graças a "Darin Dimitrov", este é o método de extensão.
fonte
Não consegui encontrar uma solução melhor do que criar um método de extensão para converter um Dicionário em QueryStringFormat. A solução proposta por Waleed AK também é boa.
Siga minha solução:
Crie o método de extensão:
E eles:
fonte