среда, 22 июня 2016 г.

Получение значения вложенного XElement-а.

[Getting the value of a nested XElement]

Допустим у нас есть следующий документ:

XDocument xDoc = XDocument.Parse(@"<Data> <X> <Y> <Z>Здесь!</Z> </Y> </X> </Data>");

Получение значения XElementa  „Z“ достаточно тривиальная задача:

String value = xDoc.Root.Element("X").Element("Y").Element("Z").Value;

Но задача усложняется, если нужно значение одного из вложенных элементов где цепочка вложенности узлов, хоть и известна, но может обрываться в любом месте. Тогда понадобится проверять каждый из под-узлов на существование.  
Получается очень громоздко.

Что бы получить значение «в один вызов», можно воспользоваться методами расширениями:

public static String xValueOrNull (this XElement xEl) {
if (xEl == null) return null;
else return xEl.Value;
}
public static XElement xElementOrNull(this XElement root, String elemName) {
if (root == null) return null;
return root.Element(elemName);
}  
Тогда вызов будет примерно таким:

String val = xDoc.Root.xElementOrNull("X").xElementOrNull("Y").xElementOrNull("Z").xValueOrNull();

Недостатком такого способа является то, что если в самом начале цепочки узел не существует, проверка все равно продолжится и для следующих узлов.
Другим решением может быть использование вспомогательных методов расширений, которые бы обрывали вызов, например такого:

public static String xFuncValueOrNull(this XElement xEl, String elemName, Func<XElement, String> func) {
if (xEl == null) return null;
XElement subEl = xEl.Element(elemName);
if (subEl == null) return null;
return func(subEl);
}

И вызов:

String val = xDoc.Root.xFuncValueOrNull("X", x => x.xFuncValueOrNull("Y", y => y.xFuncValueOrNull("Z", z => x.Value)));

вторник, 16 февраля 2016 г.

Использование XING API из c# (.NET)

[Using the XING API in c # (.NET)]

Далее представлен пример работы с XING-API из десктопного приложения (WinForms).
Документация по XING-API:https://dev.xing.com/docs/resources.

Итак, для начала использования API необходимо прежде всего получить ключ и секретное слово на следующей страничке: https://dev.xing.com/applications.

Использование API предполагает придерживания специального протокола OAuth (https://dev.xing.com/docs/authentication). Как это делается можно увидеть в коде. Особенностью десктопного приложения является то, что верификация пользователя выполняется “вручную” - пользователь должен передать в приложение специальный код, который отображается после его авторизации в браузере. В веб-приложении этот код можно вычитать из возвращаемых параметров запроса программно.

Ресурсы, которые я использовал:

  • .Net SDK for XING API

https://netforxing.codeplex.com/ (странная реализация, но подсмотрел как использовать DotNetOpenAuth)

  • Wie man die XING-API nutzt (на немецком, описан процесс использования OAuth в XING)

http://www.heise.de/ix/artikel/Sozial-integriert-1892413.html

  • API Explorer für die XING REST-API (программа для тестирования API)

https://www.cybertribe.de/druid/de/ApiExplorer


В приложении понадобятся следующие пакеты библиотек:

DotNetOpenAuth OAuth 1.0(a) Consumer:


и RestSharp:

Диалог ввода использовал из сборки "Microsoft.VisualBasic".

Интерфейс приложения:

По нажатию на кнопку "Login" (button1_Click) выводится URL, который необходимо ввести в браузере для авторизации пользователя и получения кода верификации. Этот код необходимо ввести в последующем диалоге ввода. После логина можно вызывать методы API, например получение информации о пользователе - кнопка "Get Data" (button2_Click).


Итак, код:

public partial class Form1 : Form
{
    public Form1() {
        InitializeComponent();
    }

    String consumerKey = "<your key>";
    String consumerSecret = "<your secret>";

    String access_token = null;
    String access_token_secret = null;

    String verifyPIN = null;

    private void button1_Click(object sender, EventArgs e) {
           
        A();
        B();

        verifyPIN = Microsoft.VisualBasic.Interaction.InputBox("PIN: ",
                    "Input Data",
                    "", 0, 0);

        C();
    }

    private void button2_Click(object sender, EventArgs e) {

        String userID = Microsoft.VisualBasic.Interaction.InputBox("User ID",
                    "Input Data",
                    "me", 0, 0);

        D(userID);
    }

    // -----------------
    // -----------------

    // Get Authorization Token
    void A() {
        RestClient client = new RestClient("https://api.xing.com");

        client.Authenticator = OAuth1Authenticator.ForRequestToken(
                                                        consumerKey,
                                                        consumerSecret,
                                                        "oob");

        RestRequest request = new RestRequest("v1/request_token", Method.POST);
        RestResponse response = (RestResponse)client.Execute(request);

        var qs = HttpUtility.ParseQueryString(response.Content);
        access_token = qs["oauth_token"];
        access_token_secret = qs["oauth_token_secret"];
    }

    // Use Token to get the verifier.
    void B() {
        RestClient client = new RestClient("https://api.xing.com");

        RestRequest request = new RestRequest("/v1/authorize");
        request.AddParameter("oauth_token", access_token);
        var url = client.BuildUri(request).ToString();

        // use this url to get PIN Code
        MessageBox.Show(url);
    }

    // Use Access Token and Verifier to get the last Token needed
    void C() {
        RestClient client = new RestClient("https://api.xing.com");

        client.Authenticator = OAuth1Authenticator.ForAccessToken(
                                                        consumerKey,
                                                        consumerSecret,
                                                        access_token,
                                                        access_token_secret,
                                                        verifyPIN);

        RestRequest request = new RestRequest("v1/access_token", Method.POST);
        RestResponse response = (RestResponse)client.Execute(request);

        // Change tokens to the correct Access Tokens
        // now we have all Tokens in our TokenManager
        var qs = HttpUtility.ParseQueryString(response.Content);
        access_token = qs["oauth_token"];
        access_token_secret = qs["oauth_token_secret"];
    }

    // Get Data
    void D(String userID) {
        RestClient client = new RestClient("https://api.xing.com");

        client.Authenticator = OAuth1Authenticator.ForProtectedResource(
                                                        consumerKey,
                                                        consumerSecret,
                                                        access_token,
                                                        access_token_secret);

        RestRequest request = new RestRequest("/v1/users/" + userID);
        RestResponse response = (RestResponse)client.Execute(request);


        //Verify Result
        //Assert.NotNull(response);
        //Assert.Equal(HttpStatusCode.OK, response.StatusCode);

        MessageBox.Show(response.Content);
    }
}