Kommunikáció ASP.NET és Silverlight között

Mostanában divat azon vitatkozni, hogy az ASP.NET vagy a Silverlight-e a jövő webfejlesztő technológiája. Különösen az utóbbi hívei között vannak olyanok, akik szeretik azt hinni, hogy kis kedvencük minden helyzetben tökéletes választás. Szerintem a két technológiát együtt fogjuk használni a jövőben: amit nem lehet vagy nem célszerű a böngészőben megoldani, ott fogunk a böngésző bővítményhez folyamodni. Ehhez persze nélkülözhetetlen, hogy a két világ tudjon egymással kommunikálni.

Silverlight alkalmazás inicializálása ASP.NET-ből

Egy Silverlightos alkalmazásnak induláskor adatokat adhatunk át az initParams paraméterben. Egyetlen stringben, vesszővel elválasztva kell felsorolnunk az átadandó kulcs-érték párokat.

HTML:

    <object data="data:application/x-silverlight-2," ...>
        <param name="source" value="ClientBin/SilverlightApplet.xap"/>
        <param name="initParams" value="p1=Első paraméter,p2=Második paraméter" />
        ...
    </object>

ASP.NET-ben a beágyazó asp:Silverlight vezérlő InitParameters tulajdonságát kell használnunk akár code behindból, akár ASPX markupból:

    <asp:Silverlight ID="slPlugin" runat="server" Source="~/ClientBin/SilverlightApplet.xap"
        MinimumVersion="2.0.31005.0" Width="100%" Height="100%"
        InitParameters="p1=Első paraméter,p2=Második paraméter" />

Az így átadott paraméterek Silverlightban az App.xaml.cs fájlban lévő Application_Startup metódus StartupEventArgs e paraméterében érkeznek meg egy szótár típusú változóban. Ha nem csak itt akarjuk elérni, akkor szerintem érdemes kitenni statikus változóba:

    // Silverlight: 
public partial class App : Application { internal static IDictionary<string, string> InitParams; private void Application_Startup( object sender, StartupEventArgs e ) { App.InitParams = e.InitParams; this.RootVisual = new Page(); }
}

Ez persze bárhonnan elérhető a Silverlight alkalmazáson belül:

    // Silverlight: A bemenő paramétereket vesszővel kell elválasztani, különben KeyNotFoundException jön.
    this.lblInitParams.Text = String.Format( CultureInfo.InvariantCulture, 
        "Param1={0}, Param2={1}", App.InitParams[ "p1" ], App.InitParams[ "p2" ] );

Érték átadása a weboldalról

Az ASP.NET és a Silverlight együttélésének a kulcsa a Silverlight HTML Bridge nevű komponense, aminek segítségével felügyelt kódból érhetjük el a böngészőben futó oldalt, illetve a felügyelt kódunk bizonyos részeit tehetjük böngészőből elérhetővé. Ahhoz, hogy a weboldalról adatot tudjunk átadni egy Silverlight alkalmazásnak, egy felügyelt metódust kell publikálnunk, melyet majd JavaScriptből hívunk meg. A kiválasztott metódus elé a [ScriptableMember] attribútumot kell biggyesztenünk. Ha a metódust más néven akarjuk szkriptből meghívni, használhatjuk az attribútum ScriptAlias tulajdonságát. Ha egy osztály összes metódusát publikálni szeretnénk, akkor az osztály elé tehetjük a [ScriptableType] attribútumot.

    // Silverlight
    // [ScriptableType]
    public partial class Page : UserControl
    {
        public Page()
        {
            InitializeComponent();
            HtmlPage.RegisterScriptableObject( "MyScriptableType", this );
        }

        [ScriptableMember]
        public string SayHello( string name )
        {
            this.lblMessageIn.Text = name;
            return "Szia " + name;
        }
}

A következő lépés a HtmlPage.RegisterScriptableObject meghívása. Az első paraméterben tetszőleges sztringet megadhatunk, ilyen néven lesz elérhető a második paraméterben megadott objektumunk JavaScriptből.

A példában egy HTML szövegdoboz értékét adjuk át gombnyomásra a fenti SayHello metódusnak, ami az slPlugin azonosítójú asp:Silverlight vezérlőben fut:

    <!-- ASPX -->
<asp:ScriptManager runat="server" />

    <input type="text" id="txtName" />
    <input type="button" value="Küldés" onclick="sendToSilverlight()" />
    <script type="text/javascript" language="javascript">
        function sendToSilverlight()
        {
            var slPlugin = $get( '<%= this.slPlugin.ClientID %>' );
            var txtName = $get( 'txtName' );
            var result = slPlugin.Content.MyScriptableType.SayHello( txtName.value );
            alert( 'Válasz: ' + result );
        }
    </script>

