Flickr, Silverlight og WCF


Jeg elsker billeder. Jeg elsker at se billeder på Flickr fordi de gør mig så glade og giver mig inspiration til nye ting. Billeder siger jo mere end 1000 ord; med mindre de ord er en del af et programmeringsprog 🙂

Jeg har været igang med at lave en random-image-generator udfra nogle af de brugere på Flickr jeg godt kan lide at se billeder fra.

Ideén kom sig egentlig af FogBugz, hvor der er optræder et billede som en del af en menu bjælke i applikationen. Det billede i FogBugz giver et indtryk af tryghed og tilfredsstillelse ved brug af softwaren, men desværre skifter det for sjældent.

Jeg gik selv igang med at lave lidt sjov...

Ind på flickr.com, sign up, søg om et application token og kopier det ind i ens egen web applikation. Flickr tilbyder dig at hooke ind på flere forskellige services (SOAP, REST etc) og der er lavet rigtig mange forskellige API kits til at tilgå disse services med. Jeg fandt et API kit på codeplex.com som jeg kunne bruge sammen med .NET. Jeg bruger kun FlickrNet dll filen.

Jeg tænkte jeg ville lave en Silverlight applikation som en slags host for min billede generator. Men jeg ville også gerne have noget WCF indover for at se på hvordan WCF og Silverlight virker i sammenspil.

Så jeg lavede en WCF service med en basicHttpBinding og funktionalitet til at hente billeder fra Flickr.com. Man kan vel kalde servicen for en slags proxy imellem Flickr og min Silverlight applikation.

Lad os se på den funktionalitet jeg fik smidt ind i min WCF service.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using FlickrNet;

// NOTE: If you change the class name "Service" here, you must also update the reference to "Service" in Web.config and in the associated .svc file.
public class Service : IService
{
    private Flickr flickr;
    private FlickrImage flickrImage;
    private string flickrUserId;

    private readonly string favoriteUserIds = "86474756@N00,81249677@N00,52733933@N00";
    private readonly string applicationToken = "XXX";

    private void GetImage( Photos photoSearch, int retriesCounter )
    {
        try {
            //generate a random photo index
            Random randomPhoto = new Random();
            int photoIndex = randomPhoto.Next( int.Parse( photoSearch.TotalPhotos.ToString() ) );

            //get the collection of photos from our search
            PhotoCollection photoCollection = photoSearch.PhotoCollection;

            //set the image attributes
            flickrImage = new FlickrImage();
            flickrImage.ImageUrl = photoCollection[ photoIndex ].SmallUrl;
            flickrImage.ImageAlt = photoCollection[ photoIndex ].Title;
        } catch {
            if( retriesCounter <= 2 ) {
                //if failing, try again.
                GetImage( photoSearch, retriesCounter++ );
            }

            throw new FaultException( new FaultReason( "Fejl" ), new FaultCode( "GetImage" ) );
        }
    }

    private string GetUserId()
    {
        if( favoriteUserIds.Length > 0 ) {
            //split the user ids up and put them in array
            string[] idsArray = favoriteUserIds.Split( ',' );

            //randomly picking user
            Random randomUserId = new Random();
            return flickrUserId = idsArray[ randomUserId.Next( idsArray.Count() ) ];
        } else {
            throw new FaultException( new FaultReason( "favoriteUserIds er af ugyldig længde (0)" ), new FaultCode( "GetUserId" ) );
        }
    }

    private string GetUserTag()
    {
        if( flickrUserId.Length > 0 ) {
            //get the tag list from our user
            Tag[] tags = flickr.TagsGetListUser( flickrUserId );

            //randomly picking a tag
            Random randomTag = new Random();
            return tags[ randomTag.Next( tags.Count() ) ].TagName;
        } else {
            throw new FaultException( new FaultReason( "flickrUserId er af ugyldig længde (0)" ), new FaultCode( "GetUserTag" ) );
        }
    }

    public FlickrImage GetFlickrImage()
    {
        if( applicationToken.Length > 0 ) {
            //new instance of Flickr
            flickr = new Flickr( applicationToken );

            //set the search options
            PhotoSearchOptions searchOptions = new PhotoSearchOptions();
            searchOptions.UserId = GetUserId();
            searchOptions.Tags = GetUserTag();

            //apply the search options and search
            GetImage( flickr.PhotosSearch( searchOptions ), 0 );
        }

        return flickrImage;
    }
}

