CCA (Customer Care Accelerator)

Na blogu Kuby (o tutaj: http://crmblog.pl/2010/05/28/customer-care-accelerator-cca-czy-to-jeszcze-akcelerator/) znaleźć można informacje o … no właśnie o czym ? Z jednej strony w nazwie jest akcelerator co świadczyć może o darmowym dodatku do CRM. Z drugiej strony do tej pory wszelkie akceleratory nie były aż tak skomplikowane – jeśli chodzi o architekturę, możliwości.

CCA nawiązuje do CCF, jednakże zostało specjalnie dostosowane do Dynamics CRM i całego myślenia związanego z xRM. A co najważniejsze jest za free.

Jak przeczytać możecie na blogu Kuby na CCA składa się wiele komponentów, które my (my = Netwise – Kuba) musimy poznać (on miał to szczęście i uczył się od najlepszych, ale my teraz będziemy czerpać od niego tę wiedzę). Na pewno w trakcie poznawania będziemy swoje doświadczenia, wrażenia, opinie przedstawiać na blogach. Dajcie nam tylko chwilę na poznanie tej technologii :)

Wypróbuj CRM za darmo

Microsoft uruchomił kampanię promocyjną Dynamics CRM, w której każdy może założyć sobie konto testowe i szaleć przez pewien czas :)

Złośliwość przedmiotów martwych (tak to nazwijmy) powoduje, że po wejściu na stronie http://emea.dynamicscrm.com oczom ukazuje się jakiś pseudo-angielszczyzną brzmiący komunikat, że jakieś parametry zostały źle zdefiniowane.

Aby zobaczyć to co było zaplanowane najlepiej wejść na stronę: http://emea.dynamicscrm.com/?culture=pl-PL&campaign=MSPOL&partner=Netwise

image

Unhandled Error in Silverlight Application Code: 2104

Jeśli tworzymy komponent w SL, który chcemy następnie pokazać na formatce w Dynamics CRM to możemy się spotkać z tym błędem.

Rozwiązanie polega na odpowiedniej konfiguracji typów MIME na serwerze IIS (od wersji 6.0):

IIS 6.0Dzięki takiej konfiguracji serwer IIS będzie wiedzieć co z naszym komponentem (który znajduje się w katalogu ClientBin z rozszerzeniem *.xap) zrobić. Po takiej konfiguracji można na wszelki wypadek wykonać restart IIS (iisreset).

CRM 4.0 + Outlook 2010

Aby móc korzystać z dodatku w nowej wersji Outlook należy wziąć po uwagę następujące ograniczenia:

  1. Outlook musi być w wersji 32bitowej – super sprawa, że nowa wersji Office’a jest dostępna w dwóch wersjach (32 i 64 bity). Jednakże dodatek nie został jeszcze dopracowany, aby z nowości (64 bitów) korzystać. Musimy pozostać przy wersji 32 bitowej
  2. Dodatek musi być zainstalowany przed instalacją nowej wersji Office’a – instalując nowego Office’a musimy skorzystać z opcji aktualizacji (lub też opcji odinstalowania starej wersji i instalacji nowej). Instalacja samego dodatku dla wersji 2010 spowoduje pojawienie się błędu związanego z niekompatybilną wersją oprogramowania. Podobnie jak w punkcie 1 tak samo i tutaj trzeba poczekać na nową wersję dodatku – na razie nie wiadomo kiedy zostanie ona udostępniona – miejmy nadzieję, że nie wraz z wersja CRM’a 5.
  3. Dodatek należy ręcznie uruchomić – być może okazać się, że dodatek nie zostanie automatycznie uruchomiony po pierwszym uruchomieniu Outlook. Aby go uruchomić należy:
    • Wyświetlić Opcje programu Outlook

 opcje

    • W oknie Opcji należy przejść do części poświęconej dodatkom a następnie wyświetlić dodatki COM.

image

    • Na liście dodatków należy wybrać Microsoft Dynamics CRM i kliknąć OK. Spowoduje to pojawienie się charakterystycznych elementów dla tego dodatku (w tej wersji Outlook już na wstążce).

image

image

SilverCRM cz. 3 – kilka aspektów związanych z komunikacją Silverlight i CRM

