Найти соответствующий OperationContract на основе URI - PullRequest
0 голосов
/ 15 июня 2011

... или «Как определить, какой метод WCF будет вызываться на основе URI?»

Предположим, что в службе WCF вызывается метод, и у меня есть URI, который использовался для его вызова. Как я могу получить информацию о конечной точке WCF, методе, параметрах и т. Д., На который отображается URI?

[OperationContract]
[WebGet(UriTemplate = "/People/{id}")]
public Person GetPersonByID(int id)
{
    //...
}

Например, если URI: GET <a href="http://localhost/Contacts.svc/People/1" rel="nofollow">http://localhost/Contacts.svc/People/1</a>, я хочу получить эту информацию: имя службы (Service), метод (GetPersonByID), Parameters (PersonID = 1). Суть в том, чтобы иметь возможность прослушивать запрос и затем извлекать детали запроса для отслеживания вызова API.

Сервис размещен через http. Эта информация требуется до того, как включится кэширование .Net, чтобы можно было отслеживать каждый вызов (независимо от того, кэшируется он или нет). Это, вероятно, означает делать это внутри HttpApplication.BeginRequest.

К вашему сведению, я надеюсь не использовать отражение. Я хотел бы использовать те же методы, которые использует WCF, чтобы определить это. Например. MagicEndPointFinder.Resolve(uri)

1 Ответ

0 голосов
/ 16 июня 2011

Вот что я в итоге сделал, все еще заинтересованный, если есть более чистый путь!

REST

private static class OperationContractResolver
{
    private static readonly Dictionary<string, MethodInfo> RegularExpressionsByMethod = null;

    static OperationContractResolver()
    {
    OperationContractResolver.RegularExpressionsByMethod = new Dictionary<string, MethodInfo>();

    foreach (MethodInfo method in typeof(IREST).GetMethods())
    {
        WebGetAttribute attribute = (WebGetAttribute)method.GetCustomAttributes(typeof(WebGetAttribute), false).FirstOrDefault();

        if (attribute != null)
        {
        string regex = attribute.UriTemplate;

        //Escape question marks. Looks strange but replaces a literal "?" with "\?".
        regex = Regex.Replace(regex, @"\?", @"\?");

        //Replace all parameters.
        regex = Regex.Replace(regex, @"\{[^/$\?]+?}", @"[^/$\?]+?");

        //Add it to the dictionary.
        OperationContractResolver.RegularExpressionsByMethod.Add(regex, method);
        }
    }
    }

    public static string ExtractApiCallInfo(string relativeUri)
    {
    foreach (string regex in OperationContractResolver.RegularExpressionsByMethod.Keys)
        if (Regex.IsMatch(relativeUri, regex, RegexOptions.IgnoreCase))
        return OperationContractResolver.RegularExpressionsByMethod[regex].Name;

    return null;
    }
}

SOAP

private static void TrackSoapApiCallInfo(HttpContext context)
{
    string filePath = Path.GetTempFileName();
    string title = null;

    //Save the request content. (Unfortunately it can't be written to a stream directly.)
    context.Request.SaveAs(filePath, false);

    //If the title can't be extracted then it's not an API method call, ignore it.
    try
    {
    //Read the name of the first element within the SOAP body.
    using (XmlReader reader = XmlReader.Create(filePath))
    {
        if (!reader.EOF)
        {
        XmlNamespaceManager nsManager = new XmlNamespaceManager(reader.NameTable);
        XDocument document = XDocument.Load(reader);

        //Need to add the SOAP Envelope namespace to the name table.
        nsManager.AddNamespace("s", "http://schemas.xmlsoap.org/soap/envelope/");
        title = document.XPathSelectElement("s:Envelope/s:Body", nsManager).Elements().First().Name.LocalName;
        }
    }

    //Delete the temporary file.
    File.Delete(filePath);
    }
    catch { }

    //Track the page view.
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...