A JavaScript írásakor ne várjunk az IntelliSensre, nem lesz.

Érték átadása a weboldalnak

Silverlightból adhatunk át adatokat a weboldalnak, a HTML Bridge segítségével ugyanis gyakorlatilag a teljes DOM-ot kezelhetjük felügyelt kódból. (Na ezt kellene valakinek megírnia egy kicsit típusosabban ASP.NET-ben…) Arra kell csak figyelni, hogy a Silverlight pluginon vagy az őt tartalmazó div elemen ne legyen display:none vagy visibility:hidden. Szépen is néznénk ki, ha láthatatlan vezérlők rángathatnák a weboldalunkat🙂

Íme az ASPX oldalunknak az a része, amely fogadni fogja az adatot a Silverlight alkalmazástól:

    Fogadott: <span id="lblName">(még nem jött semmi)</span>

Silverlight oldalon faragtam egy mini űrlapot:

    <StackPanel Orientation="Horizontal">
        <TextBlock Text="Küldendő üzenet: " FontWeight="Bold" VerticalAlignment="Center" />
        <TextBox x:Name="txtMessageOut" Width="100" />
        <Button x:Name="btnSend" Content="Küldés" Click="btnSend_Click" />
    </StackPanel>

A lényeg persze a gomb eseménykezelője:

    // Silverlight 
private void btnSend_Click( object sender, RoutedEventArgs e ) { HtmlDocument doc = HtmlPage.Document; HtmlElement lblName = doc.GetElementById( "lblName" ); lblName.SetAttribute( "innerHTML", this.txtMessageOut.Text ); }

Weboldal esemény kezelése Silverlightban

Arra is van lehetőségünk, hogy felügyelt kódban kezeljük egy HTML DOM objektum valamely eseményét, ráadásul ehhez nem kell JavaScriptet írni. Készíthetünk például egy combo boxot a weblapunkra:

    <!-- HTML / ASPX -->
    <select id="selWelcome">
        <option>Szia</option>
        <option>Helló</option>
        <optiondv</option>
    </select>

A select objektumnak van egy changed eseménye, amire feliratkozhatunk Silverlightból:

    // Silverlight: feliratkozás weblap esem?nyre
    HtmlDocument doc = HtmlPage.Document;
    HtmlElement selWelcome = doc.GetElementById( "selWelcome" );
    selWelcome.AttachEvent( "onchange", new EventHandler<HtmlEventArgs>( this.OnWelcomeChanged ) );

Sajnos itt sem lesz IntelliSense az eseménykezelő megírásához, ezért jó tudni, hogy létezik egy HtmlEventArgs paraméter típus:

    private void OnWelcomeChanged( object sender, HtmlEventArgs e )
    {
        HtmlElement selWelcome = sender as HtmlElement;

        string selection = String.Empty;
        foreach( HtmlElement option in selWelcome.Children )
        {
            object selectedProperty = option.GetProperty( "selected" );

            if( selectedProperty != null )
            {
                if( selectedProperty.ToString().Equals( "true", StringComparison.OrdinalIgnoreCase ) )
                {
                    selection = option.GetProperty( "innerHTML" ).ToString();
                }
            }
        }
        MessageBox.Show( "Ezt választottad az oldalon: " + selection );
    }

A fenti kódból talán látszik, hogy a HTML Bridge az összes HTML elemet egyetlen HtmlElement osztályra képezi le. Ez persze nem rossz, de most éppen kicsit nehézkes megkeresni a kiválasztott gyermekelemet. Persze bevethetünk egy kis LINQ-et🙂

    string selection = ( from HtmlElement option in selWelcome.Children
                         let o = option.GetProperty( "selected" )
                         where
                           p != null &&
                           p.ToString().Equals( "true", StringComparison.OrdinalIgnoreCase )
                         select option.GetProperty( "innerHTML" ).ToString()
).First();

A felhasznált osztályok a System.Windows.Browser névtérben találhatóak. Érdemes ott körülnézni, van ott még más hasznos típus is…

A cikkhez tartozó forráskód letölthető: HtmlBridgeSampleSolution.zip (549 kB)

Vélemény, hozzászólás?

Adatok megadása vagy bejelentkezés valamelyik ikonnal:

WordPress.com Logo

Hozzászólhat a WordPress.com felhasználói fiók használatával. Kilépés / Módosítás )

Twitter kép

Hozzászólhat a Twitter felhasználói fiók használatával. Kilépés / Módosítás )

Facebook kép

Hozzászólhat a Facebook felhasználói fiók használatával. Kilépés / Módosítás )

Google+ kép

Hozzászólhat a Google+ felhasználói fiók használatával. Kilépés / Módosítás )

Kapcsolódás: %s