W poprzednim odcinku po krótce opisałem kontrolkę PivotViewer oraz jak szybko można zacząć się nią bawić. Tym razem napiszę trochę o tym, że wcale tak szybko nie można się z nią zacząć bawić ze względu na nowe rozszerzenia plików, które muszą być obsłużone zarówno przez IIS jak i nasz wirtualny serwer Cassini. Dlaczego najpierw zajmuje się rozszerzeniami? Gdyż w następnych odcinkach zaczniemy korzystać z kolekcji w kontrolce i zrozumienie dlaczego nam się kolekcja nie ładuje będzie sednem naszych NIE zmarnowanych godzin :)

Użyłem sformułowania nowe rozszerzenia choć tak naprawdę jest tylko jedno nowe – CXML, reszta jest dość stara i pochodzi z DeepZoom:

  • CXML – jest to domyślny format kolekcji dla PivotViewer, jak popatrzycie na przykłady to wszystkie odnoszą się do pliku CXML, który tak naprawdę jest XMLem… więc po co wprowadzać zamieszanie? Nie wiem;
  • DZI – jest to format opisu obrazka z DeepZoom (DeepZoom Image), nic specjalnego – rozmiar, typ i itp. i oczywiście jest to plik XML – ech :)
  • DZC – jest to format opisu kolekcji z DeepZoom (DeepZoom Collection) – zawiera on odwołania do plików dzi :) i też jest XMLem.

Krótki opis typów można znaleźć klikając na rozszerzenie: CMLX, DZI i DZC (zawiera także info jak stworzyć pliki).

Skoro wiemy już z jakimi rozszerzeniami przyjdzie nam walczyć to jakie mamy opcję – w końcu nasze środowisko musi je rozumieć by móc je nam zwrócić, a wierzcie mi jeżeli środowisko nie rozumie to opis błędu nie będzie w jakikolwiek sposób pomocny – uwaga jeżeli zainstalowaliśmy przeglądarkę PivotViewer to pliki CXML będą nam działały :)

pivot_02_notfound

pivot_02_notfound_iis

Opcja 1: Korzystać z zewnętrznego systemu

A co? Po co się męczyć. Dać komuś innemu by wrzucił to na IIS i my będziemy się jedynie do tego odwoływać jeżeli plik ClientAccessPolicy.xml na to nam zezwoli. Jest to chyba najprostsza opcja.

Opcja 2: Stosować rozszerzenia XML! :)

To kolejna opcja która jest szybka i wydajna. Problem polega w dostępnych narzędziach do generowania kolekcji, na przykład plugin do Excela daje możliwość eksportu tylko do CXML (to łatwo zmienić na XML) i na szczęście pozostałe DZI i DZC już daje jako XML. Jednak narzędzie z linii poleceń już tak pięknie nie robi – CXML możemy mieć jako XML zaś reszta to już DZI, DZC. Nie wiem jak Blend. Jednak o sposobach tworzenia kolekcji będzie jeszcze post. Warto jednak wiedzieć iż można sobie znacząco życie ułatwić kiedy stosujemy XML :)

Opcja 3: Wykorzystujemy rozszerzenia CXML, DZI, DZC

I tutaj zaczynają się schody. Gdyż tak naprawdę mamy 3 różne systemy do obsłużenia:

  1. Cassini – nasz wirtualny serwer ASP.NET, zezwala na pewną konfigurację jednak nie jest ona jakaś za specjalna;
  2. IIS 6 – trochę inaczej deklarujemy w web.config mapowanie plików niż w IIS 7;
  3. IIS 7 – który ma nowe tagi w web.config by zadeklarować http handlers.

Cassini

Przez Cassini post został opóźniony. Mimo dokładnych notatek co i jak i dlaczego nie działało nie jestem wstanie problemu powtórzyć zarówno na czystej maszynie jak i maszynach dev. Więc cały opis Cassini zamieniam w dwa zdania.

Rozszerzenia CXML, DZI i DZC na serwerze wirtualnym ASP.NET działają bez problemu bez naszej ingerencji. Jeżeli jednak natraficie na problemy (bo ja raz natrafiłem) to opisy IIS 7 zawiera pełne rozwiązanie problemu – opcja staticContent mi nie działała, zaś handlers tak.

IIS 6

Nie mam jak tego sprawdzić (wiem jak to wygląda, ale screenshoty są z WinXP [IIS 5.1]/Win2k8 i dodatkowo nie mam uprawnień by IIS zainstalować na WinXP) ale konfiguracja dla web.config:

<system.web>
    <!-- other settings -->
  <httpHandlers>
    <add path="*.cxml" verb="GET" type="ASP.CxmlHandler"/>
    <add path="*.dzc" verb="GET" type="ASP.DzcHandler"/>
    <add path="*.dzi" verb="GET" type="ASP.DziHandler"/>
  </httpHandlers>
</system.web>

Powinna działać – kod dla hendlerów dostępny przy opisie IIS 7. Dodatkowo możemy również dodać własne MIME extensions. Jeżeli zaś konfigurację tą byśmy zastosowali do IIS 7, to otrzymalibyśmy następujący rezultat:

