Rich Internet Solutions (presence / e-commerce sites)

  • De ultieme gids voor fonts op het web

    Als een klant of extern buro een afwijkend font wil gebruiken op internet geven wij normaal 1 van 3 antwoorden:

    • NEEEE!!! doe dit alsjeblieft niet en kies maar uit dit matrix van geinstalleerde fonts
    • kan voor kopjes, met sIFR (Flash) maar dit is niet ideaal. Er is een vertraging eer het zichtbaar is en het is erg lastig te finetunen
    • kan voor kopjes, door het genereren van afbeeldingen maar dit is ook niet ideaal. Het brengt opmaak beperkingen met zich mee, is lastig te finetunen en de afbeeldingen zijn wel goed maar niet geweldig in kwaliteit

    Dit is erg jammer, want er zijn best hele mooie gratis webfonts beschikbaar

    Font replacement zonder Flash of gegenereerde afbeeldingen

    Gelukkig zijn er recent twee sIFR alternatieven ontwikkeld die geen plugins gebruiken: sinds het voorjaar is er Cufón en, sinds een paar weken, Typeface.js.
    Beide werken door een font om te zetten naar vector informatie in javascript code dat in de browser door middel van het canvas-object en svg wordt weergegeven. Doordat ze niet gebruik maken van een plugin werken ze een stuk sneller. Canvas en svg worden al een paar jaar door alle moderne browsers ondersteund, op eentje na. En daar hebben ze ook een oplossing voor.
    In de vorige eeuw implementeerde Microsoft een proprietary variant van de Virtual Reality Markup Language, VML en hoewel VML een snelle en stille dood is gestorven ondersteunen de browsers nog steeds deze vectortaal. Zowel Cufón als Typeface.js gebruiken VML om de vectoren weer te geven in de verschillende IE's.

    Beide oplossingen converteren text per woord waardoor word-wrap en <br>'s blijven werken. Er zijn ook een paar verschillen tussen de twee:

    • met Cufón is het niet mogelijk text te selecteren, met Typeface.js wel
    • voor Typeface.js kan je alleen truetype fonts converteren, voor Cufón truetype en opentype
    • Cufón is makkelijk te combineren met jQuery
    • Typeface.js levert iets grotere .js bestanden op

    Maar deze 2 methoden, die nog volop in ontwikkeling zijn, zijn net als sIFR slechts hulpmiddelen bij gebrek aan beter.

    Zoals het hoort: @font-face

    Ook al in de vorige eeuw bedachten de toen twee grote webbedrijven dat er native support zou moeten zijn voor niet-geinstalleerde fonts door middel van stylesheets. Hiervoor werd de @font-face constructie ontwikkeld maar elk bedrijf bedacht hiervoor zijn eigen proprietary font formaat en de font foundries (= font warenhuizen) gingen er niet in mee.

    Maar nu is @font-face een onderdeel van CSS3 en is het, zo eind 2009, geimplementeerd in de modernste 2 browsers, Firefox 3.5 en Safari 4 (Google Chrome loopt nog achter). Met @font-face kunnen deze browsers nu rechtstreeks opentype en truetype fonts weergeven.

    Een mogelijke implementatie lijkt voor de hand te liggen, snif met javascript naar modern @font-face support en gebruik bij een negatief Cufón of Typeface.js. Ik heb dit zelf zo snel niet aan de praat gekregen maar het werd dan ook overschaduwd door een nog veel mooiere oplossing:

    Één oplossing voor (bijna) alle browsers, zonder code

    Meerdere mensen hebben de afgelopen maanden gezocht naar de ideale, standaard compliant @font-face oplossing en dit heeft geresulteerd in de volgende oplossing:


    @font-face {
    font-family: "Your typeface";
    src: url("type/filename.eot");
    src: local("Alternate name"), local("Alternatename"),
    url("type/filename.woff") format("woff"),
    url("type/filename.otf") format("opentype"),
    url("type/filename.svg#filename") format("svg");
    }

    Deze ultieme oplossing werkt in vrijwel alle gangbare browsers door gebruik te maken van slimme fallbacks op de verschilende platformen en werkt als volgt:
    Voor Internet Explorer wordt verwezen naar het proprietary filetype (Embedded Open Type) dat ze 11 jaar geleden ontwikkeld hebben. Microsoft probeert dit nu bij de W3C als standaard erkent te krijgen.
    Daarna wordt geprobeert het font lokaal op te halen, de Internet Explorers snappen dit en het koppelen van meerdere bronnen niet en haken hier af.
    De 2 modernste standaard compliant browsers zullen nu het eerste herkenbare font formaat ophalen (opentype of truetype). Google Chrome snapt dit nog niet, maar kan wel het .svg formaat lezen (het is onderdeel van de svg specs).
    Het .woff bestandstype wordt ondersteund door Firefox 3.6 (voorjaar 2010) en is bedoeld als specifiek webfont, niet zo heel anders als de oorspronkelijke bedoeling achter Microsoft's .eot formaat maar het krijgt wel steun van de font foundries en lijkt dus een kans van slagen te hebben. Na meer dan 15 jaar lijken deze bedrijven eindelijk door te krijgen dat het internet belangrijk is. Zo kunnen deze bedrijven dus specifieke font varianten aanleveren die op internet gebruikt mogen worden.

    Voor oudere versies van Firefox, Safari, Chrome en Opera en voor mobiele browsers kunnen alternatieve fonts gedefinieerd worden zoals dat al gebruikelijk is (font-family: "Your typeface", Arial, sans-serif;) of kan gebruik worden gemaakt van het eerdergenoemde Cufón of Typeface.js.

    Een nadeel van deze methode is verder nog dat style-linking niet wordt ondersteund in IE en fout werkt in Opera. Hierdoor is het niet mogelijk aan te geven dat bepaalde font bestanden stijlen zijn (zoals bold of italic) van een ander font. Voor deze stijlen moet je dus in de stylesheet de juiste font-family definieren.

    Doordat je geen font vervangt met deze methode kan je dus ook een eigen font gebruiken voor bodytekst en niet uitsluitend voor koppen maar daar moet je wel mee oppassen. Bij een redesign van BoingBoing kwamen ze erachter dat voor Windows XP gebruikers de site onbruikbaar was. Dit komt omdat onder WinXP font-smoothing standaard uit staat en het door hun gekozen font zo onleesbaar was geworden op kleine pixelgrootte. Kennelijk hebben ze niet goed getest met IE6 op een virtual pc.

    De grootste drempel

    Het grootste probleem met het gebruik van afwijkende fonts blijft echter de licensering. Met al deze technieken worden de fontgegevens naar de client gestuurd en dit moet dus wel toegestaan zijn in de licentie die bij het font horen. En de technieken zijn nog zo nieuw dat die licenties lang niet altijd zo duidelijk zijn. Vaak verwijst font-embedding in een licentie alleen naar fontgebruik in downloadbare pdf bestanden.

    Aan de slag

    Als je een font wel online mag gebruiken is er bij Font Squirrel een handige online tool om het font naar de gewenste formaten om te zetten.
    Als je een huisstijl font niet online mag gebruiken kan het de moeite lonen om te kijken naar een gratis alternatief wat er op lijkt, ook bij Font Squirrel kan je er tientallen als @font-face kit downloaden.

    Nog wat meer info:
    Uitleg hoe deze methode precies werkt
    Webfonts wiki
    @font-face and performance

    Misschien ook wel interessant:
    TypeKit, @font-face als een service waarop je je abonneert

  • Het verschil tussen Silverlight en Flash

    Iemand vroeg mijn visie daar op. Ik kan hem gelijk met jullie delen:

    Het eerste grote verschil is dat Silverlight eigenlijk nog in z'n kinderschoenen staat. Je ziet gewoon dat de tools (Expression Blend & Expression Design in combinatie met de silverlight extensions voor Visual studio) een eerste versie zijn. Hierbij zijn de basis elementen samen gebracht maar mis je de finesse van de doorontwikkelde tools. Nu is de Flash ontwikkelomgeving nooit echt een goede tool geweest, vooral als je wat meer ingewikkelde applicaties ging bouwen. Ik heb de Flash tool eigenlijk alleen gebruikt om de onderdelen van de UI samen te stellen, maakte het basis materiaal met Illustrator en programmeerde in een open-source tool.

    Met de komst van Flex heeft Macromedia > adobe zich op het gebied begeven waar Microsoft eigenlijk zijn gelijke niet kent: de Integrated Development Environment. Dit doet Microsoft met Visual studio al sinds het begin en dat zie je ook. Debugging in Visual Studio van Javascript is al gelijk beter en performt beter dan Flash ooit heeft gedaan. Het beschrijven van de applicatie onderdelen met XML heeft Microsoft op een hoog niveau onder de knie en daar is Adobe bezig met een inhaalslag.

    Als je kijkt naar hoe je grafisch werk produceert heeft Adobe echt een voorsprong. De combinatie Illustrator en Flash zijn echt onovertroffen in intuïtiefheid, integratie en verfijndheid. De combinatie Expression Design en Expression Blend komt er dan maar karig van af. Als je een ingewikkelde UI uitwerkt in deze tools dan loop je eigenlijk meteen tegen de beperkingen van de tools aan. Design kan niet meer dan één niveau layers aan en de helft van de functionaliteit in Blend is voor Silverlight nog niet geactiveerd. Het werkt, je kunt er redelijk efficiënt applicatie elementen mee maken, maar je stapt snel naar de tekst editor om het precies te doen zoals je in je hoofd hebt.

    Eigenlijk is de vergelijking tussen de huidige silverlight 1.0 en Flash/Flex ~9 een beetje scheef. De huidige versie van Silverlight is te vergelijken met de Flash 6 omgeving van een paar jaar geleden. Net zoals Flash, die een sprong maakte van Flash 7 naar flash 8 door een het platform fundamenteel te herbouwen, maakt Microsoft met Silverlight een grote sprong met Silverlight 2.0. het platform van Silverlight hoeft niet opnieuw geschreven te worden maar de hoeveelheid toegevoegde functionaliteit is van de zelfde orde. Dit kwartaal komt er een beta uit van de Silverlight 2.0 plugin die het Silverlight platform op vele aspecten gelijk trekt aan Flash / Flex en op bepaalde vlakken zelfs voorbij stevent. Wat nog achter blijft bij Silverlight is wat Flash toch wel uniek maakt: procedural filters, toegang tot de Bitmap data van een scherm element en de video met alpha channel transparantie.

    Op deze laatste elementen na zijn de platformen dan eigenlijk nagenoeg aan elkaar gelijk. De integratie met de rest van het .NET eco-systeem geeft Silverlight ten opzichte van Flash / Flex een voordeel. De bijna Apple-iaanse coolheid van Flash met de nadruk op design & designers moet Silverlight nog bereiken. Mijn gevoel zegt dat Silverlight een licht voordeel heeft met de manier waarop het customizen van de standaard controls mogelijk is. Bij Flash / Flex is dat eigenlijk altijd een probleem geweest. Het customizen van een framework control vroeg zoveel specifieke kennis van de implementatie van het framework dat je voor het snelle werk beter, en sneller, het control zelf kon bouwen. Mijn ervaring met WPF zegt dat dat in Silverlight eleganter zal worden opgelost.

    De manier waarop het mogelijk is om dadelijk Silverlight controls te customizen met control templates is waarschijnlijk ook zo´n verschil dat belangrijk wordt. Het idee in silverlight is dat het control eigenlijk alleen maar functionaliteit is met een standaard visuele implementatie maar dat je alle onderdelen heel makkelijk kan wijzigen of zelfs vervangen. En de IDE is toch ook een belangrijk onderdeel van het geheel. Er is een veel grotere gemeenschap die makkelijker op Silverlight in kunnen springen omdat het een kleine stap is van bv. Winforms naar Silverlight.

    Frame based versus Time based: Bij Flash heb je een synchronisatie van de frames binnen één timeline. Elke movie heeft een eigen timeline en volgens mij is er geen synchronisatie over movie timelines heen. In Silverlight werk je alleen met Tijd en keyframes. De verschillende 'layers' in een control hebben een synchronisatie door associatie in plaats van concrete frame synchronisatie zoals bij flash. Qua intuïtie ligt dat zo dicht bij elkaar dat ik nog geen situatie ben tegen gekomen waarin dat een concreet verschil maakt.

    Ikzelf heb in principe al gekozen. In principe omdat ik nog steeds binnen Macaw beschikbaar ben voor flash trajecten vanwege mijn expertise op dat vlak. Een half jaar geleden heb ik Silverlight op gepakt en heb daar een aantal onderzoekjes naar gedaan. Vooral de Silverlight 2.0 preview versie heeft mij eigenlijk er voor doen kiezen om niet meer de Flash blogs te volgen en de silverlight blogs te gaan volgen :) De keuze is voor mij strategisch. Bij Macaw heb je zo'n 80/90 programmeurs die vloeiend Microsoft .NET spreken en dat heeft zo zijn voordelen. Wij werken bij Macaw uitsluitend met Microsoft technologie en daardoor is de integratie veel soepeler. Verder vind ik persoonlijk, omdat ik zelf ook een aardig woordje programmeer, de C# taal meer volwassen dan Actionscript. Ik denk dat ik meer Silverlight projecten kan doen binnen Macaw omdat Silverlight binnen Macaw beter geaccepteerd wordt en het nu als één van de speerpunten van ons Solution Center is gekozen. De Flash projecten kwamen elke twee tot twee en een half jaar langs en Silverlight komt nu al veel vaker langs.

  • HTTP-Compression with Web services on the .NET Compact Framework v2

    Over here i posted a solution to enable Sessionstate on the .NET Compact Framework v2 with Web services.

    With some extra code it is also possible to extend the solution to provide HTTP-compression compatibility. I start by posting the code with which you should subclass the WSDL generated Proxy:

    public class SubclassedService : OriginalService
    {

    #region Private fields
    ///
    <summary>
    ///
    This field contains the received session cookie
    ///
    </summary>
    private string cookie = null
    ;
    #endregion

    #region Private constants
    ///
    <summary>
    ///
    HTTP-Header for setting httpcompression
    ///
    </summary>
    private const string HEADER_ACCEPTENCODING = "Accept-Encoding"
    ;

    /// <summary>
    ///
    HTTP-Header value for httpcompression
    ///
    </summary>
    private const string HTTPCOMPRESSION = "gzip, deflate"
    ;

    /// <summary>
    ///
    Http-Header for the request SessionCookie
    ///
    </summary>
    private const string REQUESTHEADER_SESSIONCOOKIE = "Cookie"
    ;

    /// <summary>
    ///
    Http-header for the response SessionCookie
    ///
    </summary>
    private const string RESPONSEHEADER_SESSIONCOOKIE = "Set-cookie"
    ;
    #endregion

    #region Private methods
    private CompressedWebResponse ProcessResponse(System.Net.HttpWebResponse
    response)
    {
       // Is the cookie present in the response?
       if (response.Headers.Get(RESPONSEHEADER_SESSIONCOOKIE) != null
    )
       {
    // Yes
          // Store the cookie
          cookie = response.Headers.Get(RESPONSEHEADER_SESSIONCOOKIE);
       }

       // Wrap the response with a Http-Compression enabled wrapper
       return new CompressedWebResponse
    (response);
    }
    #endregion

    #region Protected overrides
    ///
    <summary>
    ///
    This override will tweak the request to allow Session-cookies and Http-compression
    ///
    </summary>
    ///
    <param name="uri"></param>
    /// <returns>The tweaked request
    </returns>
    protected override System.Net.WebRequest GetWebRequest(Uri
    uri)
    {
       System.Net.HttpWebRequest request = (System.Net.HttpWebRequest) base
    .GetWebRequest(uri);
       request.AllowWriteStreamBuffering = true

       
       request.Headers.Add(HEADER_ACCEPTENCODING, HTTPCOMPRESSION);
       // Is the session cookie cached?
       if (cookie != null
    )
       {
    // Yes
          // Add the sessioncookie to the request
          request.Headers.Add( REQUESTHEADER_SESSIONCOOKIE, cookie );
       }
       return
    request;
    }

    /// <summary>
    ///
    This override will tweak the response to allow Session-cookies and Http-compression
    ///
    </summary>
    ///
    <param name="request"></param>
    ///
    <returns></returns>
    protected override System.Net.WebResponse GetWebResponse(System.Net.WebRequest
    request)
    {
       System.Net.HttpWebResponse response = (System.Net.HttpWebResponse) base
    .GetWebResponse(request);
       return
    ProcessResponse(response);
    }

    /// <summary>
    ///
    This override will tweak the response to allow Session-cookies and Http-compression
    ///
    </summary>
    ///
    <param name="request"></param>
    ///
    <param name="result"></param>
    ///
    <returns></returns>
    protected override System.Net.WebResponse GetWebResponse(System.Net.WebRequest request, IAsyncResult
    result)
    {
       System.Net.HttpWebResponse response = (System.Net.HttpWebResponse) base
    .GetWebResponse(request, result);
       return
    ProcessResponse(response);
    }
    #endregion

    }

    To decompress the WebResponse we use the next class: 

    public class CompressedWebResponse : System.Net.WebResponse
    {

    private System.Net.HttpWebResponse _response = null;

    public CompressedWebResponse(System.Net.HttpWebResponse response)
    {
    _response = response;
    }

    private const string CONTENTENCODING_GZIP = "gzip";

    private const string CONTENTENCODING_DEFLATE = "deflate";

    public override System.IO.Stream GetResponseStream()
    {
       if (_response.ContentEncoding.ToLower() == CONTENTENCODING_GZIP)
       {
          return new ICSharpCode.SharpZipLib.GZip.GZipInputStream(_response.GetResponseStream());
       }
       else if (_response.ContentEncoding.ToLower() == CONTENTENCODING_DEFLATE)
       {
          return new ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream(_response.GetResponseStream());
       }
       else
       {
          return _response.GetResponseStream();
       }
    }

    #region Public Overrides
    public override long ContentLength
    {
       get { return _response.ContentLength; }
    }

    public override string ContentType
    {
       get { return _response.ContentType; }
    }

    public override System.Net.WebHeaderCollection Headers
    {
       get { return _response.Headers; }
    }

    public override Uri ResponseUri
    {
       get { return _response.ResponseUri; }
    }

    public override void Close()
    {
       _response.Close();
    }

    public override bool Equals(object obj)
    {
       return _response.Equals(obj);
    }

    public override int GetHashCode()
    {
       return _response.GetHashCode();
    }

    public override string ToString()
    {
       return _response.ToString();
    }
    #endregion

    }

    The class above uses the SharpZipLib library to decode the compressed response. You can download the SharpZibLib from this location: http://www.icsharpcode.net/OpenSource/SharpZipLib/Download.aspx 

  • Maintaining Web service SessionState with .NET Compact Framework v2

    For a project on which i'm working i needed to interact with a Web service implemented using Axis (Java) from an application running on a Windows Mobile 5 device. 

    I've received instructions that before invoking the main Web methods, i needed to invoke the "authenticate" web method to enable access. Unfortunatly no matter what i tried, i wasn't able to retrieve any data from the main Web methods. I got the tip from the Web service author to check SessionState.

    Apparently the Compact Framework doesn't provide any solutions for Cookie Sessionstate out-of-the-box. The most obvious class which is present in the full .Net framework, the CookieManager-class unfortunatly isn't supported by the Compact Framework. With Google i found some posts from people which had the same problem.

    A collegue of mine suggested that subclassing the Web service-proxy might give a solution, which it did. With only some minor code you can enable Sessionstate in the Compact Framework v2. I ended up with this solution. Instead of instantiating the original WSDL-generated Web service proxy class you should subclass it in this way:

    public class StatefullServiceClass : OriginalServiceClass
    {

    #region Private fields
    ///
    <summary>
    ///
    This field contains the received session cookie
    ///
    </summary>
    private string cookie = null
    ;
    #endregion

    #region Private constants
    ///
    <summary>
    ///
    Http-Header for the request SessionCookie
    ///
    </summary>
    private const string REQUESTHEADER_SESSIONCOOKIE = "Cookie"
    ;

    /// <summary>
    ///
    Http-header for the response SessionCookie
    ///
    </summary>
    private const string RESPONSEHEADER_SESSIONCOOKIE = "Set-cookie"
    ;
    #endregion

    #region Private methods
    private void ProcessResponse(System.Net.HttpWebResponse
    response)
    {
       // Is the cookie present in the response?
       if (response.Headers.Get(RESPONSEHEADER_SESSIONCOOKIE) != null
    )
       {
    // Yes
          // Store the cookie
          cookie = response.Headers.Get(RESPONSEHEADER_SESSIONCOOKIE);
       }
    }
    #endregion

    #region Protected overrides
    ///
    <summary>
    ///
    This override will tweak the request to allow Session-cookies
    ///
    </summary>
    ///
    <param name="uri"></param>
    /// <returns>The tweaked request
    </returns>
    protected override System.Net.WebRequest GetWebRequest(Uri
    uri)
    {
       System.Net.HttpWebRequest request = (System.Net.HttpWebRequest) base
    .GetWebRequest(uri);
       // Is the session cookie cached?
       if (cookie != null
    )
       {
    // Yes
          // Add the sessioncookie to the request
          request.Headers.Add( REQUESTHEADER_SESSIONCOOKIE, cookie );
       }
       return
    request;
    }

    /// <summary>
    ///
    This override will tweak the response to allow Session-cookies
    ///
    </summary>
    ///
    <param name="request"></param>
    ///
    <returns></returns>
    protected override System.Net.WebResponse GetWebResponse(System.Net.WebRequest
    request)
    {
       System.Net.HttpWebResponse response = (System.Net.HttpWebResponse) base
    .GetWebResponse(request);
       ProcessResponse(response)
       return
    response;
    }

    /// <summary>
    ///
    This override will tweak the response to allow Session-cookies
    ///
    </summary>
    ///
    <param name="request"></param>
    ///
    <param name="result"></param>
    ///
    <returns></returns>
    protected override System.Net.WebResponse GetWebResponse(System.Net.WebRequest request, IAsyncResult
    result)
    {
       System.Net.HttpWebResponse response = (System.Net.HttpWebResponse) base
    .GetWebResponse(request, result);
       ProcessResponse(response);
       return
    response;
    }
    #endregion

    }

    Instead of instantiating the original Web service proxy class, you should instantiate the subclassed version. And voila! SessionState!

  • Databases uitrollen naar hosting-omgeving met SQL Server Publishing Wizard

    Microsoft SQL Server Database Publishing Wizard 1.0 is gereleased. Met deze tool is het mogelijk om van het schema (de tabellen, stored procedures, etc.) van een SQL Server database (2000 of 2005), en/of de data in de tabellen, een script te maken dat gebruikt kan worden bij het uitrollen naar een SQL Server (2000 of 2005) in een hosting omgeving.

    Deze tool heb ik de afgelopen maanden (toen het nog een beta versie was) regelmatig in een project gebruikt bij het uitrollen van databases naar een shared SQL Server 2000 bij Macaw Hosting. Oorspronkelijk waren dit SQL 2000 databases, die op de ontwikkelomgeving waren geattached aan een SQL Server 2005 server, maar ondanks dat ze draaiden op SQL Server 2000 compatibility level, konden ze daarna niet meer geattached worden aan een 2000 server, en backup/restore van 2005 naar 2000 werkt ook niet. In eerste instantie wilde ik de tool gebruiken om de databases weer over te zetten van een 2005 naar een 2000 server, en die dan door Hosting te laten uitrollen via backups, maar toen ik ging proberen dat script rechtstreeks naar de hosting-omgeving uit te rollen, beviel dat zo goed dat ik Macaw Hosting heb gevraagd om lege databases aan te maken waar ik toegang op had, zodat ik deze zelf met scripts kon vullen. Dit maakte het mogelijk snel zonder verdere hulp van derden een uitrol te doen, en dat bespaarde veel tijd.

    Als een hoster geen rechtstreekse toegang tot de SQL Server kan geven (op TCP/IP poort 1433), is het mogelijk om het script te copy/pasten in een SQL script execution window die sommige hosters hebben in hun beheerinterface, of het SQL-bestand te uploaden en vanuit code in ASP.NET pagina (zie RunSQL.aspx) uit te voeren (vooral handig als het script te groot is voor copy/paste). Een andere mogelijkheid is dat een hoster de SQL Server Database Publishing Services installeert, waarnaar de Publishing Wizard ook kan publiceren.

    De tool is aan te roepen als Wizard GUI (zowel stand-alone als vanuit Visual Studio 2005) en vanaf de command-line (dus te gebruiken in automatische build- en uitrol-processen).

    Let op - de tool doet één ding wat je meestal niet wilt: Users worden gescript als Roles, wat soms problemen geeft. Tenzij je de tool gebruikt met de Publishing Services kun je handmatig de "EXEC dbo.sp_addrole" (2000) of "CREATE ROLE" (2005) uit het script aanpassen of verwijderen. Hopelijk komt hier in een volgende versie een optie voor.

    De Database Publishing Wizard heeft .NET Framework 2.0 en de Microsoft SQL Server 2005 Management Object Collection nodig (deze zitten bij SQL Server 2005 maar zijn ook los te downloaden). Database Publishing Services heeft alleen IIS 6.0 met ASP.NET 2.0 nodig.

    Download links:

    SQL Server Database Publishing Wizard 1.0
    SQL Server Database Publishing Services 1.0

    De Publishing Wizard en Services zijn onderdeel van het SQL Server Hosting Toolkit project op Microsoft's open source project hosting web site "CodePlex".

    Scott Guthrie van Microsoft heeft er onlangs de volgende blog postings over geschreven:

    Recipe: Deploying a SQL Database to a Remote Hosting Environment (Part 1)
    Tip/Trick: How to upload a .SQL file to a Hoster and Execute it to Deploy a SQL Database

  • Using Windows SharePoint Services 3.0 as a web site development platform

    Recently, I have been working on a project for Royal Haskoning where we created a fairly straight-forward web site for anonymous use on the internet, using WSS 3.0 as our platform. In earlier versions of the SharePoint product, this was not possible, as it did not (really) support anonymous use and the only authentication scenario was using windows user accounts. This restricted the use of SharePoint to a strictly Windows Intranet environment. The latest version of the product, however, allows for anonymous access and as it is built on top of ASP.NET 2.0, you can create your own authentication mechanism using a standard web form for login. Microsoft promotes the use of the (not very cheap) Microsoft Office SharePoint Server 2007 (MOSS) version for use on internet sites for content management, but we figured that for very simple sites, using the free WSS version would be sufficient. This article details findings in this project.

    The approach

    We imagined that a simple site would require only the following features:
    • a custom look & feel, using a custom masterpage and stylesheet
    • a document library containing web part pages
    • an image library containing the images
    • maybe some specific lists for use in the site (News, Events)

    Anonymous access and logon style

    In our situation, most users of the web site would never log in, but would just browse the site and maybe download some documents. Logging in was only necessary for content managers when adding or changing content. We decided to use Windows authentication for the content managers, but select 'Allow anonymous access' to allow all other users to access the site without logging in. This can be configured through Central Administration under Application Management | Authentication Providers. Obviously, anonymous access must also be enabled on the IIS web site and on the SharePoint site level.

    Using web part pages for content management

    The solution of placing web part pages in a document library and use this as a simple content management environment worked very well. By using versioning, you can have content managers work on pages while anonymous users still only see the last major version (you can set this up through Document Library SettingsVersioning Settings, see image below). You can even have approval required on the library. In our project we did not even use the concept of versioning and have the content managers work directly on the visible pages online. This causes some risk, of course, but in many environments this will meet the requirements and the possible confusion of having multiple versions would not be worth it.

    For our site, we wanted to have a specific layout of zones in the web part pages. To do this, we created a custom content type, deriving from WebPart Page and a custom version of spcf.aspx. This is the screen where you can specify the name of your web part page and select a template from a list. For our custom type of web part page, we wanted to have only our specially designed zone layout available, including a thumbnail of our site design to go with it. Then we specified that our 'pages' document library could only contain our custom content type and voila: the library would only show our type in the 'New' menu and this would take you to our custom version of spcf.aspx. The only disappointment here was that it turned out impossible to create web part pages from a different file name than the existing spstd1.aspx to spstd8.aspx, so we had to replace one of these with our own.

    Web Page Metadata

    In internet sites, search engine visibility is always important. Most important of course is to be linked to by others, but the metadata in the pages can also help. This includes:
    • a meaningful URL: this is pretty O.K. using WSS. A typical URL looks like www.sitename.com/pages/ProductSepcifications.aspx
    • Keywords and Description meta tags: we created a custom control to include these in the page header based upon a site wide value that could be managed through Site Settings

    Menuing

    For navigation, our site used the standard structure of a top links menu and a quick links menu. The rendering of these was done with a custom control that rendered more tidy HTML than the standard Microsoft controls did. Maintaining the menu and it's URLs had to be done manually.

    Drawbacks

    Preview

    Content managers like to have preview functionality. "Show me the page as visitors will see it". This feature is hard to accommodate. You can open a browser wihout logging in and view the page in this browser to check, but if anonymous users cannot even see the page while it has not been published yet, even this approach will not work.

    Downloading Office documents

    When you offer MS Office documents for download from the site, the Office tools on the client will recognize the SharePoint site as such and will ask the user to login for online editing. Even though the download is perfectly possible without logging in (hit escape), the login box will scare users away. This problem can be resolved mostly by turning off 'Client Integration' for the web application (same screen as allowing anonymous acces, see above). Sadly, even with this feature turned off, some configurations of browser and Office versions will still show the login box. The work-around we found is to remove the OPTIONS verb from the HTTPHandler registration in web.config (yeah, it's a dirty hack).

    No master page picker or style library

    These features are available in MOSS, but not in WSS. Both where implemented by having a WSS Feature called "Design" that included:
    • Master page
    • Stylesheets, images, deployed to a special folder under _layouts
    • Default master change on activate/deactivate: activating the feature would set the default master of the site to our custom master page
    This worked really well. Once the solution is handed over to the customer, the design can be turned on or off per site. When a change in the design is required, a new version of the Feature is deployed, updating the design in all sites using it. Selecting master pages by content managers is only confusing, really.

    HTML editor

    The HTML editor in both Rich Text fields in lists as in the Content Editor Web Part is very limited. It has no real functionality to clear out garbage HTML resulting from copying Word content and worst of all: you cannot select images from Image libraries or directly upload them. The only option in the "insert image" dialog is to manually enter a URL. For most systems this is really not acceptable. We created a small fix for the Word content, but decided to go live without image integration. Presumably, vendors like Telerik will provider better editors soon. I might even provide one myself some day.

    Search results uses application.master

    The search results page for some reason does not use the default master page of the site, but the application.master. This results in a results page that does not fit in with the rest of the pages. We decided to pull a quick hack here, updating searchresults.aspx to use our custom master instead, but a definite solution here has still to be found.

    Performance

    I have not performed stress tests, but the performance of the product could in my opinion be better. One of the features offered by MOSS is output caching. I am not sure how hard it would be to add such functionality to a WSS site.

    Conclusion

    All in all: when requirements of a web site are fairly simple, WSS 3 is very suitable as a web site platform. It allows to customize the look and feel reasonably well and anonymous access seems to work fine. WSS brings some of the flexibility of the SharePoint platform to the realm of internet presence sites. Add a new field to the list of news items on the home page and sort on this? Content manager can do it! All of the requirements for a full blown content management platform (autorization, versioning, flexible content types, workflows, ...) are built in. Most of them, however, lack a user interface.

This Blog

Post Calendar

<May 2012>
SuMoTuWeThFrSa
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

Syndication

Powered by Community Server, by Telligent Systems