Część druga projektu SilverCRM zakończyła się wspomnieniem na temat aspektów związanych z komunikacją pomiędzy komponentem Silverlight a CRM. Aby je opisać trzeba zrozumieć różnicę pomiędzy np. stronami *.aspx, które wbudowane są w formatkę CRM i znajdują się na serwerze IIS w katalogu ISV. Strony takie uruchamiane są po stronie IIS a klient (czyli przeglądarka) dostaje efekt pracy wykonanej po stronie serwera. Całe wykonanie kodu leży po stronie serwera. W przypadku komponentu Silverlight sprawa wygląda nieco inaczej. To, że znajduje się on na serwerze IIS w tej samej lokalizacji jak strona *.aspx jest jedyną ich cechą wspólną. Wykonanie kodu w przypadku komponentu jest przeniesione na maszynę klienta, tam następuje wykonanie kodu i jednocześnie prezentacja wyniku. Z jednej strony serwer IIS jest odciążony od obsługi dużej ilości żądań a z drugiej strony nasz komponent rozprzestrzenił się po wszystkich stacjach klienckich, które z niego korzystały.

W przypadku usług, z którymi komponent będzie się łączyć może wystąpić problem komunikacji cross-domain. Polega on na tym, że usługa może znajdować się w innej domenie niż nasz komponent, a wtedy wykonanie naszego kodu zakończy się błędem. Rozwiązaniem tego problemu jest umieszczenie po stronie usługi pliku, w którym należy wyspecyfikować, z którym domen usługa powinna obsługiwać żądania. Plik ten musi być nazwany clientaccesspolicy.xml i znajdować się w musi w katalogu głównym naszej usługi. Przykład takiego pliku jest następujący:

<?xml version="1.0" encoding="utf-8"?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from http-request-headers="SOAPAction">
        <domain uri="*"/>
      </allow-from>
      <grant-to>
        <resource path="/" include-subpaths="true"/>
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>

W tym pliku mamy zezwolenie na łączenie się do usługi z dowolnej domeny: <domain uri="*"/>. Zamiana tego elementu powoduje zezwolenie na łączenie się ze wskazanej domeny. Można również skorzystać z pliku crossdomain.xml, który znany jest chociażby z Flash – na ten temat można znaleźć informacje tutaj: http://msdn.microsoft.com/en-us/library/cc197955(VS.95).aspx

Kolejnym aspektem jest korzystanie z metod usługi CRM. Jak już możemy się z nią odpowiednio komunikować możemy np. pobrać wszystkie konta, do których mamy prawo. Kod, który to zrobi wygląda tak:

QueryExpression _query = new QueryExpression();
_query.ColumnSet = new AllColumns();
_query.EntityName = "account";
_client.RetrieveMultipleAsync(_query);

Jednakże jak się okazuje, mimo, że kolekcja zawiera odpowiednią liczbę elementów o tyle elementy te mają wszystkie właściwości ustawione na null. Błąd ? Z tego co wyczytałem na forach jest to błąd Silverlight, który powinien zostać wyeliminowany, ale z tego co widać jeszcze nie został. Na szczęście jest tzw. workaround. Zamiast pisać krótki kod do pobierania elementów trzeba zawsze pobierać elementy w postaci DynamicEntity. Wtedy dostając się do kolekcji właściwości otrzymamy dane, które nie będą null.

RetrieveMultipleRequest _request = new RetrieveMultipleRequest();
_request.Query = _query;
_request.ReturnDynamicEntities = true;
_client.ExecuteAsync(_request);

Na szczęście tworząc nowe obiekty w CRM, np. nowe konto nie musimy tworzyć obiektu w postaci DynamicEntity tylko możemy korzystać z bezpośrednich klas.

Mając wiedzę z trzech wpisów, które tutaj zamieściłem każdy będzie mógł zacząć tworzyć to, na co jego biznes ma ochotę. Mając do dyspozycji Silverlight można w CRM wbudować bardzo bogato wyglądające elementy, np. piękne raporty, strumieniowanie - jednym słowem wszystko to co oferuje Silverlight.

CRM 4.0 Sharepoint Connector

 

Czasami jest potrzebne w czasie wdrożenia systemu CRM zintegrowanie systemu z bibliotekami dokumentów czy to na darmowym WSS czy też na MOSS. Na podstawie naszego doświadczenia przygotowaliśmy specjalny komponent, który w prosty sposób zastosować można do takiej integracji.

Przy jego pomocy można, m.in:

  1. Tworzyć strukturę katalogów odpowiadającą obiektom w systemie CRM, np. dla każdego klienta tworzymy katalog na dokumenty, dla każdej oferty tworzymy katalog w katalogu klienta na kolejne wersje dokumentu zawierającą aktualną wersję oferty, itd.
  2. Prezentować zawartość katalogu, np. na formatce klienta, na formatce szansy sprzedaży
  3. Automatycznie zarządzać zabezpieczeniami katalogu na WSS tak aby ten kto nie może widzieć rekordów w CRM nie mógł ich znaleźć na katalogu w bibliotece dokumentów.
  4. Automatycznie usuwał katalog w czasie usunięcia rekordu w systemie CRM.

