- Set Doctype to XHTML.
- Remove browser default built-in styles. Use any of the CSS-resets available, for example Eric Meyers.
- Use the W3C Markup Validation Service and the W3C CSS Validation Service to verify HTML/CSS.
- Set the default W3C style sheet, or use a CSS framework like Twitter Bootstrap.
- Use a Javascript framework, for example jQuery.
Monday, October 22, 2012
Cross browser compatibility
Friday, October 8, 2010
Simple NAnt dependency manager for the TeamCity repository
I did not found any suitable tool that can be used to load dependencies when building .NET project in a TeamCity environment (using NAnt scripts).
Until now all dependencies where stored in VCS together with the source, not so sophisticated.
All our TeamCity projects contains one SDK-configuration that is a zipped file with all output assemblies and executables.
The TeamCity offers URL patterns to access build artifacts. For example:
These two facts trigged me to build a custom NAnt task.
It simply downloads SDK-artifacts from the TeamCity repository, and unpacks the assemblies in the current build environment before the build is started.
I added a “pom”-file to all TeamCity configuration projects that defines the dependencies:
<project> <dependencyManagement> <repositories> <repository>http://teamcity.mycompany.com/guestAuth/repository/download/</repository> </repositories> <dependencies> <dependency> <groupId>AGroup</groupId> <artifactId>AProduct</artifactId> <version>1.1.124.0</version> </dependency> <dependency> <groupId>AGroup</groupId> <artifactId>BProduct</artifactId> <version>5.4.42.0</version> </dependency> <dependency> <groupId>BGroup</groupId> <artifactId>CProduct</artifactId> <version>2.5.24.0</version> </dependency> </dependencies> </dependencyManagement> </project>
The NAnt task is executed in the build file:
<target name="loadDependencies"> <loaddependencies filename="${Build.Base}\dependencies.xml" target="${Build.Base}\Dependencies"/> </target>
And here is the source if someone is interested:
using System; using System.Collections.Generic; namespace MyNAnt.Build.Tasks { using System.IO; using System.Net; using System.Xml; using global::NAnt.Core; using global::NAnt.Core.Attributes; using ICSharpCode.SharpZipLib.Zip; [TaskName("loaddependencies")] public class LoadDependenciesTask : Task { // NAnt parameters [TaskAttribute("filename", Required = true)] [StringValidator(AllowEmpty = false)] public string DependencyFile { get; set; } [TaskAttribute("target", Required = true)] [StringValidator(AllowEmpty = false)] public string Target { get; set; } // Lokal parameters private List<Dependency> Dependencies { get; set; } private List<string> Repositories { get; set; } /// <summary> /// Executes the NAnt task /// </summary> protected override void ExecuteTask() { // load all dependency information LoadDependencies(); // download dependencies from TeamCity foreach (var dependency in Dependencies) { DownloadArtifact(Repositories, dependency.Group, dependency.Name, dependency.Version, Target); } } /// <summary> /// Reads the dependency list from configuration file /// </summary> private void LoadDependencies() { var doc = new XmlDocument(); Log(Level.Info, "Loading dependencies from '{0}'.", DependencyFile); doc.Load(DependencyFile); // load all repositories to search for assemblies var repList = new List<string>(); var repElemList = doc.GetElementsByTagName("repository"); foreach (XmlNode repository in repElemList) { repList.Add(repository.InnerText); } Repositories = repList; // load all dependency assemblies var depList = new List<Dependency>(); var depElemList = doc.GetElementsByTagName("dependency"); foreach (XmlNode dependency in depElemList) { var item = new Dependency(); if (dependency != null) { item.Group = dependency["groupId"].InnerText; item.Name = dependency["artifactId"].InnerText; item.Version = dependency["version"].InnerText; } depList.Add(item); } Dependencies = depList; } /// <summary> /// Downloads and unzip artifact from TeamCity repository /// </summary> /// <param name="repositoryList"></param> /// <param name="group"></param> /// <param name="name"></param> /// <param name="version"></param> /// <param name="destination"></param> private void DownloadArtifact(List<string> repositoryList, string group, string name, string version, string destination) { Log(Level.Info, "Destination folder: '{0}'.", destination); // create destination folder if it not exist Directory.CreateDirectory(destination); foreach (var repository in repositoryList) { // URL-example // http://teamcity.mycompany.com/guestAuth/repository/download/AGroup::AProduct/1.1.124/SDK/AProduct_SDK-1.1.124.zip var address = repository + group + "::" + name + "/" + version + "/SDK/" + name + "_SDK-" + version + ".zip"; using (var wc = new WebClient()) { try { using (var streamRemote = wc.OpenRead(new Uri(address))) { Log(Level.Info, "Found artifact '{0}'.", address); var zis = new ZipInputStream(streamRemote); ZipEntry ze; while ((ze = zis.GetNextEntry()) != null) { if (ze.IsDirectory) { Directory.CreateDirectory(ze.Name); } else { var buffer = new byte[2048]; var fileName = Path.GetFileName(ze.Name); Log(Level.Info, "Unzipping '{0}'.", fileName); using ( Stream outstream = new FileStream( destination + "\\" + fileName, FileMode.Create)) { while (true) { var bytes = zis.Read(buffer, 0, 2048); if (bytes > 0) outstream.Write(buffer, 0, bytes); else break; } } } } return; } } catch (Exception) { // ignore exceptions } } } Log(Level.Error, "ERROR: Artifact '{0}::{1}' with version '{2}' not found!.", group, name, version); } } }
Friday, September 24, 2010
WSDL-First development with Visual Studio
This is how I implemented the WSDL-First approach when creating a WCF service with Visual Studio.
An example of a simple WSDL:
<?xml version="1.0" encoding="utf-8"?> <definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.myweb.com/ws/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://www.myweb.com/ws/" xmlns="http://schemas.xmlsoap.org/wsdl/"> <types> <s:schema elementFormDefault="qualified" targetNamespace="http://www.myweb.com/ws/"> <s:element name="DoSomething"> <s:complexType> <s:sequence> <s:element minOccurs="0" maxOccurs="1" name="param1" type="s:string" /> <s:element minOccurs="0" maxOccurs="1" name="param2" type="s:string" /> </s:sequence> </s:complexType> </s:element> <s:element name="DoSomethingResponse"> <s:complexType> <s:sequence> <s:element minOccurs="0" maxOccurs="1" name="DoSomethingResult" type="tns:TheDTO" /> </s:sequence> </s:complexType> </s:element> <s:complexType name="TheDTO"> <s:complexContent mixed="false"> <s:extension base="tns:BaseDTO"> <s:sequence> <s:element minOccurs="0" maxOccurs="1" name="Att1" type="s:string" /> </s:sequence> </s:extension> </s:complexContent> </s:complexType> <s:complexType name="BaseDTO" abstract="true"> <s:sequence> <s:element minOccurs="0" maxOccurs="1" name="BaseAtt1" type="s:string" /> <s:element minOccurs="0" maxOccurs="1" name="BaseAtt2" type="s:string" /> </s:sequence> </s:complexType> </s:schema> </types> <message name="DoSomethingSoapIn"> <part name="parameters" element="tns:DoSomething" /> </message> <message name="DoSomethingSoapOut"> <part name="parameters" element="tns:DoSomethingResponse" /> </message> <portType name="IService"> <operation name="DoSomething"> <documentation xmlns="http://schemas.xmlsoap.org/wsdl/">Do something.</documentation> <input message="tns:DoSomethingSoapIn" /> <output message="tns:DoSomethingSoapOut" /> </operation> </portType> <binding name="TheServiceSoap" type="tns:IService"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" /> <operation name="DoSomething"> <input> <soap:body use="literal" /> </input> <output> <soap:body use="literal" /> </output> </operation> </binding> <service name="TheService"> <port binding="tns:TheServiceSoap" name="TheServicePort"/> </service> </definitions>
Tip: It can be useful to download a WSDL-template to start with, instead of writing it from scratch.
Use the svcutil utility to save the WSDL-file exported from a service:
> svcutil /t:metadata http://localhost:8731/TheService/Service/
I added a Pre-Build command that reads my WSDL-file and creates an interface file in preferred language, in my case C#:
svcutil /language:C# /n:*,TheService /out:$(ProjectDir)IService.cs $(ProjectDir)\TheService.wsdl
The IService.cs will be regenerated each time I initiates a build so I adds the implementation of the interface in a separate file, Service.cs.
using System; namespace TheService { using System.ServiceModel; [ServiceBehavior(Namespace = "http://www.myweb.com/ws/")] public class Service : IService { public TheDTO DoSomething(string param1, string param2) { throw new NotImplementedException(); } } }
It is preferable to store the WSDL file separately in the VCS, then you can redesign both server and clients without affecting the functionality, as long as they use the same version of the WSDL file.
The WSDL can now be used to create service clients.
For example, to create a .NET client, use the svcutil utility to create the service proxy code:
> svcutil TheService.wsdl
The svcutil utility creates a Service.cs that you include in the client project, and then the service can be invoked as if it were a local object.
var myService = new ServiceClient(); TheDTO result = myService.DoSomething("A", "B");