经过大量的反复试验,我找到了一个非常丑陋且完全不合逻辑的解决方案来解决我的问题。但是仍然......也许这篇文章可以帮助将来的人。请注意,此“解决方案”在 .NET 4.5 中适用于我。我不保证它会为你工作。
问题归结为:
- 在 .NET 中的 Uri 中放置转义的正斜杠是不可能的(AFAIK)
- 为了与外部服务(RabbitMQ)通信,我真的需要能够在我的请求 URL 中放入 %2f(即正斜杠)
以下帖子让我朝着“正确”的方向前进:如何停止 System.Uri 取消转义正斜杠字符
我尝试了帖子中提出的解决方案,但是...无济于事
然后经过大量的诅咒,谷歌搜索,逆向工程等等,我想出了以下代码:
/// <summary>
/// Client enpoint behavior that enables the use of a escaped forward slash between 2 forward slashes in a url
/// </summary>
public class EncodeForwardSlashBehavior:IEndpointBehavior
{
public void Validate(ServiceEndpoint endpoint)
{
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.ClientMessageInspectors.Add(new ForwardSlashUrlInspector());
}
}
/// <summary>
/// Inspector that modifies a an Url replacing /// with /%2f/
/// </summary>
public class ForwardSlashUrlInspector:IClientMessageInspector
{
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
string uriString = request.Headers.To.ToString().Replace("///", "/%2f/");
request.Headers.To = new Uri(uriString);
AddAllowAnyOtherHostFlagToHttpUriParser();
return null;
}
/// <summary>
/// This is one of the weirdest hacks I ever had to do, so no guarantees can be given to this working all possible scenarios
/// What this does is, it adds the AllowAnyOtherHost flag to the private field m_Flag on the UriParser for the http scheme.
/// Replacing /// with /%2f/ in the request.Headers.To uri BEFORE calling this method will make sure %2f remains unescaped in your Uri
/// Why does this work, I don't know!
/// </summary>
private void AddAllowAnyOtherHostFlagToHttpUriParser()
{
var getSyntaxMethod =
typeof(UriParser).GetMethod("GetSyntax", BindingFlags.Static | BindingFlags.NonPublic);
if (getSyntaxMethod == null)
{
throw new MissingMethodException("UriParser", "GetSyntax");
}
var uriParser = getSyntaxMethod.Invoke(null, new object[] { "http" });
var flagsField =
uriParser.GetType().BaseType.GetField("m_Flags", BindingFlags.Instance|BindingFlags.NonPublic);
if (flagsField == null)
{
throw new MissingFieldException("UriParser", "m_Flags");
}
int oldValue = (int)flagsField.GetValue(uriParser);
oldValue += 4096;
flagsField.SetValue(uriParser, oldValue);
}
public void AfterReceiveReply(ref Message reply, object correlationState)
{
}
}
所以基本上我正在创建一个自定义 EndpointBehavior,它使用反射将枚举标志添加到 UriParser 内的私有变量。这显然可以防止我的 request.Headers.To uri 中的转义正斜杠被转义。