禁用 URL 参数值中的等号编码
Disable URL Encoding of Equals sign in a Parameter Value
下面这段代码为 restful 网络服务调用创建了查询参数集合
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
事后没有进行重写,有没有办法防止这种情况发生?该服务没有 return 正确的结果集,因为它将 %3d 解释为需要过滤的内容。
我为解决此问题所做的工作如下。我只是不知道是否有办法首先防止这种情况。
string queryString = outgoingQueryString.ToString().Replace("%3d", "=");
我不知道有什么方法可以让 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);
}
下面这段代码为 restful 网络服务调用创建了查询参数集合
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
事后没有进行重写,有没有办法防止这种情况发生?该服务没有 return 正确的结果集,因为它将 %3d 解释为需要过滤的内容。
我为解决此问题所做的工作如下。我只是不知道是否有办法首先防止这种情况。
string queryString = outgoingQueryString.ToString().Replace("%3d", "=");
我不知道有什么方法可以让 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);
}