在参数值中禁用等号的URL编码

时间:2019-02-07 01:23:47

标签: c# namevaluecollection

我下面有这段代码,用于为宁静的Web服务调用创建查询参数集合

NameValueCollection outgoingQueryString = HttpUtility.ParseQueryString(String.Empty);
outgoingQueryString.Add("SessionID", _sessionId);
outgoingQueryString.Add("LoanNumberID", loanId.ToString());
outgoingQueryString.Add("Nonce", _nonce);
outgoingQueryString.Add("OtherParams", "Enable_Filter_Show_on_Action_Report=0");

问题在于,最后一个参数值Enable_Filter_Show_on_Action_Report = 0得到的是它的'='编码为%3d SessionID=319A561B6D&LoanNumberID=351591&Nonce=3262383361&OtherParams=Enable_Filter_Show_on_Action_Report%3d0

应该在什么时候

SessionID=319A561B6D&LoanNumberID=351591&Nonce=3262383361&OtherParams=Enable_Filter_Show_on_Action_Report=0

在没有办法防止这种情况发生之后,只需进行重写?该服务未返回正确的结果集,因为它将%3d解释为需要过滤的内容。

我为解决此问题所做的工作如下。我只是不知道是否有一种方法可以防止这种情况发生。

string queryString = outgoingQueryString.ToString().Replace("%3d", "=");

1 个答案:

答案 0 :(得分:1)

我不知道让NameValueCollection做你想要的事情的方法;您可能会遇到某种解决方法。

我确实在您的解决方法实施中看到了潜在的问题:

[Fact]
public void ProblemWithOriginalSolution()
{
    NameValueCollection outgoingQueryString = HttpUtility.ParseQueryString(String.Empty);
    outgoingQueryString.Add("Param1", "Value1");
    outgoingQueryString.Add("Param2", "Value2=Something"); // this '=' needs to remain URL-encoded
    outgoingQueryString.Add("OtherParams", "Enable_Filter_Show_on_Action_Report=0");

    var queryString = outgoingQueryString.ToString().Replace("%3d", "=");

    Assert.Contains("Value2=Something", queryString); // Passes, but not what we want
    Assert.Contains("Value2%3dSomething", queryString); // Actually what we want, but fails
}

这可能对您的需求无关紧要,但是如果有的话,我有两个建议。

首先是仅使用字符串连接。根据您的使用情况,这可能需要额外的逻辑来处理OtherParams是唯一查询字符串参数的情况(在这种情况下,与号应省略)。字符串串联也是一个坏主意,OtherParams可能包含需要URL编码的字符。

[Fact]
public void Concatentation()
{
    NameValueCollection outgoingQueryString = HttpUtility.ParseQueryString(String.Empty);
    outgoingQueryString.Add("Param1", "Value1");

    var queryString = outgoingQueryString.ToString() + "&OtherParams=Enable_Filter_Show_on_Action_Report=0";

    Assert.Contains("&OtherParams=Enable_Filter_Show_on_Action_Report=0", queryString);
}

第二个是进行双重替换。这有点笨拙,效率不高,但应该可靠。

[Fact]
public void DoubleSubstitution()
{
    // Make sure the placeholder doesn't have any characters that will get URL encoded!
    // Also make sure it's not something that could appear in your input.
    const string equalsPlaceholder = "__Equals__";

    NameValueCollection outgoingQueryString = HttpUtility.ParseQueryString(String.Empty);
    outgoingQueryString.Add("Param1", "Value1");

    // First, remove the equals signs from the OtherParams value
    outgoingQueryString.Add("OtherParams", "Enable_Filter_Show_on_Action_Report=0".Replace("=", equalsPlaceholder));

    // Then, build the query string, and substitute the equals signs back in
    var queryString = outgoingQueryString.ToString().Replace(equalsPlaceholder, "=");

    Assert.Contains("&OtherParams=Enable_Filter_Show_on_Action_Report=0", queryString);
}