Sziasztok újra itt, akkor ott folytatnánk, ahol legutóbb abbahagytuk. Vázoljuk fel újra, hogy mit is kell tennünk. Eljutottunk odáig, hogy van egy Silverlight 1.1 videólejátszó user control-unk, amiből egy Silverlight oldal betölt párat. Jelenlegi problémánk mindösszesen annyi, hogy a lejátszandó videók elérési útjai be vannak drótozva, ami egy kicsit tompítja a videógaléria csillogását. Ehelyett valami olyat szeretnénk, hogy egy mappából (ez lehet bedrótozott
), automatikusan felolvassa a wmv fájlokat, és betölti őket egy-egy videólejtászóba. Hogy ez miért jelent problémát???
A gondunk összesen annyi, hogy a Silverligt tartalom nem fér hozzá a fájlrendszerünkhöz (vagyis igen, de csak egy saját Isolated Storage-ba tud dolgozni azaz semmit nem lát az igazi fájlrendszerből), ennél fogva képtelen felolvasni például egy videos mappa tartalmát is. Ez okozza nekünk is a problémát. A megoldás tehát, hogy valami más olvassa fel, hogy hol is vannak a videófájlok, és mik is azok, és ez a valami egy webszolgáltatás lesz. Merthogy webszolgáltaást tudunk hívni Silverlight kódból
.
Nyissuk meg a kiindulási projektet amit korábban már elkészítettünk, és folytassuk. Adjunk egy új projektet a solution-höz, mégpedig egy ASP.NET Web Service-t VideoPlayerService néven. Hozzunk létre benne egy videos mappát, és másoljunk bele pár wmv fájlt, ezeket, illetve ezek elérési útját fogja felolvasni és visszaadni a webszolgáltatás. Első körben írjuk meg a webszolgáltatást, ami a mellette lévő videos mappát felderíti:
[WebMethod]
public string[] GetFiles()
{
StringBuilder sbFileNames = new StringBuilder();
DirectoryInfo di = new DirectoryInfo(this.Server.MapPath("videos"));
if (di.Exists)
{
foreach (FileInfo fi in di.GetFiles())
sbFileNames.AppendFormat("videos/{0};", fi.Name);
}
return sbFileNames.ToString().Split(';');
}
Egyetlen egy metódusunk van, a GetFileNames, és sztring tömbbel tér vissza. Tegyük fel, hogy csak wmv fájlok vannak a kérdéses mappában (ezért csak GetFiles()), és ne felejtsük el a using System.IO; using System.Text; névtereket. A működését nem részletezném, viszont van valami, amire mindeképp ki kell térnem: a Silverlight kód a kliens oldaloun fut(!), ezért a webszolgáltatásunknak kliens kódból meghívhatónak kell lennie. Ez ismerős már az ASP.NET AJAX kapcsán, és az Orcas ráadásul így generálta le magát a Service.asmx.cs-t is:
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
Fogadjunk hát szót, és vegyük ki a kommentezést
. Webszolgáltatás kész, videógaléria kész, integráljuk össze.
Első lépés: Silverlightos projektben referencia a webszolgáltatásra (VideoPlayerService), és a videólejátszó betöltésének átírása, hogy a webszolgáltatást használja. Mielőtt ezt megtennénk, ejtsünk pár szót arról, hogy miként bonyolítja meg most az életünket a fejelsztői webszerver. Először is, dinamikus portot generál, ez nem túl jó, hiszen hiába adok egy porton referenciát a webszolgáltatásra, ha legközelebb úgysem ott fut. Oké, semmi gond, webszolgáltatás tulajdonságainél állítsuk be, hogy ne használjon dinamikus portot. Implementáljuk a webszolgáltatás meghívását így:
VideoPlayerService.Service s = new VideoPlayer.VideoPlayerService.Service();
foreach (var file in s.GetFiles())
{
if ( file != "" )
new Player(this, new Uri(HtmlPage.DocumentUri, file));
}
Semmi extrát nem kell tennünk, a webszolgáltatás pont olyan formában adja vissza a sztring tömböt, hogy konform legyen a korábbi megoldásunkkal. Futtassuk. Az F5 megnyomásakor baljós árnyként tűnik fel ez a dialógusablak:
Ne ijedjünk meg, nem akar ez semmi rosszat, csak figyelmeztet, hogy ugye tudjuk, hogy webszolgáltatást kívánun használni, és hogy ugyanabban a kontextusban kell lennünk, ahol a webszolgáltatás is van. Bevillan valami a kliens oldali cross-domain hívásokról, illetve hogy az nem megy, de rövid gondolkodás után megállpítjuk, hogy no problem, localhost-on vagyunk, úgyhogy tűnj innen ablak, Yes. Kipróbáljuk, és nem megy
, hanem jön egy újabb ablak:
Mégis oda kellett volna figyelni, hogy mit akart vajon a korábbi ablak, mert mégis ezzel a cross-domain dologgal van baja. Kicsit elgondolkodunk, és látjuk, hogy a Silverlight projektet d:\...\TestPage.html elérési úttal futtaja a VS, míg a webszolgáltatást ugye http://localhost/.../Service.asmx címen érjük el. Nézzük mit tehetünk az "ugyanazon" kontextusért. Tehát a Silverlight alkalmazást kellene betenni a webszolgáltatás projektjébe. Ehhez a következőket kell tenni:
- webszolgáltatás projektjén jobb gombbal kattinva, majd Add Silverlight Link..., majd a megjelenő kérdésre: "igen akarjuk".
- Ez hozzáadta a Silverlight ClientBin mappáját a dll-ekkel együtt a webszolgáltatás projektjéhez, továbbá idemásolódott a Page.xaml és a Silverlight.wmv is, ez utóbbit nyugodtan töröljük, úgysem ez kell.
- Hozzuk át még a TestPage.html, TestPage.html.js, és Silverlight.js fájlokat is,
Végül nyissuk meg a webszolgáltatás mappájában lévő TestPage.html-t, és csodák-csodája, végre működik. Megvan amit akartunk, dinamikusan, fájlrendszerből olvassuk fel a videók listáját. Ehhez az kellet, hogy a Silverlight kódból webszolgáltatást hívjunk (adunk referenciát rá a már ismert módon), ami pedig nem megy addig, amíg a Silverlight-ot tartalmazó oldal ugyanabban a projektben nincs, amiben a webszolgáltatás is (adunk hivatkozást a Silverlight projektre a webszolgáltatásból). Nem alakul ki keresztbe referencia, mert az "Add Silverlight Link..." nem igazi referencia, inkább csak egy automatizmus, ami a Silverlight projekt outputját átmásolja (és szinkronban tartja a Silverlight projekt újrafordításakor is) a webes alkalmazásba. Ezt a második megkötést szertinem egyelőre tudjuk be az 1.1 alpha készültségének, a legtöbb helyen azt lehet olvasni, hogy lehet majd cross domain módon is webszolgáltatást hívni Silverlight 1.1-ből is.
Forráskódot ismét mellékeltem, jó csemegézést! Remélem tudtam segíteni.