WCF címkéhez tartozó bejegyzések

WCF szolgáltatás publikálása IIS 8-on

Egy alapbeállításokkal telepített IIS 8-on nem működnek a WCF szolgáltatások, mégpedig azért, mert a webszerver nem tudja, hogyan kell kezelnie az .svc kiterjesztésre érkező kéréseket. Két lépésben taníthatjuk meg neki:

 

1. Vegyünk fel egy új MIME type-ot:

Extension: .svc
MIME type: application/octet-stream

iis8-svc-mime-type

 

2. Vegyünk fel egy Managed HTTP Handlert:

Request path: *.svc
Type: System.ServiceModel.Activation.HttpHandler
Name: svc-Integrated

iis8-svc-handler

És már működik is!

 

Technorati-címkék: ,,

WCF és REST – ahol mindenre van URI

Az alkalmazásintegráció területén a SOAP mellett egyre nagyobb szerepet kapnak a REST alapú megoldások. Mert kicsi, egyszerű, gyors. Egyszóval fapados. Nem csak az elkésztése, hanem a meghívása is, ami különösen akkor érdekes, ha a klienseink butábbak az átlagnál, például Ajaxos weboldalak vagy épp telefonok.

Ezt a területet a Microsoft már évekkel ezelőtt célba vette, és kiadta hozzá a WCF REST Starter Kitet. Még sosem hallottál róla? Hát valóban nem ez lett a világ leghíresebb terméke, de legalább elindította a céget egy olyan irányba, amelynek komoly mérföldköve lett a .NET4 és a héten a MIX’11 konferencián bejelentett WCF Web API.

A WCF Web API a WCF Futures csomagban érhető el, amely a következő területekre fókuszál:

  • REST – ez a WCF Web API
  • Kliensek – Ajax, jQuery, Silverlight, telefon
  • Felhő
  • Egyszerűsítés

Ezek közül a MIX-en két területtel kapcsolatban jelent meg újdonság.

1. A REST területen elérhetővé vált a WCF Web API Preview 4 verziója. Ennek az a célja, hogy az alkalmazásaink funkcióit egyszerűen nyithassuk meg HTTP felett a REST alapelveit követve. Itt egy olyan architektúrát kell elképzelni, ahol minden a HTTP-re van kihegyezve:

WCF-Web-API

2. A kliensek területén megjelent a RIA/JS, ami gyakorlatilag közvetlen WCF támogatást jelent a jQuery-hez:

WCF-jQuery

Ez még elég gyerekcipőben jár, de a BigShelf példa alkalmazáson már érezhető, hogy a $.dataSource és a DataLink jQuery pluginek mennyire egyszerűsítik a megírandó kliens oldali kódot.

Aki web API fejlesztéssel foglalkozik, annak mindenképp érdemes megnéznie az újdonságokat, mert a jelek szerint a REST a jövő.

 

Technorati-címkék: ,,

WCF Data Services vs Web Deployment Projects

Ha egy olyan Web Site projektet szeretnénk Web Deployment Projects segítségével összecsomagolni, amely egy WCF Data Services (OData) végpontot is tartalmaz, akkor sajnos az .svc fájl feldolgozása közben az alábbi hibába futhatunk bele:

Exception type: System.ServiceModel.ServiceActivationException    

Exception message: The service ‘/MyService.svc’ cannot be activated due to an exception during compilation. 

The exception message is: Could not load file or assembly ‘App_global.asax, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null’ or one of its dependencies. The system cannot find the file specified.

Inner exception type: System.IO.FileNotFoundException    

Elég idegesítő, de elég szép megoldást alkothatunk rá: szabaduljunk meg az egész .svc fájltól és használjunk helyette ASP.NET routingot!

Irány a global.asax, ahol regisztrálhatunk egy új route szabályt:

RouteTable.Routes.Add( "MyService",
  new ServiceRoute( "MyService", 
                    new DataServiceHostFactory(), 
                    typeof( MyService ) ) );

A WCF Data Service szolgáltatásunkat pedig a MyService osztályban implementáljuk:

public class MyService : DataService<MyDataModel>
{
  public static void InitializeService( DataServiceConfiguration config )
  {
    // Ide jön az inicializáló kód, jogosultságok, lapozás beállítása stb...
  }

