Teknikdagboken En blogg om teknik i vardagen

19Mar/120

Databasproblem i MVC Music Store

Jag har börjat lyft av jonkopingsok.nu från ASP/VBScript till MVC3 och ville titta på lite andra lösningar för att se hur de fungerar. En av de mest kända är MVC Music Store men när jag försökte starta den fick jag felkod Unable to find the requested .Net framework data provider. Jag hade SQL Server 2008 R2 och VS2010 Premium SP1 men tydligen saknades ändå någon data provider för SQL Server Compact 4.0. Följ länken och installera så bör det fungera.

Om du testar applikationne och försöker logga in på admin-delen måste du först ge ditt nya konto rollen Administrator. Detta kan göras via ASP.Net Web Site Administration Tool som man kommer åt via Visual Studio -> Project -> ASP.Net Configuration. Eller så loggar du in med det förskapade administratörskontot som jag inte vet lösenordet på men som borde stå i guiden på asp.net.

4Mar/110

Serialisera objekt till json med camelCase

För att serialisera ett objekt till json i MVC3 kan man använda Json(), men då skapas objektet som serialiseras med fel namn i JavaScript där camelCase används. För att fixa detta kan man använda DataContractJsonSerializer. Här är min lösning:

public class JsonHelper
{
    public static string Serialize<T>(T obj)
    {
        var serializer = new DataContractJsonSerializer(obj.GetType());
        var ms = new MemoryStream();
        serializer.WriteObject(ms, obj);
        string retVal = Encoding.UTF8.GetString(ms.ToArray());
        ms.Dispose();
        return retVal;
    }

    public static T Deserialize<T>(string json)
    {
        T obj = Activator.CreateInstance<T>();
        var ms = new MemoryStream(Encoding.Unicode.GetBytes(json));
        var serializer = new DataContractJsonSerializer(obj.GetType());
        obj = (T)serializer.ReadObject(ms);
        ms.Close();
        ms.Dispose();
        return obj;
    }
}

Objektet som skall serialiseras behöver några extra taggar på sig ex:

[DataContract]
public class Person
{
    [DataMember(Name="firstName")]
    public string FirstName { get; set; }

    [DataMember(Name="lastName")]
    public string LastName { get; set; }
}

För att serialisera/deserialisera skriver man så här:

var myPerson = new Person()
{
    FirstName = "John",
    LastName = "Doe"
};

// Serialize
string json = JSONHelper.Serialize<Person>(myPerson);

// Deserialize
myPerson = JSONHelper.Deserialize<Person>(json);

Koden är i princip identisk med http://pietschsoft.com/post/2008/02/NET-35-JSON-Serialization-using-the-DataContractJsonSerializer.aspx. Jag har bara ändrat från default encoding till utf8.

26Feb/110

Lång tid att ladda sidor i Firefox med Visual Studio

Jag upptäckte för någon månad sedan att när man kör VS2008/VS2010 för att utveckla webbapplikationer tar det nästan en sekund innan sidorna börjar laddas. Dumt tänkt jag och fortsatte arbeta som om inget hade hänt. Några veckor senare stötte jag på sidor i projekt som tog flera sekunder att ladda i Firefox medan de laddades direkt i IE. För att se vad som tog tid använde jag det mycket användbara verktyget Firebug i Firefox.

Efter att ha googlat lite hittade jag en lösning som sa att detta är en bugg när man kör Firefox mot den inbyggda webbservern i Visual Studio. Tydligen har det något att göra med att Firefox frågar efter en IPv6 adress men får en IPv4 adress tillbaka. Vad jag förstår är inte detta en bugg i Firefox utan en bugg i DNS servern som finns i VS inbyggda webbserver.

Buggen kan enkelt undvikas genom att ändra en inställning i Firefox så att den alltid använder IPv4 mot localhost. Skriv about:config i adressfältet, leta upp network.dns.ipv4OnlyDomains och skriv in en kommaseparerad lista med domäner där FF inte skall använda IPv6. Om det inte står något där ska det alltså stå localhost. Du kanske behöver starta om Firefox för att ändringen skall slå igenom.

En annan lösning är att sätta network.dns.disableIPv6 men då stänger man av IPv6 för alla webbsidor och inte bara localhost och påverkar alltså inte bara sin utvecklingsmiljö.

network.dns.disableIPv6
7Feb/100

Litebox som anpassar sig efter webbläsarfönstret

Jag tycker att bildvisning med hjälp av Lightbox2 / Litebox är riktigt snyggt på webbsidor och har nyligen installerat det på en av mina hemsidor.

Jag hittade då ett problem där applikationen inte tar hänsyn till hur stora bilderna är relaterat till webbläsaren vilken ibland gjorde att inte hela bilderna syntes. När man använder dessa skript får man inte heller någon skrollbar så man kunde inte bläddra för att se hela bilden.

Enkelt löst tänkte jag och googlade vidare efter liknande applikation som gör just detta, men jag hittade inget bra och bestämde mig för att lösa detta själv.

Det som behöver göras är att lägga in ny funktionalitet i litebox-1.0.js för att ta hänsyn till storleken på webbläsarfönstret. Förändringen som behövs är liten och enkel att införa. Byt bara ut

imgPreloader.onload=function(){
	Element.setSrc('lightboxImage', imageArray[activeImage][0]);
	myLightbox.resizeImageContainer(imgPreloader.width, imgPreloader.height);
}

mot

imgPreloader.onload=function(){
	Element.setSrc('lightboxImage', imageArray[activeImage][0]);
	
	var innerWidth = arrayPageSize[2];
	var innerHeight = arrayPageSize[3];
	
	if(imgPreloader.width>(innerWidth-100) || imgPreloader.height>(innerHeight-130)){
		if(imgPreloader.width>(innerWidth-100)){
			var width=(innerWidth-100);
			var height=imgPreloader.height/(imgPreloader.width/(innerWidth-100));
			if(height>(innerHeight-130) ){
				var height=(innerHeight-130);
				var width=imgPreloader.width/(imgPreloader.height/(innerHeight-130));
			}
		} else if(imgPreloader.height>(innerHeight-130)){
			var height=(innerHeight-130);
			var width=imgPreloader.width/(imgPreloader.height/(innerHeight-130));
		}
		
		height = Math.floor(height);
		width = Math.floor(width);
		
		document.getElementById('lightboxImage').height=height;
		document.getElementById('lightboxImage').width=width;
		document.getElementById('lightboxImage').style.width=width;
		document.getElementById('lightboxImage').style.height=height;
		myLightbox.resizeImageContainer(width, height);
	} else {
		document.getElementById('lightboxImage').height=imgPreloader.height;
		document.getElementById('lightboxImage').width=imgPreloader.width;
		document.getElementById('lightboxImage').style.width=imgPreloader.width;
		document.getElementById('lightboxImage').style.height=imgPreloader.height;
		myLightbox.resizeImageContainer(imgPreloader.width, imgPreloader.height);
	}
}

så skall det fungera.

Skillnaden mellan Litebox och Lightbox är liten och ligger främst i vilket bakomliggande JavaScript-ramverk som används, vilket gör att detta därför går att applicera på båda applikationerna.