WCF UriTemplate UrlEncode
问题描述:
想象一下,我想使用WCF调用外部(意味着我无法控制合同)REST服务。 我有以下的合同WCF UriTemplate UrlEncode
[ServiceContract]
public interface ISomeRestApi
{
[OperationContract]
[WebInvoke(Method = "PUT", UriTemplate = "blablabla/{parameter1}/{parameter2}")]
void PutSomething(string parameter1, string parameter2);
}
再说说我的参数之一是正斜杠(/)
public class Test{
[Fact]
public void TestPutSomething()
{
ISomeRestApi api = CreateApi();
//this results in the url: http://server/blablabla///someotherparam
api.PutSomething("/", "someotherparam");
//this also results in the url: http://server/blablabla///someotherparam
api.PutSomething(HttpUtility.UrlEncode("/"), "someotherparam");
//but i want: http://server/blablabla/%2F/someotherparam
}
}
如何强制WCF来urlencode我UriTemplate路径参数?
答
随着大量的试验和错误,我发现了一个非常丑陋,完全不合逻辑的解决方案,我的问题。但仍然...也许这篇文章可以帮助未来的人。 请注意,这个“解决方案”适用于.NET 4.5。我不保证它会为你工作。
的问题归结为:
- 这是不可能的(据我所知)把一个转义正斜杠在乌里在.NET
- 与外部服务(RabbitMQ的)通信我真的需要能够认沽%2F(即正斜杠)在我的请求URL
下后把我的“正确”方向:How to stop System.Uri un-escaping forward slash characters
我试着在后提出的解决方案,但是......无济于事
然后很多咒骂后,谷歌搜索,逆向工程等我想出了下面的一段代码:
/// <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中的私有变量添加一个枚举标志。这显然可以防止我的请求中逃脱的正斜杠。头部。让你不被转义。
+0
它仍然可以避开字符。看到链接的答案。 – 2016-02-16 18:31:15
可能的重复[如何将斜杠和其他'url敏感'字符传递给WCF REST服务?](http://*.com/questions/7176726/how-can-i-pass-slash-and -other-url-sensitive-characters-to-a-wcf-rest-service) – 2016-02-04 18:48:48
由于我无法控制被调用的外部服务,因此链接问题中的答案并非此问题的有效答案,因此更改服务合同中的uritemplate是不可能的。我修改了我的问题以反映这个约束。 – Stif 2016-03-12 16:53:16