Welcome to MSDN Blogs Sign in | Join | Help

Windows Azure SDK November 2009 ute nu!

I går släppte vi Windows Azure Software Development Kit (November 2009) och Windows Azure Tools for Microsoft Visual Studio (November 2009) samt tillhörande exempel.

Vad är det då som är nytt? Det första vi kan lägga märke till är att förkortningen CTP inte längre finns med i namnen vilket skvallrar som production quality. Bland funktioner som är nya eller förädlade kan nämnas;

  • Möjlighet till kommunikation mellan rollinstanser (SDK)
  • Nya API:er för loggning och hälsokontroll. (SDK)
  • Hantering av SSL certifikat (SDK)
  • Välj vilken typ av virtuell maskin du vill deploya din rollinstans på (SDK)
  • Externa ändpunkter på Worker Roles (SDK)
  • Skriv information till lokalt lagringsutrymme utan att riskera att informationen är borta när rollen startas om (SDK)
  • Ett “riktigt” Storage Client bibliotek för åtkomst till Azure Storage (Tables, Queues och Blobs) (SDK)
  • Förbättrat Development Storage. Inget mer “generate tables”  (SDK) – whoho!
  • Nya rolltyper: F# Worker, ASP.NET MVC 2, WCF Service (VSTools)
  • Stöd för Visual Studio 2010 Beta 2. Även Express. (VSTools)  - sweet!
  • Användargränssnitt för hantering av tjänstemodellen (VSTools)

Så nu är det bara att tanka ned, installera, labba, titta på PDC dragningar nästa vecka för att till slut husera production appar på Windows Azure.

VS2010 Express med Azure Tools

Posted by chrislof | 0 Comments
Filed under: ,

Kom igång med PHP på Windows Azure

På senare tid har vi på Microsoft introducerat ett antal initiativ för ökad interoperabilitet med PHP.  Det handlar bland annat om drivare för SQL Server, verktyg för att konsumera ADO.NET Data Services resurser och exekvering av PHP i Internet Information Services. Alla dessa är högst relevanta för PHP på Windows Azure men fungerar också lika bra på “vanliga” Windows. För utveckling ämnad Windows Azure har vi tillsammans med våra partners Soyatec och RealDolmen tagit fram två riktigt smaskiga bitar; Windows Azure SDK for PHP och Windows Azure Tools for Eclipse.

Windows Azure SDK for PHP

Windows Azure SDK for PHP är ett utvecklingspaket för Windows Azure och Windows Azure StorageBlobs, Tables och Queues. Funktioner är bland andra;

  • Klasser för CRUD operationer på Blobs, Tables och Queues
  • Hjälpklasser för HTTP-transport, felhantering, REST och säkerhet
  • Instrumentering och loggning
  • Hantering av PHP sessioner i Tables.

Windows Azure Tools for Eclipse

Windows Azure Tools for Eclipse är ett tillägg till Eclipse vilket ger bra verktygsstöd för utveckling av PHP applikationer för Windows Azure. Funktionerna är bland andra;

  • Projektmallar och migrering av projekt
  • Hantering av Windows Azure specifika begrepp som Roller och Tjänstedefinitioner
  • Storage Explorer – Hantera dina Windows Azure Storage konton (inkl innehåll)
  • Windows Azure project deployment – paketering av ditt projekt och publicering till portal eller Windows Azure Development Fabric

Windows Azure Tools for Eclipse inkluderar även Windows Azure SDK for PHP, vilket gör att du endast behöver installera ett paket och är därmed snabbt igång.

Windows Azure Tools for Eclipse

(Klicka för större bild)

Om du är en PHP utvecklare som använder andra verktyg än Eclipse för att skriva din kod, (kanske Vim , Emacs eller Notepad) så är du inte portad från Windows Azure för det. Du kommer dock troligen få ägna lite mer tid åt att paketera och hantera dina Windows Azure projekt med CSPack, CSRun, DSInit och hålla tungan rätt i munnen än om du använder Windows Azure Tools for Eclipse.

Avslutningsvis

Att enhetstesta WCF-tjänster

Jag möts gång på gång av tappra försök till att “enhetstesta” WCF tjänster där det i själva verket har resulterat i mer eller mindre komplexa integrationstester. Anledningarna till detta har oftast sin grund i att det man byggt nyttjar WCF:s OperationContext eller ServiceSecurityContext för att hämta information från inkommande meddelande eller anropande användare.

OperationContext och ServiceSecurityContext instansieras av WCF hosten och är således inte tillgängliga utanför WCF:s exekveringskontext. Lösningen på detta anses därför i många fall  vara att helt enkelt bygga “enhetstester” som hostar aktuell WCF-tjänst för att på så vis få tillgång till OperationContext och ServiceSecurityContext instanserna. Jag säger inte att detta är fel. Däremot vill jag absolut kalla denna typ av tester för Integrationstester. Man testar helt enkelt sin tjänst tillsammans med övriga komponenter av vilka man inte har full kontroll över.

Låt mig visa ett exempel. Nedan operation returnerar ett klasiskt “Hello” med användarnamnet på anropande användare.

