2013-04-23 4 views
2

Представьте, что я хочу вызвать внешний (что означает, что у меня нет контроля над контрактом) Служба REST с использованием WCF. У меня есть следующий контракт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 параметр пути?

+0

Возможный дубликат [Как передать символы слэш и другие символы с URL-адресами в службу WCF REST?] (Http://stackoverflow.com/questions/7176726/how-can-i-pass-slash-and -other-url-sensitive-characters-to-a-wcf-rest-service) –

+0

Ответ в связанном вопросе не является допустимым ответом на этот вопрос, так как я не контролирую внешнюю службу, которая вызывается, поэтому изменение uritemplate в контракте на обслуживание невозможно. Я изменил свой вопрос, чтобы отразить это ограничение. – Stif

ответ

0

С большим количеством проб и ошибок я нашел очень уродливое и абсолютно нелогичное решение моей проблемы. Но все же ... Может быть, этот пост может помочь кому-то в будущем. Обратите внимание, что это «решение» работает для меня в .NET 4.5. Я не гарантирую, что это сработает для вас.

Проблема сводится к следующему:

  • это невозможно (AFAIK), чтобы положить бежал косую черту в Ури в .NET
  • для связи с внешним обслуживанием (RabbitMQ) Мне действительно нужно быть в состоянии поместить% 2f (т.е. вперед слэш) в моем URL запроса

следующий пост поставил меня в «правильном» направлении: How to stop System.Uri un-escaping forward slash characters

I Пытался решение, предложенное в этой должности, но ... не дали никаких результатов

Тогда после того, как много ругательств, прибегая к помощи, инженерные и так далее я придумал следующий фрагмент кода:

/// <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, которая использует отражение, чтобы добавить флаг enum в приватную переменную внутри UriParser. Это, по-видимому, предотвращает сбежавшую косую черту в моем запросе. Хозяева. Чтобы ури не был скрыт.

+0

По-прежнему можно отключить символы. См. Связанный ответ. –

Смежные вопросы