  protected override void OnStartProcessingRequest( ProcessRequestArgs args )
  {
    base.OnStartProcessingRequest( args );

    // Cache és egyéb fejlécek beállítása...
  }
}

Az eredmény: működik a Web Deployment Projects és az URL-jeink is gyönyörűek.

WCF szolgáltatás IIS-en: 404 Page Not Found

Ebbe elég könnyű belefutni és pofonegyszerű a megoldás, csak nem biztos, hogy elsőre beugrik, ezért inkább leírom. Adott egy prímán megírt WCF szolgáltatás, ám amikor IIS-re telepítjük, nem működik. Böngészőben megnézve az .svc fájlt HTTP Error 404: Not Found fogad, pedig a fájl ott van. Csak szegény IIS nem tud róla.

A Windows Communication Foundationt ugyanúgy regisztrálni kell a webkiszolgálóba, mint az ASP.NET-et. ASP.NET esetén erre az aspnet_regiis.exe szolgál, WCF esetén pedig a ServiceModelReg.exe. Az ész nélküli telepítést ugyanúgy a –i kapcsoló szolgáltatja, a telepítés ellenőrzésére viszont a –vi kapcsolót kell használnunk. A ServiceModelReg.exe a .NET Framework 3.0 telepítése után a C:WindowsMicrosoft.NETFrameworkv3.0Windows Communication Foundation mappában található, futtatásához rendszergazdai jogok szükségesek.

CryptographicException: Keyset does not exist

Korábban CardSpace használatakor futottam bele a fenti hibaüzenetbe, most egy IIS-ben hosztolt WCF szolgáltatás készítésekor jött elő. Elvesztettem volna a kulcsaimat? A problémát az okozza, hogy a web.config fájlban szerepel egy tanúsítvány hivatkozás a <serviceCertificate> ágban, de az IIS worker process felhasználói fiókjának, alapértelmezés szerint a Network Service fióknak, nincs joga hozzáférni a tanúsítványhoz. De hogy adok egy tanúsítványra olvasási jogot?

A CardSpace esetén bemutatott megoldás persze most is működik: letöltjük a Web Services Enhancements (WSE) 3.0-t és a WseCertificate3.exe segítségével Read jogot adunk a felhasználónak.

Ha nincs kéznél WSE, akkor használhatjuk a WCF példák között elérhető Find Private Key Toolt (letölthető innen is). Listázhatjuk vele az egyes tanúsítványtárakban lévő tanúsítványokat. Legegyszerűbben így:

FindPrivateKey.exe My LocalMachine

Erre megkapjuk ezt:

Select Certificate ablak

A tanúsítvány kiválasztása után kattintsunk az OK gombra és máris megtudjuk, hol lakik a tanúsítvány:

FindPrivateKey.exe eredmény

Nincs más dolgunk, mint elnavigálni a megadott C:ProgramDataMicrosoftCryptoRSAMachineKeys mappába és a megadott 0a38f98… nevű fájl tulajdonságlapján a Network Service felhasználónak Read jogot adni. Nem kell több, elég a Read!

RSS generálás ASP.NET webalkalmazásban WCF alapokon

Webalkalmazások fejlesztésekor gyakran merül fel az igény, hogy a tartalmat RSS formában is publikálnunk kell. Erre számtalan megoldás létezik, a .NET Framework 3.5 megjelenése óta azonban közvetlen támogatást ad a keretrendszer a System.ServiceModel.Syndication névtér osztályainak segítségével.

A névtér nevéből látszik, hogy a WCF részeként kapjuk ezt a szolgáltatást és a weben számtalan példát látunk arra, hogy akár egy konzol alkalmazásban hogyan hozhatunk létre egy WCF alapú szolgáltatást, amely RSS formában válaszol, arra azonban alig van utalás, hogy ez a funkció közvetlenül használható egy ASP.NET-es webalkalmazásban is.

A nem-HTML jellegű válasz előállításához szerintem leginkább IHttpHandlert érdemes használni:

Visual Studio Add New Item: Generic Handler

