Uma tarefa comum ao chamar recursos da Web a partir de um código é criar uma sequência de consultas para incluir todos os parâmetros necessários. Embora, por todos os meios, não exista ciência de foguetes, há alguns detalhes bacanas que você precisa cuidar, acrescentando um &
se não o primeiro parâmetro, codificando os parâmetros etc.
O código para fazer isso é muito simples, mas um pouco tedioso:
StringBuilder SB = new StringBuilder();
if (NeedsToAddParameter A)
{
SB.Append("A="); SB.Append(HttpUtility.UrlEncode("TheValueOfA"));
}
if (NeedsToAddParameter B)
{
if (SB.Length>0) SB.Append("&");
SB.Append("B="); SB.Append(HttpUtility.UrlEncode("TheValueOfB")); }
}
Essa é uma tarefa tão comum que se espera que exista uma classe de utilidade que a torne mais elegante e legível. Ao digitalizar o MSDN, não encontrei um - o que me leva à seguinte pergunta:
Qual é a maneira mais elegante e limpa de saber o que foi dito acima?
c#
.net
url
query-string
Boaz
fonte
fonte
Respostas:
Se você olhar por baixo do capô, a propriedade QueryString é uma NameValueCollection. Quando eu faço coisas semelhantes, geralmente me interesso em serializar E desserializar, então minha sugestão é criar uma NameValueCollection e passar para:
Eu imagino que há uma maneira super elegante de fazer isso no LINQ também ...
fonte
application/x-www-form-urlencoded
e é realmente definido pelo HTML, com a finalidade de enviar dados do formulário como parte de umaGET
solicitação. O HTML 5 não proíbe vários valores por chave nesse formato e, de fato, exige que o navegador produza vários valores por chave, caso a página (incorretamente) contenha vários campos com o mesmoname
atributo. Veja goo.gl/uk1AgVocê pode criar uma nova instância gravável
HttpValueCollection
chamandoSystem.Web.HttpUtility.ParseQueryString(string.Empty)
e usá-la como qualquer outraNameValueCollection
. Depois de adicionar os valores desejados, você pode chamarToString
a coleção para obter uma sequência de consultas, da seguinte maneira:O
HttpValueCollection
é interno e, portanto, você não pode construir diretamente uma instância. No entanto, depois de obter uma instância, você pode usá-la como qualquer outraNameValueCollection
. Como o objeto real com o qual você está trabalhando é umHttpValueCollection
, chamar o método ToString chamará o método substituídoHttpValueCollection
, que formata a coleção como uma sequência de consulta codificada em URL.Depois de pesquisar na SO e na Web por uma resposta para um problema semelhante, esta é a solução mais simples que encontrei.
.NET Core
Se você estiver trabalhando no .NET Core, poderá usar a
Microsoft.AspNetCore.WebUtilities.QueryHelpers
classe, o que simplifica bastante isso.https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.webutilities.queryhelpers
Código de amostra:
fonte
public static string ToURLQueryString(this IDictionary dict) { ... }
Add
método Ou seja,queryString.Add("type", "1"); queryString.Add("type", "2");
usar oAdd
método é provavelmente a melhor maneira de fazer isso o tempo todo, na verdade.Com a inspiração do comentário de Roy Tinker, acabei usando um método de extensão simples na classe Uri que mantém meu código conciso e limpo:
Uso:
Editar - Variante compatível com padrões
Como várias pessoas apontaram,
httpValueCollection.ToString()
codifica caracteres Unicode de uma maneira não compatível com os padrões . Essa é uma variante do mesmo método de extensão que lida com esses caracteres, invocando oHttpUtility.UrlEncode
método em vez doHttpUtility.UrlEncodeUnicode
método obsoleto .fonte
Eu respondi uma pergunta semelhante há um tempo atrás. Basicamente, a melhor maneira seria usar a classe
HttpValueCollection
, que éRequest.QueryString
realmente a propriedade do ASP.NET , infelizmente ela é interna na estrutura do .NET. Você pode usar o Reflector para agarrá-lo (e colocá-lo na sua classe Utils). Dessa forma, você pode manipular a sequência de consultas como um NameValueCollection, mas com todos os problemas de codificação / decodificação de URL atendidos.HttpValueCollection
estendeNameValueCollection
e possui um construtor que utiliza uma sequência de consulta codificada (e comercial e pontos de interrogação incluídos) e substitui umToString()
método para reconstruir posteriormente a sequência de consultas da coleção subjacente.Exemplo:
fonte
httpValueCollection.ToString()
na verdade chama,httpValueCollection.ToString(true)
portanto,true
não é necessário adicionar explicitamente.Aqui está uma maneira fluente / lambda-ish como um método de extensão (combinando conceitos em postagens anteriores) que suporta vários valores para a mesma chave. Minha preferência pessoal é extensões sobre invólucros para a capacidade de descoberta por outros membros da equipe para coisas como esta. Observe que há controvérsia quanto aos métodos de codificação, muitas postagens sobre isso no Stack Overflow (uma dessas postagens ) e blogueiros do MSDN (como esta ).
edit: com suporte nulo, embora você provavelmente precise adaptá-lo para sua situação específica
fonte
Flurl [divulgação: eu sou o autor] suporta a construção de cadeias de consulta por meio de objetos anônimos (entre outras maneiras):
A lib complementar opcional Flurl.Http permite fazer chamadas HTTP diretamente da mesma cadeia de chamadas fluente, estendendo-a para um cliente REST completo:
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
Aqui está minha entrada tardia. Eu não gostei de nenhum dos outros por várias razões, então escrevi o meu.
Esta versão possui:
Uso apenas de StringBuilder. Nenhuma chamada ToArray () ou outros métodos de extensão. Não parece tão bonito quanto algumas das outras respostas, mas considero essa uma função essencial, portanto a eficiência é mais importante do que ter um código "fluente" e "uma linha" que oculte ineficiências.
Manipula vários valores por chave. (Não precisava disso sozinho, mas apenas para silenciar Mauricio;)
Exemplo de uso
Resultado
fonte
Que tal criar métodos de extensão que permitam adicionar os parâmetros em um estilo fluente como este?
Aqui está a sobrecarga que usa um
string
:E aqui está a sobrecarga que usa um
StringBuilder
:fonte
NameValueCollection
,HttpValueCollection
ou umUri
em primeiro lugar. Obrigado!Eu precisava resolver o mesmo problema para uma biblioteca de classes portátil (PCL) em que estou trabalhando. Nesse caso, não tenho acesso ao System.Web, portanto não posso usar ParseQueryString.
Em vez disso, usei
System.Net.Http.FormUrlEncodedContent
assim:fonte
fonte
.ToArray()
s.Adicione esta classe ao seu projeto
E use-o assim:
fonte
Minha oferta:
Uso:
fonte
Não testado, mas acho que algo nesse sentido funcionaria muito bem
fonte
Uma versão baseada no método de extensão rápida:
Você pode usar uma cláusula where para selecionar quais parâmetros serão adicionados à string.
fonte
Supondo que você queira reduzir dependências para outros assemblies e manter as coisas simples, você pode:
Isso funciona bem com loops também. A remoção final do e comercial precisa sair do loop.
Observe que o operador de concatenação é usado para melhorar a legibilidade. O custo de usá-lo em comparação com o custo de um StringBuilder é mínimo (acho que Jeff Atwood postou algo sobre este tópico).
fonte
Combinou as principais respostas para criar uma versão anônima do objeto :
Isso gera isso:
Aqui está o código:
fonte
O mesmo que a solução aceita, mas transfere para a sintaxe LINQ "ponto" ...
fonte
Eu tenho um método de extensão para Uri que:
uri.WithQuery(new { name = "value" })
string/string
pares (por exemplo, Dictionary`2 ).string/object
pares (por exemplo, RouteValueDictionary ).A versão documentada pode ser encontrada aqui .
A extensão:
O analisador de consultas:
Aqui estão os testes:
fonte
Classe de wrapper capaz de cadeia para HttpValueCollection:
Exemplo de uso:
fonte
Eu adicionei o seguinte método à minha classe PageBase.
Chamar:
fonte
Eu escrevi alguns métodos de extensão que achei muito úteis ao trabalhar com QueryStrings. Freqüentemente, quero começar com o QueryString atual e modificar antes de usá-lo. Algo como,
Para mais informações e a fonte: http://www.charlesrcook.com/archive/2008/07/23/c-extension-methods-for-asp.net-query-string-operations.aspx
É básico, mas eu gosto do estilo.
fonte
Só queria jogar meus 2 centavos:
Os documentos dizem que
uri.Query
começará com um?
se não estiver vazio e você deve cortá-lo se quiser modificá-lo.Observe que
HttpUtility.UrlEncode
é encontrado emSystem.Web
.Uso:
fonte
Embora não seja elegante, optei por uma versão mais simples que não usa
NameValueCollecitons
- apenas um padrão de construtorStringBuilder
.Pelas respostas existentes, certifiquei-me de usar as
HttpUtility.UrlEncode
chamadas. É usado assim:fonte
Resultado:
O código; todos vocês podem me agradecer em algum lugar, de alguma forma: D
fonte
Fui com a solução proposta pelo DSO (respondida em 2 de agosto de 11 às 7:29), sua solução não requer o uso de HttpUtility. No entanto, de acordo com um artigo publicado no Dotnetpearls , o uso de um dicionário é mais rápido (em desempenho) do que o uso de NameValueCollection. Aqui está a solução do DSO modificada para usar o Dicionário no lugar de NameValueCollection.
fonte
A cadeia de consulta pode ser adicionada a um URL por:
https://blog.codingnovice.com/blog
fonte
Eu escrevi um ajudante para o meu projeto de barbear usando algumas dicas de outras respostas.
O negócio ParseQueryString é necessário porque não temos permissão para violar o objeto QueryString da solicitação atual.
Eu uso assim:
Se você deseja que ele use mais de um valor, basta alterar os parâmetros para um Dicionário e adicionar os pares à string de consulta.
fonte
O código abaixo é retirado da
HttpValueCollection
implementaçãoToString
, via ILSpy, que fornece uma string de consulta name = value.Infelizmente, HttpValueCollection é uma classe interna que você só recebe de volta se usar
HttpUtility.ParseQueryString()
. Eu removi todas as partes do viewstate e ele codifica por padrão:fonte
É o mesmo que a resposta aceita, exceto um pouco mais compacta:
fonte
Apenas para aqueles que precisam da versão VB.NET da resposta principal:
E a versão sem LINQ:
E a versão C # sem LINQ:
fonte