Læg mærke til at jeg bruger FaultExceptions i min WCF service, men husk at dette kan Silverlight ikke forstå. Det skyldes at Silverlight kun kommer med et subset af WCF eller det kun kommer med et subset af WPF.

Jeg smed servicen ind i IISen og testet om der var hul igennem. Jeg lavede 2 nye filer som lagde i roden af mit site hvor min WCF service lå; clientaccesspolicy.xml og crossdomain.xml.

Disse to filer er sikkerheds konfigurations filer og ser således ud:

clientaccesspolicy.xml:

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

crossdomain.xml

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
    <allow-http-request-headers-from domain="*" headers="*"/>
</cross-domain-policy>

crossdomain filen er faktisk den samme som Flash bruger. Den fortæller at vi kan connecte fra et vilkårligt site igennem den port og protocol sitet nu engang bruger.

Så lavede jeg en ny silverlight applikation (Husk at SL 2.0 RC0 er ude) og tilføjde et ganske almindeligt web site til silverlight løsningen. Jeg tilføjede en service reference til min WCF service på localhost og skrev et par liniers kode til for at komme i kontakt med min WCF service.

private void GetNewImage()
{
    ServiceClient client = new ServiceClient();
    try {
        client.GetFlickrImageCompleted += new EventHandler<GetFlickrImageCompletedEventArgs>( client_GetFlickrImageCompleted );
        client.GetFlickrImageAsync();
    } catch( FaultException faultException ) {
        error.Text = faultException.ToString();
    }
}

Godt nok tjekker jeg for en FaultException i min klient, men min OperationContract i WCF servicen er ikke market med en FaultException attribut. Markere du den med attributen vil din klient fejle næste gang du opdatere service referencen.

Jeg lavede en "Set as start page" på min test side i mit silverlight hosting website og kørte debuggeren. Op kom et billede.

Jeg har lavet nogle ekstra features i applikationen som jeg har vist her pga. længden af posten, men hvis du downloader koden kan du se hvad jeg mener 🙂


Comments (10)
  1. nikolajr says:

    Meget fint eksempel på brug af WCF og Silverlight. Men du behøver ikke at bruge clientaccesspolicy.xml og crossdomain.xml hvis din service og din SL-app ligger på samme domæne/server. Har man så alligevel brug for at kalde services på andre servere kan man blot lade SL-app’ens service kalde de andre services.

    Spørgsmål: Har du løst problemet med størrelsen af dine WCF service requests er begrænset. Jeg har lavet en app der bl.a. uploader billeder til en service host via SL. Lynhurtigt løber jeg ind en begrænsning i størrelsen på det billede, som jeg vil sende. Der er nogle indlæg der ude i clouden, men ingen hjælper.

  2. 出会い says:

    ヒマだょ…誰かかまってぉ…会って遊んだりできる人募集!とりあえずメール下さい☆ uau-love@docomo.ne.jp

  3. 小向美奈子 says:

    話題の小向美奈子ストリップを隠し撮り!入念なボディチェックをすり抜けて超小型カメラで撮影した神動画がアップ中!期間限定配信の衝撃的映像を見逃すな

  4. 話題の小向美奈子ストリップを隠し撮り!入念なボディチェックをすり抜けて超小型カメラで撮影した神動画がアップ中!期間限定配信の衝撃的映像を見逃すな

  5. カワイイ子ほど家出してみたくなるようです。家出掲示板でそのような子と出会ってみませんか?彼女たちは夕食をおごってあげるだけでお礼にHなご奉仕をしてくれちゃったりします

  6. あなたは右脳派?もしくは左脳派?隠されたあなたの性格分析が3分で出来ちゃう診断サイトの決定版!合コンや話のネタにも使える右脳左脳チェッカーを試してみよう

  7. セレブラブでは性欲のある男性を募集しています。セフレパートナーを探している20代・30代の女性たちが多数登録されています。セレブと遊びたい、Hがしたいという方は無料登録からどうぞ

  8. セレブ達は一般の人達とは接する機会もなく、その出会う唯一の場所が「逆援助倶楽部」です。 男性はお金、女性はSEXを要求する場合が多いようです。これは女性に圧倒的な財力があるから成り立つことの出来る関係ではないでしょうか?

  9. 貴方のオ○ニーライフのお手伝い、救援部でHな見せたがり女性からエロ写メ、ムービーをゲットしよう!近所の女の子なら実際に合ってHな事ができちゃうかも!?夏に向けて開放的になっている女の子と遊んじゃおう

Comments are closed.

Skip to main content