[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public string Hello() {

    var user = ServiceSecurityContext.Current.WindowsIdentity.Name;
    return "Hello " + user;

}

Ur ett enhetstestperspektiv finns det två problem med ovan “enkla” operation.

  1. ServiceSecurityContext.Current kommer vara null om operationen inte exekverar inom en WCF host.
  2. Om man istället sätter upp ett integrationstest för att få fatt i en instans av ServiceSecurityContext så kommer WindowsIdentity.Name returnera användarnamnet på det konto som exekverar testet. Dvs synnerligen svårt att skriva ett test som alltid är sant.

Hur skall jag då göra för att verkligen kunna enhetstesta ovan operation? Som i många andra sammanhang med enhetstestning så får jag helt enkelt addera en abstraktion på, i detta fall, ServiceSecurityContext för att kunna ersätta implementationen med en Mock eller Stub. Det som kan röra till det hela i WCF':s fall är att ServiceSecurityContext inte implementerar något Interface eller basklass som jag kan utgå ifrån. Jag börjar således med att skapa ett Interface som ser likadant ut som ServiceSecurityContext.

namespace Chrislof.ServiceModel.Abstractions {
    
    public interface IServiceSecurityContext {

        AuthorizationContext AuthorizationContext { get; }

        ReadOnlyCollection<IAuthorizationPolicy> AuthorizationPolicies { get; }

        bool IsAnonymous { get; }

        IIdentity PrimaryIdentity { get; }

        IWindowsIdentity WindowsIdentity { get; }

    }
}

Detta Interface implementerar jag sedan i en sk Wrapper. Denna wrapper-implementation tar en referens till aktuellt ServiceSecurityContext och vidarebefordrar endast anropen till den “riktiga” ServiceSecurityContext instansen.

namespace Chrislof.ServiceModel.Abstractions {
    /// <summary>
    /// Decorates the <see cref="ServiceSecurityContext"/> for testability
    /// </summary>
    public class ServiceSecurityContextWrapper : IServiceSecurityContext
    {
        private readonly ServiceSecurityContext _context;

        public ServiceSecurityContextWrapper(ServiceSecurityContext context) {

            context.ArgumentNotNull("context");
            _context = context;
        }

        public AuthorizationContext AuthorizationContext {
            get { return _context.AuthorizationContext; }
        }

        public ReadOnlyCollection<IAuthorizationPolicy> AuthorizationPolicies {
            get { return _context.AuthorizationPolicies; }
        }

        public bool IsAnonymous {
            get { return _context.IsAnonymous; }
        }

        public IIdentity PrimaryIdentity {
            get { return _context.PrimaryIdentity; }
        }

        public IWindowsIdentity WindowsIdentity {
            get { return new WindowsIdentityWrapper(_context.WindowsIdentity); }
        }
    }
}

För att nyttja ovan ServiceSecurityContextWrapper i min tjänsteimplementation adderar jag en constructor och ett privat fält som håller referensen till wrappern.

public Service(IServiceSecurityContext securityContext) {
    _securityContext = securityContext;
}

Hello-operationen justeras till följande.

[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public string Hello() {

    var user = _securityContext.WindowsIdentity.Name;
    return "Hello " + user;

}

Detta gör att jag nu kan tilldela min tjänst med ett ServiceSecurityContext som jag har full kontroll över inom ramen av mitt enhetstest. Jag använder i nedan exempel ramverket Moq för att skapa en ServiceSecurityContext-stub som returnerar mitt användarnamn.

[TestMethod]
public void Hello_WhenCalled_ReturnsHelloWithCurrentUser() {

    const string user = "Chrislof";

    var securityContext = new Mock<IServiceSecurityContext>();
    securityContext.SetupGet(x => x.WindowsIdentity.Name).Returns(user);
    
    var service = new Service(securityContext.Object);

    var response = service.Hello();

    Assert.AreEqual("Hello Chrislof",response);

}

Ovan konstruktor som kräver en parameter är inget som WCF diggar alls som standard. (Se tidigare artikel ang detta) Jag behöver dessutom få WCF att ge mig en instans av min ServiceSecurityContextWrapper. Det absolut enklaste sättet att lösa detta är att infoga en defaultkonstruktor utan parametrar och i den instansiera ServiceSecurityContextWrapper.

public Service() : 
    this(new ServiceSecurityContextWrapper(ServiceSecurityContext.Current)) {}

Ovan exempel finns att ladda ned här nedan. Projektet inkluderar även ett mer avancerat scenario med en ServiceAuthorizationManager. Använd gärna mina Abstraktions-klasser men kom ihåg – de kommer as-is utan någon som helst garanti eller support.

Happy testing!

Posted by chrislof | 0 Comments
Filed under: , , ,

Routing med WCF 4

Att införa en eller flera sk Message Routers i sin tjänsteorienterade lösning görs av olika anledningar. Vanligtvis rör det sig om mer avancerade behov som att kunna brygga mellan protokoll och transport sätt, versionshantera kontrakt, centraliserad säkerhetshantering med mera. Den grundläggande förmågan som Routern har för att möjliggöra allt detta är att inspektera inkommande meddelande och sedan skicka det vidare till definierad mottagare baserat på ett regelverk.

WCF 4 tillhandahåller en färdig Routing-tjänst - Det du behöver göra är att konfigurera den efter dina behov.

Content Based Routing

Som jag skrev ovan bygger Routerns förmågor på att kunna skicka vidare ett inkommande meddelande till en definierad måltjänst. I mitt exempel denna gång visar jag vad som kallas för Content Based Routing – dvs inspektera meddlandekroppen (läs Body) och skicka sedan vidare meddelandet baserat på meddelandeinnehåll.

routing

Konsumenten (C) har en Proxy baserad på en ordertjänsts kontrakt (S). Istället för att ansluta till ordertjänstens ändpunkt så ansluter konsumenten till Routern (R). Routern kontrollerar om meddelandet kommer från en Premiumkund och skickar i sådant fall meddelandet vidare till en ordertjänst specifik för just Premiumkunder - 15% rabatt!. (I ett mer “riktigt” scenario skulle det kanske snarare röra sig om SLA-nivå eller liknande istället för en så enkel sak som rabatt.)

Det första som behöver göras är naturligtvis att exponera Routing-tjänsten. Det finns ett par olika kontrakt att välja på beroende på det kommunikationsmönster du önskar – Message Exchange Pattern. I detta fall använder jag IRequestReplyRouter. Implementationen RoutingService är densamma för alla tillgängliga kontrakt.

<services>
  <service behaviorConfiguration="routing" name="System.ServiceModel.Routing.RoutingService">
    <host>
      <baseAddresses>
        <add baseAddress="http://localhost:8080/router"/>
      </baseAddresses>
    </host>
    <endpoint
      name="basic"
      address="basic-request-reply"
      binding="basicHttpBinding"
      contract="System.ServiceModel.Routing.IRequestReplyRouter"/>
  </service>
</services>

Nästa steg är att definiera de ändpunkter som Routern skall kunna skicka vidare meddelanden till.

<client>
  <endpoint
    name="premiumCustomer"
    address="net.tcp://localhost:8091/orders/premium-customer"
    binding="netTcpBinding"
    contract="*"/>
  <endpoint
    name="ordinaryCustomer"
    address="http://localhost:8090/orders/ordinary-customer"
    binding="basicHttpBinding"
    contract="*"/>
</client>

Så långt är det inga konstigheter – Det är nu det balla börjar på riktigt.

Hjärtat i Routing-tjänsten är vad som kallas Filter Tables och Filters. Det är helt enkelt där jag definierar regelverket för hur meddelanden skall tolkas och skickas vidare. Jag vill i mitt exempel genomsöka meddelandekroppen efter kundnamnet “VS2010” och agera därefter. För att göra det använder jag filtertypen XPath. Det finns även här ett antal alternativ.

<routing>
  <namespaceTable>
    <add prefix="c" namespace="urn:chrislof-examples"/>
  </namespaceTable>
  <filters>
    <filter name="ordinaryCustomerFilter" filterType="XPath" filterData="//c:customerName != 'VS2010'"/>
    <filter name="premiumCustomerFilter" filterType="XPath" filterData="//c:customerName = 'VS2010'"/>
  </filters>
  <filterTables>
    <filterTable name="filterTable">
      <add filterName="ordinaryCustomerFilter" endpointName="ordinaryCustomer"/>
      <add filterName="premiumCustomerFilter" endpointName="premiumCustomer"/>
    </filterTable>
  </filterTables>
</routing>

I filtertabellen definierar jag vilken ändpunkt meddelandet skall skickas vidare till om specificerat filter returnerar en match.

Dags att provköra!

Jag tycker mig behöva en ny Laptop och lägger därmed en order på en ny.

Place order

Routern anser inte att jag är en Premiumkund och skickar således ordern vidare till OrdinaryOrderService.

image

När jag istället beställer en Server i namnet VS2010 skickar Routern beställningen till PremiumOrderService och ger mig därmed 15% rabatt.

Place order

image

Avslutningsvis

Precis som med Discovery är ovan möjligt att implementera med WCF 3.x. Ett lysande exempel på det är Managed Services Engine. Det är dock nu med WCF 4 betydligt enklare att implementera flera av dessa förmågor som MSE:n besitter på egen hand.

Exemplet kan du ladda ned här. (Kräver VS2010 Beta 2)

Posted by chrislof | 0 Comments
Filed under: , ,

Förändringar mellan WF4 Beta 1 och Beta 2

Få har nog missat att Visual Studio 2010 Beta 2 och .NET Framework 4 Beta 2 släpptes till MSDN prenumeranter igår.

Beta 2 innehåller en hel del förändringar baserade på kommentarer från er Betatestare världen över. Förändringar gällande Windows Workflow Foundation (WF) har Matt Winkler beskrivit i två alldeles strålande artiklar.  Den första beskriver generellt om förändringar i ramverket  medans den andra fokuserar på förändringar gjorda i designern (tack).

Tycker du som jag ? – Det är en spännande tid just nu :)

Jag vet.. Det är för enkelt att bara länka vidare.
Posted by chrislof | 0 Comments
Filed under: , ,

WS-Discovery med WCF 4

Att WCF 4 nu kommer med stöd för WS-Discovery protokollet tycker jag är en riktig höjdare. Protokollet i sig är ingen nyhet men det är först i .NET 4.0 som WCF-stacken levereras med detta direkt "från fabrik".

Med hjälp av WS-Discovery kan tjänster och konsumenter kommunicera och hitta varandra utan något behov av tjänsteregister eller liknande.

Hur fungerar det då?

I mitt exempel (som jag lånat från WS-Discovery specifikationsdokumentet) har jag en konsument som söker efter en skrivare. Förfrågan skickas ut på nätverket och till svar får jag en lista med Endpoints som påstår sig implementera det kontrakt jag specificerat i min förfrågan (Probe).

discovery-probe

Det första jag måste göra för att få fart i detta är att skapa två sk DiscoveryEndpoints; en på konsumentsidan och en på tjänstesidan. Denna typ av Endpoint finns med i WCF 4's uppsättning av sk Standard Endpoints varför jag endast behöver lägga till ett Endpoint-element och sätta dess nytillkomna Kind egenskap i konfiguration. Adresser , Bindningar och Kontrakt (som vi är vana vid att definiera på en Endpoint) hanterar WCF åt oss på Standard Endpoints.

<endpoint kind="udpDiscoveryEndpoint" />

Ovan: Endpoint-definition tjänst.

var discoClient = new DiscoveryClient(new UdpDiscoveryEndpoint());
var criteria = new FindCriteria(typeof(IPrintService));
var result = discoClient.Find(criteria);

var numberOfPrintersFound = result.Endpoints.Count;

Ovan: Konsument skickar förfrågan efter en skrivare

Oftast är det ju också som så att jag söker efter en mer specifik skrivare. Vi har trots allt sju våningsplan på vårat kontor i Kista och det vore ju angenämt om min utskrift kunde hamna på en skrivare på det våningsplan jag anger. Ibland söker jag även efter en skrivare som klarar att skriva ut i färg.

Denna typ av sökkriterier definieras i form av Scopes och Extensions. Dessa egenskaper kan tjänsterna exponera och när jag skickar en förfrågan om tjänst som uppfyller mina ställda kriterier så kommer jag endast få svar från tjänster som har matchande egenskaper definierade.

I nedan exempel påstår skrivaren att den är lokaliserad på plan 3...

<endpointBehaviors>
  <behavior>
    <endpointDiscovery>
      <scopes>
        <add scope="ldap:///ou=floor3,ou=kista,o=chrislof-example,c=local"/>
      </scopes>
    </endpointDiscovery>
  </behavior>
</endpointBehaviors>

... Och konsumenten adderar ett Scope med samma värde i sin förfrågan.

var criteria = new FindCriteria(typeof(IPrintService));
criteria.Scopes.Add(new Uri("ldap:///ou=floor3,ou=kista,o=chrislof-example,c=local"));

I WS-Discovery finns det också funktionalitet definierad så att tjänster kan notifiera varandra om sin existens (Announce). Det handlar i praktiken om att skicka ut notifiering om "Hej! Jag har startat upp nu - och jag finns på denna adress" alternativt "Vill bara tala om att jag stängs ned nu...". Även detta är i WCF 4 implementerat med Standard Endpoints, vilket gör det väldigt enkelt att anamma.

discovery-announce

Den lilla detaljen som jag måste beaktas är att Announcement-Endpointen måste definieras genom ett ServiceDiscovery-behavior. Men detta är allt som jag behöver göra på tjänstesidan.

<serviceBehaviors>
  <behavior>
    <serviceDiscovery>
      <announcementEndpoints>
        <endpoint kind="udpAnnouncementEndpoint" />
      </announcementEndpoints>
    </serviceDiscovery>
  </behavior>
</serviceBehaviors>

På konsumentsidan behöver jag instansiera AnnouncementService och lyssna på dess Events OnlineAnnouncementReceived och OfflineAnnouncementReceived för att kunna agera därefter. Jag behöver även exponera denna tjänst med en Announcement Standard Endpoint.

Konsument och Tjänst - och nu en Konsument som exponerar en Tjänst? Nja - Tjänster kan också vara konsumenter samt vice versa.

var announcementService = new AnnouncementService();

announcementService.OfflineAnnouncementReceived += (o, e) => 
    Console.WriteLine("Bye {0}", e.AnnouncementMessage.EndpointDiscoveryMetadata.Address);

announcementService.OnlineAnnouncementReceived += (o, e) =>
    Console.WriteLine("Hi! {0}", e.AnnouncementMessage.EndpointDiscoveryMetadata.Address);

Så om jag knyter an till mitt tidigare exempel med skrivaren - så får jag i detta fall en notifiering om att skrivaren stängs av.

announce

Hela tiden i ovan exempel är det sk Ad Hoc Discovery (utan mellanhand) som används. Detta begränsar användandet till det lokala nätet då det är baserat på multicast meddelanden. För att möjliggöra Discovery över t ex Internet måste en sk Discovery Proxy Service implementeras. Denna tjänst är inget som vid skrivandets stund levereras färdigt utan måste implementeras manuellt med utgångspunkt från DiscoveryProxyBase. När man använder denna modell, med en Discovery Proxy , kallas det för Managed Discovery.

Att visa hur man implementerar en Discovery Proxy är utanför omfattningen av denna artikel.

Ladda ned ovan exempel här:

Posted by chrislof | 1 Comments
Filed under: , ,

Introduktion till SOA Advanced Application Blocks

SOA Advanced Application Blocks är en samling av applikationsblock (á la Enterprise Library) som är baserade på mönster som vi konsulter har samlat på oss, tillsammans med partners och kunder, genom engagemang vid framtagandet av tjänsteorienterade lösningar.

Applikationsblocken ämnar att hjälpa den enskilda utvecklaren vid implementeringen av applikationer som skall ingå i en tjänsteorienterad arkitektur genom att bidra med byggstenar för förmågor som ofta efterfrågas. Applikationsblocken kan användas tillsammans eller var för sig. Undantaget är Service Agent applikationsblocket som är beroende av Directory Service applikationsblocket.

Följande applikationsblock är del av SOA Advanced Application Blocks

Untitled3

Requestor Side Caching Application Block

Detta applikationsblock möjliggör caching av responsmeddelanden från tjänster och har stöd för både offline och online scenarion.

Directory Service Application Block

Detta applikationsblock möjliggör dynamisk namnupplösning av ändpunktsadresser från en central tjänstekatalog, vilket medför en lös koppling mellan klientapplikationen och den faktiska platsen för en ändpunkt.

Policy Service Application Block

Detta block möjliggör en centraliserad hantering av regler (läs Policy) som är associerade med tjänster. Dessa regler kan hanteras och appliceras på tjänster i runtime.

Service Agent Application Block

Tjänsteagenten (läs Service Agent) utökar det sk Proxy-mönstret genom att tillföra ytterligare förmågor med hjälp av de övriga applikationsblocken. Det gör det t ex möjligt för klienten att dynamiskt hitta platsen för en ändpunkt och därefter konfigurera bindningarna att möta kraven som ställs av tjänstens definierade regler.

Jag kommer i en artikelserie framöver gå in mer i detalj på varje enskilt applikationsblock.

Posted by chrislof | 0 Comments
Filed under: , , ,

Förenklad konfiguration med WCF 4

När jag med WCF 3.x väljer att generera en Proxy med hjälp av svcutil eller Add Service Reference i Visual Studio så läggs det till en hel del konfiguration i .config-filen. Mycket av denna information kan jag, som oftast, ta bort. Det som minst måste vara kvar är definitionerna av den adress, binding och det kontrakt som tjänsten jag skall konsumera använder - vilket kan rymmas på tre rader. Men även dessa tre rader konfiguration är något som jag upplever som hinder för många för att vilja ta till sig WCF.

En glädjande nyhet för alla, oavsett om du hoppat på WCF tåget eller inte, är att vi med WCF 4 inte behöver ha ens ett system.serviceModel element i vår .config-fil för att göra en tjänst åtkomlig för konsumtion. Det är lite som med XP Mode i Windows 7 - det finns ingen anledning längre att inte uppgradera.

Default Endpoints

Grunden till detta är något som kallas för Default Endpoints - baserat på mitt val av protokollschema bygger WCF-stacken upp mina Endpoints automatiskt.

Titta på nedan exempel. Förutom tjänstekontraktet MotorbikeService är detta allt som min applikation nu består av. Ingen app.config för att definiera tjänsten eller dess Endpoints , och allt jag behöver göra i koden är att ange de URI:er där jag vill ha tjänsten exponerad.

static void Main(string[] args) {

var host = new ServiceHost(typeof(MotorbikeService),
new Uri("http://localhost:8080/bikeStore"),
new Uri("net.tcp://localhost:8081/bikeStore"));
host.Open();

foreach (var endpoint in host.Description.Endpoints) {
Console.WriteLine(string.Format("{0} - {1}", endpoint.Address, endpoint.Binding.Name));
}

Console.Read();
host.Close();
}

När jag väljer att köra applikationen så ser vi också vilka Bindings WCF-stacken har valt åt mig, baserat på ändpunkternas protokollscheman.

BasicHttpBinding

Mappningarna mellan protokollschema och Binding är definierade i machine.config. Vill du t ex ändra standard Binding för http-schemat till en Binding med stöd för WS-* protokollen så kan du göra det på maskin nivå men också på applikationsnivå i app.config.

Nu, när jag går ifrån WCF:s standardkonventioner, behöver jag lägga till system.serviceModel-elementet i min app.config. Därefter ändrar jag mappningen från BasicHttpBinding till WS2007Binding i protocolMappings-elementet.

<system.serviceModel>
<!--
ändra default binding för http-schemat till ws2007HttpBinding -->
<
protocolMapping>
<
add scheme="http" binding="ws2007HttpBinding"/>
</
protocolMapping>
</
system.serviceModel>

Kör jag applikationen igen så ser vi att WCF-stacken nu bygger upp en WS2007Binding åt mig istället.

WS2007Binding

Alla mina tjänster som är exponerade över en HTTP-Endpoint kommer nu att använda WS2007Binding:en med dess standardinställningar. För att göra justeringar i dessa standardinställningar behövde jag i WCF 3.x överrida dem med en explicit Binding-konfiguration per Endpoint. Med WCF 4 kan jag nu överrida standardinställningarna på en Binding genom att definiera en namnlös Binding-konfiguration.

<system.serviceModel>
<!--
ändra default binding för http-schemat till ws2007HttpBinding -->
<
protocolMapping>
<
add scheme="http" binding="ws2007HttpBinding"/>
</
protocolMapping>
<
bindings>
<
ws2007HttpBinding>
<!--
flödande transaktioner som default -->
<
binding transactionFlow="true"/>
</
ws2007HttpBinding>
</
bindings>
</
system.serviceModel>

Förenklad IIS hosting

För att husera WCF-tjänster i IIS:en så är vi vana vid att skapa en .svc-fil som pekar ut vilken tjänst som skall hantera förfrågan. Med WCF 3.x räckte det inte att skapa denna fil – vi var även tvungen att definiera minst en Endpoint i web.config. Detta är med WCF 4 historia -  jag lägger dit min .svc-fil och är därmed klar att erbjuda tjänsten för konsumtion.

<%@ ServiceHost Service="ByeAsmx.MotorbikeService" %>

Om du minns min förra artikel om WCF 4 så har jag nu också ett frestande val att lägga till system.serviceModel-elementet i web.config och därmed slopa .svc-filen.

<system.serviceModel>
<
serviceHostingEnvironment>
<
serviceActivations>
<
add relativeAddress="/BikeStore" service="ByeAsmx.MotorbikeService"/>
</
serviceActivations>
</
serviceHostingEnvironment>
</
system.serviceModel>
inge .svc

.svc-fil eller Address Activation för dina asmx-ersättare?

Exempelkod finns att ladda ned här.

Posted by chrislof | 0 Comments
Filed under: ,

Principer för tjänstedesign

Nyttan med Tjänster är som störst när de återanvänds om och om igen. Detta är en av anledningarna till varför Webbtjänster (oftast SOAP/HTTP) är ett populärt sätt att implementera dessa Tjänster - det ger oss nåbarhet från många olika plattformar. Med nåbarheten kommer också möjligheten till återanvändning.

Allt för sällan finns det ett gemensamt register över tillgängliga tjänster. Men även om det skulle finnas ett register krävs det att man förhåller sig till ett antal principer för att hjälpa konsumenterna att hitta rätt tjänst och slutligen rätt operation(er) i detta register.

Jag har i denna artikel sammanställt de principer som jag anser är de viktigaste att anamma för att maximera återanvändningen av enskilda tjänster.

Namnge för konsumtion

Använd namn och begrepp som är bekanta för de som skall konsumera tjänsterna. Oftast är begrepp från den aktuella domänen mer meningsfulla för konsumenten än tekniska begrepp.

En tumregel kan också vara att använda substantiv till tjänstenamn och verb till operationsnamn.

public interface IManageMotorbikeData
{
    int InsertMotorbikeRecord();

    bool UpdateMotorbikeRecord();
}

Ovan: Tjänstedefinition som använder verb och IT-begrepp.

Nedan: Tjänstedefinition som använder substantiv och verb från verksamhetsdomänen.

public interface IMotorbikeService
{
    Motorbike CreateNewMotorbike();

    Parts UpgradeBikeWithCarbonParts(Motorbike motorbike);
}

Balansera antalet operationer per tjänst

Hitta en bra balans mellan antal tjänster och antal operationer per tjänst.

En tjänst blir ofta den enhet som testas och till slut släpps för konsumtion, vilket gör att tjänster med stort antal operationer kan påverka många konsumenter samt att de tar längre tid att testa och kvalitetssäkra. Har man istället många tjänster med få operationer per tjänst kan det bli svårare att hitta tjänsten med önskad operation.

Tjänsterna skall vara sammanhängande

Detta hänger till viss del ihop med föregående princip. Designa tjänsterna på så vis att dess operationer hör ihop. Vad som gör att de hänger ihop kan dock variera. Det kan t ex röra sig om;

  • Operationerna skall täcka de funktioner som behövs för att uppfylla ett scenario
  • Operationer som skall täcka de funktioner som kan utföras på en viss typ av entitet
  • En konsument har efterfrågat en tjänst med en specifik uppsättning operationer

Använd grovkorniga parametrar

Att definiera "grovkorniga" parametrar för en operation medför flera fördelar. För det första blir den enklare att använda. För det andra underlättare det kommande versionshantering av tjänstekontraktet då en förändring i datastrukturen inte behöver förändra signaturen på operationen.

int CreateNewMotorbike(string name, string brand, string color, double price);

Ovan: Finkorniga parametrar

Nedan: Grovkorniga parametrar

Motorbike CreateNewMotorbike(MotorbikeDetails newMotorbike);

Men tänk på..

När många i din organisation tycker att det fungerar kanon med Webbtjänster och vill ha mer och antalet konsumenter ökar - det är då problemen med konsumtion brukar uppenbara sig. Hur avvecklar vi en tjänst? Hur uppgraderar vi en tjänst från v1 till v2 utan att behöva uppdatera 20 konsumerande system? Rekommendationen är att samtidigt som du tar till dig ovan principer överväger att implementera ett virtualieringslager. Why Service Virtualization Matters är ett utmärkt whitepaper som introducerar dig till just detta.

Posted by chrislof | 0 Comments
Filed under: ,

Kom och prata Azure med mig på Microsoft Summit

Den 1:a oktober huserar vi Microsoft Summit på Kistamässan.

Jag kommer finnas på plats under dagen för att diskutera dina tekniska frågor rörande Azure Services Platform.

- Hur migrerar vi bäst applikation x till Windows Azure?
- Skulle .NET Service Bus kunna hjälpa oss i sammanhang y?
- SQL Azure eller Windows Azure Storage?

Vill du vara helt säker på att få en pratstund med mig så rekommenderar jag att du bokar en tid.

REST med WCF 4 Beta 1

Med WCF 4 introduceras en hel del nyheter. Denna artikel fortsätter på det REST-tema jag påbörjade tidigare och fokuserar specifikt på vad som är nytt i WCF 4 Beta 1 som hjälper oss i byggandet av REST-tjänster. Inte helt oväntat är det till stor del funktionalitet som vi känner igen från REST Starter Kit som nu hittat in i själva ramverket. Någonting säger mig att så kommer det också fortsatt vara vid Beta 2 lanseringen men, det är bara en personlig gissning.

Hjälpsida

Hjälpsidan är i själva verket en Atom Feed. De flesta Web Browsers har dock någon form av Feed läsare i sig, vilket du kan se i nedan exempel där Internet Explorer visar Feed:en i ett läsbart format, vilket gör att du väldigt enkelt kan se tjänstens exponerade resurser. Vidare ger hjälpsidan information om URI-format, responsformat, exempel på responstyper etc. Skriv in “help” efter tjänstens basadress för att visa hjälpsidan.

Då hjälpsidan är en Atom Feed innebär det också att du har möjlighet att programmatiskt prenumerera på hjälpsidans innehåll om du så önskar.

Men hur aktiverar man det då?

Saken är den att funktionen är aktiverad som standard. Det är webHttpBehavior som har begåvats med ytterligare en egenskap - enableHelp, vilken är satt till “true” som standard av WebServiceHost.

<endpointBehaviors>
  <behavior name="HelpBehavior">
    <webHttp enableHelp="true" />
  </behavior>
</endpointBehaviors>

WAS aktivering av tjänster utan .svc-fil.

RESTafarier kan inte tolerera URL:er som inte "ser snygga ut", eller är RESTfulla. De kommer gilla detta.

Med WCF 3.5 sker WAS aktivering av en tjänst mha en .svc fil, vilket i detta fall genererar en URI enligt nedan.

I WCF 4 kommer möjligheten att göra denna aktivering baserat på en relativ adress. I följande exempel har jag angivit att den relativa adressen "/Customers" skall aktivera min tjänst “CustomerService”. På så vis kan jag nu tydligare få till exponeringen av min kollektion av kunder.

Så, kasta din .svc fil och lägg till detta i web.config istället:

<serviceHostingEnvironment>
  <serviceActivations>
    <add relativeAddress="Customers" service="NoSvcFile.CustomerService" 
         factory="System.ServiceModel.Activation.WebServiceHostFactory"/>
  </serviceActivations>
</serviceHostingEnvironment>

HTTP Caching

En av fördelarna med REST är att du kan dra nytta av HTTP infrastruktur för Caching, t ex IIS:ens output cache. Detta sker i WCF 4 med en integration gjord till ASP.NET:s Caching förmågor. Med det nya attributet AspNetCacheProfile kan du ange vilken Cache Profile du vill använda för specifik operation.

[OperationContract]
[WebGet]
[AspNetCacheProfile("defaultCacheProfile")]
public List<Customer> GetCustomers() {

Definiera sedan Cache Profilen i web.config som vanligt.

<system.web>
  <compilation debug="true" targetFrameworkMoniker=".NETFramework,Version=v4.0"/>
  <caching>
    <outputCacheSettings>
      <outputCacheProfiles>
        <add name="defaultCacheProfile" duration="10" varyByParam="*"/>
      </outputCacheProfiles>
    </outputCacheSettings>
  </caching>
</system.web>

Exempelkod

Ladda ned exempel för ovan här:

Posted by chrislof | 0 Comments
Filed under: , ,

Kanban med Team Foundation Server på 15 minuter

Det börjar ploppa upp en del verktyg på nätet för att hålla koll på sina projekt med hjälp av ett sk Kanban Board. Idén i sig härstammar från Taiichi Ohno's produktionssystem med ursprung hos Toyota. Jag dyker inte in djupare än så i historien och mina tankarna kring Kanban och Lean. Med denna artikel vill jag bara påvisa att man kan tillämpa detta även med Team Foundation Server. Jag visar här hur du med enkla sätt kan skapa er ett Kanban Board utan att behöva bygga processmallar och liknande. Allt som krävs är lite Reporting Services kunskap.

-Ett Kanban Board tack.
-15 minuter en kvart kompis.

Go!

0 min

Teamprojekt baserat på processmallen MSF for Agile Software Development 5.0 finns skapat sedan tidigare. Jag är även med i nödvändiga SQL roller.

1 min

Jag sätter upp Areas och Iterations för att använda som processteg och User Story status.

clip_image001clip_image002

Siffran innan namnet på processteget är endast till för sorteringens skull i rapporten. Siffran inom parantes anger gränsvärdet för maximalt antal User Stories för det steget. Stegen och gränsvärdena är helt plockade ur luften för denna demonstrations skull!

2 min

Jag skapar ett Report Server projekt ...

clip_image001[4]

... och en rapport.

clip_image002[4]

2:30 min

Jag lägger till en datakälla till rapporten...

clip_image001[6]

... och ett Dataset.

clip_image002[6]

Som fråga för Dataset:et anger jag SQL utrycket:

SELECT 
    System_Id, 
    System_Title,
    IterationName,
    AreaName,
    System_AssignedTo,
    Microsoft_VSTS_Scheduling_StoryPoints,
    Microsoft_VSTS_Common_StackRank
FROM
    CurrentWorkItemView
WHERE
    System_WorkItemType = 'User Story' AND
    System_State = 'Active'
ORDER BY
    ISNULL(Microsoft_VSTS_Common_StackRank,9999),
    System_Id

4 min

Dags att bygga rapporten!

Jag släpar först ut en List-kontroll från verktygslådan. Sedan tar jag bort ev Row Group och lägger till fältet IterationName som en Column Group.

clip_image001[8]

Jag släpar sedan ut ytterligare en List-kontrol som jag lägger i detaljarean på den första listan. Denna skall lista alla User Stories för aktuellt processteg.

I listan lägger jag sedan en Rectangle-kontroll för som skall agera Story Card. I denna Rectangle-kontroll lägger jag fälten System_Id, System_Title, Assigned_To och Microsoft_VSTS_Scheduling_StoryPoints. Jag har nu en rapport som i designern ser ut på följande sätt:

clip_image002[8]

7 min

Att illustrera statusen på en User Story väljer jag att göra genom att sätta bakgrundsfärgen på Rectangle-kontrollen. Är Story:n Blocked, dvs ingen gör något annat än att försöka lösa problemet, skall bakgrunden vara röd. Är Story:n Ready, dvs någon kan ta Story:n vidare till "sitt" steg, skall bakgrunden vara grön. I övriga skall bakgrunden vara gul.

Detta löser jag genom att ange ett utryck för Rectangle-kontrollens bakgrundsfärg.

clip_image001[10]

=IIf(Fields!AreaName.Value = "Blocked", "Firebrick", IIf(Fields!AreaName.Value = "Ready", "PaleGreen", "Khaki"))

9 min

Sätter lite kantfärger och fontstilar.

För att kunna klicka på en User Story och därmed få fram aktuellt Work Item, sätter jag Action egenskapen på System_Title textboxen till Go to URL. URL:en jag anger är till TFS Web Access Work Item Editor.

clip_image001[12]

="javascript:void(window.open('http://tfs/sites/DefaultCollection/project/_layouts/tswa/UI/Pages/WorkItems/WorkItemEdit.aspx?id=" & Fields!System_Id.Value & "'))"

11 min

Deploy till Reporting Services. Inga konstigheter.

13 min

Jag möblerar om på projektets standard Dashboard.

15 min

Klart!

clip_image001[14]

TFS måste vara det bästa sedan skivat bröd?

Posted by chrislof | 0 Comments

Tillbaka till framtiden med REST

Vad är det för skillnad mellan en REST-tjänst och en "vanlig" Webbtjänst?
Är REST bättre än SOAP?
Hur gör vi för att använda det i våra system?

Diskussionen kring REST, eller Representational State Transfer, har på senare tid blommat upp rejält och jag möts lite nu och då av frågorna ovan. Träffar jag istället någon som är mer påläst på området möts jag ofta av en stor entusiasm och övertygelse. Lite som om personen ifråga har sett “ljuset”. Det är så vackert... Min uppfattning är att det finns två grupper av REST-anhängare; de som är övertygade och de som är nyfikna. Denna artikel vänder sig främst till er som är nyfikna.

I dag säger man vanligtvist Webbtjänster om tjänster som utbyter SOAP meddelanden över HTTP. Är det verkligen korrekt? På flera sätt följer inte SOAP Webbens arkitektur alls. Det finns som nämnt bindningar för att kommunicera med SOAP över HTTP men många aspekter av SOAP motsäger sig Webbens tillståndslösa natur. REST å andra sidan nyttjar HTTP:s semantik vilket gör det väldigt tillgängligt och enkelt att komma igång med. Har plattformen en HTTP stack så kan du kommunicera med ,och exponera, REST-tjänster. Detta tror jag är nyckeln till RESTs framgång hittills. Med utökat verktygsstöd samt introduktionen av erbjudanden som t ex Azure, vars gränssnitt exponeras till stor del av REST-tjänster, tror jag att vi bara har sett början av REST-vågen.

Den största skillnaden mellan en sk RESTful tjänst och en SOAP/HTTP Webbtjänst är att REST-tjänsten exponerar kollektioner av Resurser medan SOAP/HTTP-tjänster exponerar metoder. Varje REST Resurs identifieras av en unik URL och implementerar ett antal standard operationer som tillåter konsumenten att skapa, läsa, uppdatera och radera resurser (CRUD). Dessa operationer representeras av standard HTTP verb som GET, POST, PUT och DELETE. Vissa tjänster passar naturligt in i REST-modellen - ofta när Resursen är tydligt identifierad och tjänsten mest handlar om att hantera denna resurs.

Kunder vill ofta höra våra sk Best Practices kring mönster och teknikval. REST är inget undantag. vilket sätt skall vi bygga våra RESTfulla tjänster på er platform?

Mitt första inlägg jag skrev här på bloggen heter "WCF Best Practices". Även om jag använde uttrycket Best Practices där så vill jag poängtera att det sällan finns ett gyllene sätt att lösa flera problem med. Det gyllene sättet (Best Practice) måste sättas i sitt sammanhang vilket med största sannolikhet resulterar i olika lösningar för olika sammanhang.

Jag har nedan sammanställt Microsofts REST-landskap som jag ser det. Till varje erbjudande har jag skrivit en kortare kommentar så du själv kanske kan identifiera vad som kan innehålla rätt lösning för dig.

rest-landscape

Med WCF 3.5 fick vi på riktigt stöd i WCF för att bygga REST-tjänster. WebHttp bindningen är utgångspunkten. Använd detta om du är bekväm med WCF. WCF REST Starter Kit innehåller klasser och Visual Studio tillägg som gör det enklare för dig att utveckla WCF REST-tjänster i synnerhet och konsumera REST-tjänster i allmänhet.

ADO.NET Data Services är en del av ADO familjen och är baserat på WCF. Används med fördel till att exponera datamodeller som AtomPub tjänster. Introducerar en del ramar som hjälper dig att snabba upp utvecklingen. Bygger du en Silverlight applikation eller tittar på Azure Services Platform är detta ett hett alternativ.

ASP.NET MVC är kanske tom det RESTfulligaste erbjudandet. Bygger du en MVC applikation och vill exponera REST-tjänster för att driva viss funktionalitet kan detta med fördel göras i passande Controller. En vy av din information behöver inte vara något som skall presenteras för en människa. Vyn kan lika gärna bestå av t ex XML eller JSON ämnat för konsumtion av en applikation.
Introducera inte WCF i mixen om det inte är absolut nödvändigt.

ASP.NET HttpHandler; Är du bekväm med ASP.NET, bygger inte en MVC applikation, och anser att det tar för lång tid att läsa in dig på WCF. Då kan en HttpHandler absolut vara rätt verktyg för jobbet. Här har du dock minst infrastruktur att ta hjälp av, vilket kommer resultera i att du skriver mer infrastrukturrelaterad kod i dina tjänster.

Hur kan något så relativt "gammalt" plötsligt kännas som framtiden? Håll det simpelt säger jag bara.

Mer information kring REST och .NET

Bedriva mjukvaruutveckling är som att bygga altan – eller?

För lite drygt ett år sedan köpte jag och min festmö Ann-Christine en nyproducerad villa i Upplands-Väsby. Perfekt tänkte vi; huset är top-notch, det är bara tomten som behöver fixas. Den lilla detaljen är att bara inte alltid är så bara.

Första sommaren jobbade vi hårt med stenläggning, mur och gräsmatta på framsidan av huset. Denna säsong är det baksidan som gäller. Altan skall byggas och gräsmatta skall rullas ut. En altan bygger man väl på en helg? Kanske om man är professionell snickare eller har gjort det flera gånger förut. Jag är inte snickare och har inte heller byggt en altan tidigare.

Många gånger när jag har stannat upp i arbetet för att planera nästa steg så har tanken fört mig till likheterna mellan att anlägga tomt och att bygga mjukvara.

Både i det stora hela och i detta specifika fall med altanen så har vi börjat bygga de saker som ger oss mest nytta först. User Storyn som var högst upp på listan för altanen var att kunna sitta ute under markisen och äta ett mål mat. Detta ledde till att vi först såg till att lägga klart golvet på altanen på den del där vi hade för avsikt att ställa bord och stolar. Sagt och gjort vi fick glädje av vårt trädäck redan innan det var helt färdigt.

Christofer rullar Victoria på trädäcket

De absolut tydligaste likheterna mellan altanbygge och mjukvaruutveckling är nog behovet och nyttan av rätt verktyg och rätt personer för att utföra arbetet.

Jag hade med stor sannolikhet fixat att få ihop något som liknade en altan genom att prata med personalen på brädgården och läsa hur andra gjort på nätet. Men jag är helt övertygad om att resultatet inte hade blivit ens hälften så bra om jag inte hade haft tillgång till de verktyg jag hade och kära släktingar som vet hur dessa verktyg skall användas i samband med byggandet av en altan. Ett pucko med ett verktyg är fortfarande ett pucko...

Geringssågens alla finesser skulle kunna jämföras med WCF:s förmågor, medans Fogsvansen representerar ASP.NET Web Services (asmx). Båda sågarna kan kapa brädor. Med både ASP.NET Web Services och WCF kan du implementera webbtjänster för att skicka XML meddelanden över HTTP. Men Geringssågen öppnar nya möjligheter så som fina snitt, både raka och sneda, och fler användningsområden genom byte av sågklinga (läs WCF Bindings).

Cirkelsåg med linjal Geringssåg Cutters

På bilderna: Cirkelsåg med linjal (vänster) är perfekt för vinklar som Geringssågen (mitten) inte fixar. Essve Cutters (höger) är en helt oslagbar träskruv.

Överst i Backloggen inför nästa Sprint ligger "vindskydd". Product Ownern (läs Ann-Christine) lade dock nu i veckan till en Story vid namn "sitta under segel som solskydd" som kanske blir upprioriterad. Det återstå att se.

Nu är det dags för lite sommarvila från allt som har med mjukvaruutveckling att göra för att sedan återkomma i augusti med laddade batterier och motivationen på topp. Jag kommer naturligtvis lyssna på MSDN och TechNet Sommarpratare under min ledighet.

Efter semestern kommer jag fortsätta att hjälpa våra kunder använda våra verktyg på bästa sätt.

Har du vägarna förbi Upplands-Väsby i sommar? Tweet:a mig så tänder jag grillen!

Ha en skön sommar.

Posted by chrislof | 0 Comments

.NET Service Bus och Managed Services Engine är bästa vänner

Många håller nog med mig om att .NET Service Bus är en av de ballaste tjänsterna som Azure Services Platform erbjuder. I praktiken är det ett DMZ i molnet som erbjuder sina användare mycket kraftfulla kommunikationsmönster. Mer generell information om .NET Service Bus finner du här.

Ett konkret problem som har dykt upp i samband med exponering av tjänster via .NET Service Bus är att den fysiska tjänsten behöver aktiveras för att registrera sig med Service Bus:en. Vilket direkt diskvalificerar WAS/IIS som host i dessa fall. Detta eftersom WAS:en aktiverar tjänsten först när det kommer en förfrågan till den aktuella tjänsten. Moment 22.

Det finns en lösning på problemet, vilken också medför sig ytterligare fördelar i dessa sammanhang, vår lilla darling: Managed Services Engine (MSE).

MSE:n möjliggör exponering av dina WAS hostade tjänster genom sin virtualiseringsteknik och egna runtime miljö. Det handlar i korta drag om att definiera .NET Service Bus som en sk MSE Runtime Server och sedan associera dina befintliga endpoints och operations med denna Server.

MSE Codeplex siten finns ett dokument med walkthroughs för olika MSE och .NET Service Bus scenarios.

image

Bilden visar Endpoint konfigurerad i MSE med NetTcpRelayBinding och Policy (Behavior) för SB autentisering.

-c

More Posts Next page »
 
Page view tracker