‘…’ oznacza, że komponent ten może działać w dowolny inny sposób jaki sobie tylko zażyczysz :)

Nowy obraz

Wszelkie informacje jak się z nami skontaktować, aby otrzymać szczegółowe informacje dotyczące tego komponentu znaleźć można na stronie: www.netwise.pl

SilverCRM cz. 2 – połączenie z Dynamics CRM.

Silverlight, aby spełnić wymaganie przed nim stawiane – uruchamianie się na różnych systemach operacyjnych (Windows, Linux, Mac) i w różnych przeglądarkach (IE, Firefox, Safari) – został zbudowany niejako obok .NET Framework. Fundamentem .NET Framework jest CLR. Silverlight został wyposażony w specjalne środowisko uruchomieniowe oraz w specjalny zbiór klas, aby móc spełnić tym wymaganiom. Jeśli chodzi o warstwę komunikacyjną to posiada on wbudowany WCF (Windows Communication Foundation). Chcąc skomunikować ze sobą Dynamics CRM oraz Silverlight będziemy łączyć ze sobą technologią ASP.NET oraz WCF. Jak dalej zostanie opisane – nie zawsze jest to, aż takie proste :)

Pierwszym krokiem jest skorzystanie z opcji dodania referencji do usługi. W przypadku starszych technologii w VS posiadaliśmy opcję Add Web Reference. Wraz z WCF dostaliśmy opcję Add Service Reference, którą można było zamienić na zwykłą Web Reference (wchodzą w dodatkowe ustawienia). W Silverlight nie mamy takiej opcji i musimy korzystać tylko z Service Reference – tak jak to jest pokazane na rysunku:

 