pivot_02_iis6_settings

IIS 7

Wymaga od nas własnych handlerów, które zwrócą nam odpowiednio pliki o które pytamy. Jako programiści mamy dwie opcje:

  • Ściągnąć paczkę (uwaga, MS nie wykazał się usability, link download dla paczki jest na dole tuż nad stopką nie ten na górze) zawierającą już takie handlery :)
  • Pokazać jacy jesteśmy świetni i napisać je sobie samemu :)

No dobra, wielcy nie musimy być gdyż implementacja jest banalna i lepiej na początku wykorzystać naszą gdyż paczka daje duuużo więcej możliwości jak generowanie CXML itp. w locie, dodatkowo implementacja udostępniona przez MS wymaga od nas dodania dodatkowej referencji do projektu, czego mi się już przeważnie nie chce robić.

A więc gdzieś w projekcie dodajemy plik Handlers.cs i wklejamy następujący kod:

using System;
using System.Web;

namespace ASP
{
    public abstract class BaseXmlHandler : IHttpHandler
    {
        public virtual void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/xml";
            context.Response.WriteFile(context.Request.Path);
        }

        public bool IsReusable
        {
            get { return true; }
        }
    }

    public class CxmlHandler : BaseXmlHandler
    {
        public override void ProcessRequest(HttpContext context)
        {
            // intentionally implemented
            base.ProcessRequest(context);
        }
    }

    public class DziHandler : BaseXmlHandler
    {
        public override void ProcessRequest(HttpContext context)
        {
            // intentionally implemented
            base.ProcessRequest(context);
        }
    }

    public class DzcHandler : BaseXmlHandler
    {
        public override void ProcessRequest(HttpContext context)
        {
            // intentionally implemented
            base.ProcessRequest(context);
        }
    }
}

Następnie by wykorzystać te handlery w serwerze IIS 7 w pliku Web.config dodajemy:

<system.webServer>
  <!-- other settings -->
  <handlers>
    <add name="CXML" path="*.cxml" verb="GET" type="ASP.CxmlHandler"/>
    <add name="DZC" path="*.dzc" verb="GET" type="ASP.DzcHandler"/>
    <add name="DZI" path="*.dzi" verb="GET" type="ASP.DziHandler"/>
  </handlers>
</system.webServer>

Lub wykonujemy operacje następująca, kasujemy handlery, kasujemy powyższą konfigurację i wstawiamy taką:

<system.webServer>
  <!-- other settings -->
  <staticContent>
    <mimeMap fileExtension=".cxml" mimeType="text/xml" />
    <mimeMap fileExtension=".dzc" mimeType="text/xml" />
    <mimeMap fileExtension=".dzi" mimeType="text/xml" />
  </staticContent>
</system.webServer>

Możemy to też wykonać z palca w IIS 7:

pivot_02_mime

Teraz by sprawdzić czy nasze handlery działają stwórzmy sobie przykładowy plik XML i zapiszmy go jako CXML lub DZI lub DZC i spróbujmy go otworzyć w przeglądarce. Teraz w zależności od opcji ustawień, jakie mamy (i przeglądarki) plik albo zostanie zwrócony w postaci XML, albo zostanie ściągnięty:

pivot_02_working

Podsumowanie

Jak widać coś co miało być proste nagle stało się bardziej skomplikowane. Ja osobiście nad tym by obsłużć CXML spędziłem więcej czasu niż chciałbym, jednak problemy u mnie były różne, kłopot z odwołaniem się do pliku (po nazwie hosta nie działał a po localhost działał albo całkowicie na odwrót), IIS nie akceptujący ustawień web.config (dziwne), IIS nie przyjmujący ustawienia mapowania mime ręcznie w ustawieniach (poprzez IIS Managment Console), dopiero jak podałem staticContent do web.config to zadziałało.

Na szczęście po jakimś czasie ktoś wpadł na genialny pomysł z MS i udostępnił narządko sprawdzające czy kolekcja, którą hostujemy, jest dostępna i jak nie jest to dlaczego.

2 KOMENTARZE

  1. hej,
    Dzieki że udostępniasz informacje o PV
    Czy próbowałeś może pobierać dane na bieżąco z bazy danych? tj czy da się podłączyć bazę bez tworzenia plików xml?
    Pomysł jaki mi przychodzi do głowy to pobieranie danych z bazy, tworzenie xml, zapis do pliki i załadowanie do PV

  2. mozesz to zrobic w locie bez plikow tak naprawde – PV daje mozliwosc dodawania elementow wiec da sie to i tak zrobic. zas co do dynamicznie tworzonych kolekcji jeszcze sie tym dokladnie nie bawilem ale w weekend zamierzam. Wiem ze sie da pytanie tylko czy bedzie to "efektywne" w sensie czasowo-wydajnosciowym – rozszerzyc handlera o to by tak naprawde odpytal baze danych i wygenerowal XMLa zamiast zwracac zawartosc zapytania context.Request.Path, nawet bez zapisu do pliku wszystko w locie. swoje zmagania opisze pewnie za tydzien lub dwa :)

Comments are closed.