Az IHttpHandler legfontosabb metódusa a ProcessRequest, amelyben közvetlenül a HttpContextbe kell beleírnunk a HTTP választ. Ha RSS 2.0 formában akarjuk visszaküldeni a választ és szeretnénk az elejére XML fejlécet, akkor azt megtehetjük például így:

    public void ProcessRequest( HttpContext context )
    {
        // XML válasz típus beállítása.
        context.Response.ContentType = "application/xml";

        // XML fejléc beírása a válasz elejére.
        XmlTextWriter writer = new XmlTextWriter( context.Response.Output );
        writer.Formatting = Formatting.Indented;
        writer.WriteProcessingInstruction( "xml", @"version=""1.0"" encoding=""utf-8""" );

        // SyndicationFeed sorosítása RSS 2.0 formátumban.
        this.BuildFeed().SaveAsRss20( writer );        
    }

Itt felhasználtam egy általam írt BuildFeed nevű segédmetódust, amely visszaadja az adatbázisban tárolt információk alapján összeállított SyndicationFeed objektumot.

A feed összeállítása az alap attribútumok beállításával kezdődik:

    SyndicationFeed feed = new SyndicationFeed
    {
        Title = SyndicationContent.CreatePlaintextContent( "MSDN Kompetencia Központ" ),
        Description = SyndicationContent.CreatePlaintextContent( "MSDN Kompetencia Központ RSS feedje" ),
        Copyright = SyndicationContent.CreatePlaintextContent( "Copyright (C) MSDN Kompetencia Központ" ),
        Language = "hu-HU",
        ImageUrl = new Uri( imageUrl ),
        Generator = "Cube"
    };

Az egyes elemeket a feed objektum Items gyűjteményébe kell felvennünk SyndicationItemek formájában. Az elemek összerakása az új C# szintaktikával szintén aránylag tömören megoldható:

    SyndicationItem item = new SyndicationItem
    {
        Title = SyndicationContent.CreatePlaintextContent( title ),
        Content = SyndicationContent.CreateHtmlContent( body ),
        PublishDate = date.ToUniversalTime(),
        Id = articleUrl
    };

Az itt felsoroltakon kívül még természetesen számos tulajdonságot tudunk megadni, melyek közül egyik-másik gyűjtemény, ilyen például a <link> tag:

    item.Links.Add( SyndicationLink.CreateAlternateLink( new Uri( articleUrl ) ) );

Az RSS egyik érdekessége, hogy a séma bővíthető, akár más névtérbe tartozó XML elemekkel. A .NET-es objektum modell erre is ad támogatást az ElementExtensions és AttributeExtensions tulajdonságokon keresztül. Például ha szeretnénk felvenni egy <comments> tag-et a generált XML-be, amely egy URL címre mutat, akkor arra nem találunk saját tulajdonságot, de így mégis megtehetjük:

    item.ElementExtensions.Add( "comments", null, commentsUrl );

Ha azonban azt is szeretnénk tárolni, hogy egy adott cikkhez hány hozzászólás tartozik, akkor egy slash:comments elemre lesz szükségünk, amihez a slash névteret definiálnunk kell az XML elején. Hasonló a helyzet akkor, ha a szerző nevét egy dc:creator elemben szeretnénk publikálni, szintén meg kell adnunk a névtér feloldását a feed elején:

<channel xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">

Ezt így tehetjük meg:

    feed.AttributeExtensions.Add( new XmlQualifiedName( "xmlns:dc" ), "http://purl.org/dc/elements/1.1/" );
    feed.AttributeExtensions.Add( new XmlQualifiedName( "xmlns:slash" ), "http://purl.org/rss/1.0/modules/slash/" );

Az értékek beszúrását pedig így:

    item.ElementExtensions.Add( "slash:comments", null, commentCount );
    item.ElementExtensions.Add( "dc:creator", null, userName );

Mindezekből látható, hogy tetszőleges szerkezetű XML-t össze tudunk állítani, az objektumok szabványos sorosításáról a SaveAsRss20 vagy SaveAsAtom10 metódus gondoskodik. Ahhoz, hogy az eredmény valóban szabványos legyen, célszerű használni a CreatePlaintextContent, CreateHtmlContent, CreateAlternateLink stb. metódusokat.

Bár a felhasznált osztályok olyan névtérben találhatóak, amelyek elvileg a WCF részei, ASP.NET esetén nincs szükség arra, hogy WCF endpointokat definiáljunk, közvetlenül használhatjuk ezeket az osztályokat egy HTTP handlerben és a kisorosított XML-t közvetlenül írhatjuk a válasz streambe.

Technorati Tags: ,,,,