Skorzystanie z opcji dodania referencji do usługi spowoduje wyświetlenie okienka, w którym wprowadzić będzie trzeba adres, pod którym dostępna będzie usługa (np. http://localhost/MSCrmServices/2007/CrmService.asmx). Można tutaj również wskazać np. ścieżkę na lokalnym dysku gdzie znajduje się plik z definicją usługi (*.wsdl). Po odpowiednim skonfigurowaniu i wygenerowaniu namiastki zostanie w projekcie utworzony katalog Service References gdzie znajdziemy kod źródłowy stworzonej namiastki.

 

Oprócz kodu namiastki zostanie wygenerowany plik konfiguracyjny, który będziemy mogli wykorzystać w czasie tworzenia instancji namiastki. Zamiast pisać kod i wskazywać, z których wiązań i w jakiej konfiguracji należy korzystać można te wartości wskazać w pliku konfiguracyjnym i w czasie tworzenia instancji namiastki na ten plik się powoływać. Przykładowy plik konfiguracyjny wygląda następująco:

<configuration>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="CrmServiceSoap" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
                    <security mode="None" />
                </binding>
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="
http://localhost/MSCrmServices/2007/CrmService.asmx"
                binding="basicHttpBinding" bindingConfiguration="CrmServiceSoap"
                contract="CrmSdk.CrmServiceSoap" name="CrmServiceSoap" />
        </client>
    </system.serviceModel>
</configuration>

Warto tutaj zwrócić uwagę na nazwę końcówki (endpoint), która w pokazanym pliku jest ustawiona na CrmServiceSoap. W momencie tworzenia instancji namiastki będzie można wskazać na jaką konfigurację WCF musi się powołać, aby poprawnie namiastkę zainicjować.

Warto tutaj zwrócić uwagę na nazewnictwo klas wygenerowanym z pliku *.wsdl usługi CRM. W czasie tworzenia namiastki poprzez zwykłe Web Reference dostawaliśmy w efekcie klasę CrmService. Tutaj otrzymujemy CrmServiceSoapClient. Inne klasy takie jak account, contact, reprezentujące obiekty CRM generowane są bez żadnych zmian.

Tworzenie instancji namiastki jest następujące:

CrmServiceSoapClient _client = new CrmServiceSoapClient("CrmServiceSoap");

gdzie CrmServiceSoapClient jest klasą wygenerowaną przez WCF, natomiast argumentem konstruktora tej klasy jest wskazanie konfiguracji końcówki z pliku konfiguracyjnego również wygenerowanego przez WCF.

Silverlight umożliwia wywoływanie tylko i wyłącznie metod asynchronicznych. Zatem w namiastce nie mamy metod CrmService takich jak Execute, Create, Update. Mamy natomiast metody ExecuteAsync, CreateAsync, itd. Wszelkie operacji przy pomocy Silverlight wykonywane są asynchronicznie !!! Mając to na uwadze po utworzeniu namiastki trzeba obsłużyć zdarzenia zakończenia wykonywania operacji asynchronicznej. Przykładowy kod wygląda tak:

_client.RetrieveMultipleCompleted += new EventHandler<RetrieveMultipleCompletedEventArgs>(OnClientRetrievedMultiple);
_client.ExecuteCompleted += new EventHandler<ExecuteCompletedEventArgs>(OnClientExecuteCompleted);

, gdzie metody OnClientRetrievedMultiple oraz OnClientExecuteCompleted są zdefiniowane następująco:

void OnClientExecuteCompleted(object sender, ExecuteCompletedEventArgs e) {}

void OnClientRetrievedMultiple(object sender, RetrieveMultipleCompletedEventArgs e) {}

Aby wiedzieć do jakiej organizacji się połączyć do tej pory (tzn. korzystając z Web Reference) otrzymywaliśmy klasę CrmAuthenticationToken, który umożliwiał wskazanie do której organizacji chcemy się połączyć, w jaki sposób chcemy dokonać uwierzytelnienia, itd. W przypadku WCF oczywiście otrzymujemy klasę CrmAuthenticationToken w namiastce jednakże klasa CrmServiceSoapClient nie posiada właściwości, która umożliwia ustawienia i wykorzystanie tokenu. Aby poprawnie połączyć się z usługą CRM musimy mieć możliwość dołączenia do żądań SOAP nagłówka – musimy mieć metodę GenerateAuthenticationHeader, którą mamy jak piszemy skrypt uruchamiany, np. na zdarzeniu OnLoad formatki CRM. Metodę tą możemy zbudować korzystając z kanały komunikacyjnego, z którego korzysta WCF. Musimy ręcznie dołączyć nagłówek do wiadomości wychodzących od naszego komponentu:

MessageHeader header = MessageHeader.CreateHeader("CrmAuthenticationToken",
                  "http://schemas.microsoft.com/crm/2007/WebServices",
                  "",
                  new CrmAuthenticationTokenSerializer(0, orgname, null));

OperationContext.Current = new OperationContext((IContextChannel)_client.InnerChannel);
OperationContext.Current.OutgoingMessageHeaders.Add(header);

Klasa CrmAuthenticationTokenSerializer jest naszą własną klasą dziedziczącą po XmlObjectSerializer:

    public class CrmAuthenticationTokenSerializer : XmlObjectSerializer
    {
        int _authType;
        string _organizationName;
        string _callerId;

        public CrmAuthenticationTokenSerializer (int authType, string organizationName, string callerId)
        {
            _authType = authType;
            _organizationName = organizationName;
            _callerId = callerId;
            if (_callerId == null)
            {
                _callerId = "00000000-0000-0000-0000-000000000000";
            }
        }


        public override void WriteStartObject(XmlDictionaryWriter writer, Object graph)
        {
        }

        public override void WriteObjectContent(XmlDictionaryWriter writer, Object graph)
        {
            string authToken = string.Format("<AuthenticationType xmlns='http://schemas.microsoft.com/crm/2007/CoreTypes'>

            {0}</AuthenticationType><OrganizationName xmlns='http://schemas.microsoft.com/crm/2007/CoreTypes'>

            {1}</OrganizationName><CallerId xmlns='http://schemas.microsoft.com/crm/2007/CoreTypes'>

            {2}</CallerId>", _authType, _organizationName, _callerId);

            writer.WriteRaw(authToken);
        }

        public override void WriteEndObject(XmlDictionaryWriter writer)
        {
        }


        public override bool IsStartObject(XmlDictionaryReader reader)
        {
            return true;
        }

        public override Object ReadObject(XmlDictionaryReader reader, bool verifyObjectName)
        {
            return null; 
        }

    }

Mając tak zdefiniowaną klasę możemy przystąpić do wywoływania metod usługi CRM. Jednakże w czasie wywołania najprostszego żądania, np. WhoAmIRequest dostaniemy błąd związany z komunikacją pomiędzy domenami. Dlaczego tak się dzieje ? O tym w kolejnym wpisie. Tam również kilka informacji na temat błędów związanych z metodami Retrieve oraz RetrieveMultiple.