Posta form-data till en extern URL

Jag kommer ihåg när man jobbade med klassisk ASP, och gick över till ASP.NET, att begreppet PostBack var rätt förvirrande. Typ: "Vadå ska varje sida posta tillbaks till sig själv?" Efter ett tag förstod man finessen och nu skulle skulle jag inte vilja byta tillbaks till hur föregångaren fungerade.

Ibland vill man dock kunna posta data från ett formulär till en annan URL, speciellt när man har att göra med betalväxlar (t ex Postens betalväxel), som ofta fungerar så.

PostBackUrl

I ASP.NET 1.1 var det rätt begränsade möjligheter men i 2.0 fick vi attributet PostBackUrl som kan sättas på Button, LinkButton och ImageButton. Har aldrig använt det själv men borde fungera bra.

HttpWebRequest

Med HttpWebRequest kan man skicka webbströmmar med data. Passar bäst om man vill att postningen ska ske i bakgrunden om jag förstått det rätt, och inte lika bra om man vill att webbläsaren ska följa URLen, som postningen sker till. Jag kan ha fel här för har inte provat så mycket med denna metod. Här är ett exempel som verkar rätt lätt att förstå.

Med JavaScript

Man kan lägga till ett extra formulär på sidan och posta detta genom att registrera ett javascript, från koden bakom, ungefär så här.

string sendScript = "<script language='javascript'>document.getElementById('paymentform').submit();<"+"/script>";
Page.RegisterStartupScript("SendPayment", sendScript);

På det extra formuläret anger man den externa URLen i action och variablerna som hidden-inputs.

<form id="paymentform" name="paymentform" action="https://thepaymentservice.domain" method="post">
<input type="hidden" id="Card_num" runat="server">
<input type="hidden" id="Currency" runat="server">
<input type="hidden" id="Amount" runat="server">
</form>

Eller så bygger man formuläret själv

Här är ett exempel på hur man kan använda HttpContext för att helt enkelt bygga ihop formuläret själv med html-taggar. Det är skrivet av Jigar Desai och finns att ladda hem på C# Corner.

Här kommer lätt modifierad variant:

using System;
using System.Web;
using System.Text;
using System.Collections.Specialized;

/// <summary>
/// Summary description for RemotePost
/// </summary>

public class RemotePost
{
private NameValueCollection inputs = new NameValueCollection();

private string url = string.Empty;
public string Url
{
set{ url = value; }
}
private string method = "post";
private string formName = "form1";

public void Add(string name, string value)
{
inputs.Add(name, value);
}

public void Post()
{
HttpContext.Current.Response.Clear();

StringBuilder sb = new StringBuilder();

sb.Append("<html><head>");

sb.Append(string.Format("</head><body onload=\"document.{0}.submit()\">", formName));
sb.Append(string.Format("<form name=\"{0}\" method=\"{1}\" action=\"{2}\" >", formName, method, url));

for (int i = 0; i < inputs.Keys.Count; i++)
{
sb.Append(string.Format("<input name=\"{0}\" type=\"hidden\" value=\"{1}\">", inputs.Keys[i], inputs[inputs.Keys[i]]));
}

sb.Append("</form>");
sb.Append("</body></html>");

HttpContext.Current.Response.Write(sb.ToString());

HttpContext.Current.Response.End();
}
}

Man anropar klassen så här:

RemotePost remotePost = new RemotePost();
remotePost.Url = "http://theRemoteDomain/Page.aspx";
remotePost.Add("field1","This is my first value");
remotePost.Add("field2","And another one");
remotePost.Post();

By Jesper Lind

Snart dags för uppdatering av PageRank?

Läste hos beNi att VI-SU har gjort en beräkning på när nästa uppdatering av Google PageRank färväntas ske.

Om man kollar på hur lång tid det vart mellan uppdateringarna innan så brukar det vara i genomsnitt 77,18 dagar mellan varje. Om Google hade följt denna takten så skulle uppdateringen skett igår den 16 aug. 

By Jesper Lind

Error-mail med Health monitor

Ett riktigt bra tips av Mads Kristensen, som förklarar hur man kan konfigurera health monotor i .NET så den skickar mail, när ett oväntat fel har uppstått i applikationen. Läs mer på MSDN.

Inställningarna i Web.config ser ut så här:

<?xml version="1.0"?>
<configuration>
   <appSettings/>
   <connectionStrings/>

   <system.web>
      <compilation debug="false" />
      <trace enabled="true" localOnly="false" />

      <healthMonitoring enabled="true">
         <providers>
            <add name="EmailProvider"
               type="System.Web.Management.SimpleMailWebEventProvider"
               from="you@domain.com"
               to="you@domain.com"
               subjectPrefix="Error: "
               buffer="true"
               bufferMode="Notification" />
         </providers>
         <rules>
            <add provider="EmailProvider" name="All App Events" eventName="All Errors" />
         </rules>
      </healthMonitoring>

   </system.web>
   <system.net>
      <mailSettings>
         <smtp from="you@domain.com">
            <network host="smtp.domain.com" />
         </smtp>
      </mailSettings>
   </system.net>
</configuration>

By Jesper Lind

Första XSS-attacken mot vår blogg

Det här är inte speciellt dramatiskt egentligen, men lite kul med action. Någon postade för en stund sen en XSS-länk på den engelska delen av vår hemsida.

Jag visste att kommentarsfältet inte var skyddat mot HTML och har inte brytt mig om att fixa det förrän nu.

Attackvektorer

I kommentaren som postades låg följande html-tagg och det är alltså bara en test för att se ifall det gick att köra javascript genom kommentarerna på vår blogg.

<INPUT TYPE="IMAGE" src="javascript:alert('XSS');">

På ha.ckers.org's XSS (Cross Site Scripting) Cheat Sheet kan man läsa att denna vektor inte fungerar på IE7 eller FF2 men på IE6 och Opera. Där finns även fler referenser till andra vektorer.

Hur man skyddar man sig mot XSS (med .NET)

Det enklaste alternativet är att låta validateRequest vara på slaget som det är som standard. Nackdelarna är att det då inte går att posta taggar över huvudtaget och att ett error visas. Läs mer om för-/nackdelar ValidateRequest här. I vår blogg som handlar om webbutveckling vill vi ju kunna tillåta html-kod från våra besökare, så vi har detta skydd avstängt.

Istället ser vi till att använda Server.HtmlEncode på all text som kommer från besökaren (det var detta jag just la till).

En bra effekt är att det numera går att skriva htmlkod i kommentarerna och den visas som den ska. Vissa har ju märkt att det inte fungerat så bra tidigare och vi borde ha fixat det för länge sen.

Testning tillåtet

Om nån är intressarad får ni gärna försöka att posta XSS till detta inlägget. Jag antar att det är omöjligt men vem vet om det finns någon obskyr metod som inte HTMLEncode klarar av att filtera.

Har även lagt in en liten funktion som ska göra om url till länkar. Där kan jag tänka mig att det kan gå att få in någon XSS-variant. Så här ser funktionen ut ifall nån vill prova att "hacka" den.

public string ConvertUrlToHyperlink(string strInput)
{
string strPattern = @"(?<url>http://(?:[\w-]+\.)+[\w-]+(?:/[\w-./?%&~=]*[^.\s|,|\)|<|!])?)";
string strReplace = "<a href=\"${url}\" target=_blank>${url}</a>";
string strResult;
strResult = Regex.Replace(strInput, strPattern, strReplace);
strPattern = @"(?<!http://)(?<url>www\.(?:[\w-]+\.)+[\w-]+(?:/[\w-./?%&~=]*[^.\s|,|\)|<|!])?)";
strReplace = "<a href=\"http://${url}\" target=_blank>${url}</a>";
strResult = Regex.Replace(strResult, strPattern, strReplace);

return strResult;
}

By Jesper Lind

Exempel på enkel box-layout

Imorgon ska jag lära en kille grunderna i webb-design och html-programmering. Tänkte även att detta kan vara något att skriva om i bloggen, så andra läsare kan få nytta av detta.

Ett enkelt exempel i XHTML

Nu ikväll har jag förberett en enkel stuktur för en webbplats för att ha något att börja med. Denna kan ni se på följande länk:

Simple box-layout

Exempel-sajten är kodad i XHTML 1.0. Funderade ett tag på om det var bättre att använda HTML som första exempel, men vi kör med XHMTL till en en början så får vi se.

Layout utan tabeller

Sajten i exemplet är kodad utan tabeller använder istället <div>-taggar som positioneras med hjälp av CSS.

Validerad

Ofta stöter man på konstigheter med att olika webbläsare visar layouten olika. Det första man bör göra är att se till att korrekt CSS och HTML (länkarna går till valideringsverktygen hos W3C). Det är en förutsättning för att de olika webbläsarna ska få en chans att visa ditt innehåll som det var tänkt.

Övrigt

Till sajten har jag använt lite externa resurser. "Lorem Ipsum"-texterna har jag fått genererade här och bakgrundbilden lånade jag från Kaliber 10000.

By Jesper Lind

Skatteverket förklarar hur man designade sin nya webbplats

Webbsnack ger en länk till Skatteverkets utvecklingsblogg där man förklarar hur man jobbat för att designa den nya hemsidan. Där finns också skärmdumpar som visar hur den sett ut genom tiderna.

Läser att även Skatteverkets webbutvecklare Jens Wedin har insett fördelarna med en "grid-design", och satsat på en total bredd på 960px, som vi skrev om nyss och ett tag sen. Verkar som vi fått en ny industristandard, och skönt är det.

Man har även i den senaste versionen gått över till att använda en flexibel layout, istället för en fast, som man hade innan.

Tycker att resultatet blev väldigt bra och det är kul att man delar med sig av arbetsprocessen på det här sättet.

By Jesper Lind

Dust-Me Selectors - Firefox-tillägg för att kontrollera CSS-redundans

http://www.codeodyssey.se/upload/resource/blog/dust-me-selectors.png

Måste först passa på att tacka Andy Budd (även om han antagligen inte förstår svenska så bra). Många av mina senaste CSS-relaterade inlägg kommer från hans länk-RSS.

Där snappade jag även upp det förträffliga tipset om Firefox-tillägget Dust-Me Selectors.

Ni som hängt med här på bloggen kanske kommer ihåg att vi skrev om ett annat verktyg för CSS-redundans-kontroll. Det fungerade bara lokalt och med statiska HTML-filer så vi eftersökte ett liknande verktyg som fungerade online. Nu har vi alltså funnit det i form av detta Firefox-godis.

Dust-Me Selectors ger alltså en rapport på ej använda CSS-klasser och ID och man kan välja att spara ner dem i en komma-separeras CVS-fil.

Ni kan se en del av rapporten för vår webbplats här ovan, där man kan se att det finns en del oanvända klasser. Detta gäller bara fronten som är den sida som jag scannade, de flesta av selektorerna använd någonstans längre in i sidans struktur. En del av dem läggs till med Javascript och dessa kan inte tillägget hitta.

By Jesper Lind

Blueprint CSS - ett ramverk för avancerad layout

http://www.codeodyssey.se/upload/resource/blog/Blueprint-CSS.png

Blueprint är ett projekt på Google Code som är släppt som öppen källkod under MIT licens. Det är en uppsättning CSS-mallar som skapar en smidig grund att bygga din CSS-design ovanpå. Efter en snabb koll tycker jag det ser riktigt bra och man har lagt fokus på att följa webbstandarder och tabell-lös design.

Intressant att notera är demosajtens bredd (skärmdump här ovan) som är exakt 960px bred. Det ger en ytterligare bekräftelse att detta börja bli ett slags standardmått, nu när fler och fler användare sitter på 1024-skärmar. Läs gärna vår tidigare artikel som handlar om att designa webbsidor med 960px bredd och rutnät. Kan tänka mig att dessa ideer har inspirerat folket bakom Blueprint.

Något annat värt att notera i Blueprint-projektet är att man har möjlighet att placera textraderna i jämna rader vertikalt. Tidigare länk på detta ämne finns hos oss, här.

Blueprint verkar alltså vara ett riktigt intressant projekt värt att kolla närmare på, för alla som vill ha en bra grund till CSS-design och ger ett bra rutnät, mall för utskrift och typografi-regler.

By Jesper Lind

Variera OutputCache beroende på sökvägens mapp

Jag har undrat ett tag över hur man kan basera OutputCache beroende på vilken mapp en sida ligger i, och nu kom jag på en lösning.

I mitt fall var det några User Controls som jag ville ha separata Cache-versioner av i varje mapp i applikationen. Först lade jag till följade deklaration på dessa:

<%@ OutputCache Duration="1800" VaryByParam="none"  VaryByCustom="CustomFolder"  %>

Sen overridade jag GetVaryByCustomString i Global.asax som man ska göra om man vill använda VaryByCustom.

public override string GetVaryByCustomString(
HttpContext context,
string arg)
    {
        string result = String.Empty;

        if (arg == "CustomFolder")
        {
            //object o = HttpContext.Current.Request.Path;<--This also gets the file name
           
            //Get the current folder, without the file name
            object o = HttpContext.Current.Request.Path.Substring(0,HttpContext.Current.Request.Path.LastIndexOf("/"));
            if (o != null)
            {
                result = o.ToString();
            }
        }
        else
        {
            result = base.GetVaryByCustomString(context, arg);
        }

        return result;
    }

Raden där den aktuella mappen hämtas ut blev lite lång och krånglig. Ville alltså ha bara mappen och inte filnamnet. Läste här att man kan använda Page.TemplateSourceDirectory, men kunde inte komma åt en referens till Page från Global.asax, eller hitta en motsvarande funktion i HttpContext.

By Jesper Lind

Formatera utskrifter med CSS

Den senaste månaden har vi jobbat en hel del med pappersutskrifter av olika det slag, så det kan nog bli en del blogg-material om det i framtiden.

Tänkte börja med grunderna i för hur man formaterar en sida för utskrifter med CSS. Ofta vill man ju inte att allt som syns på skärmen ska komma mer på utskriften, då lägger man till en separat stilmall enligt följande.

<link rel="stylesheet" href="css/print.css" type="text/css" media="print" />

I denna stilmall kan det vara bra att ställa in fontstorleken i punkter. Här kommer ett exempel där jag har angett hur all text ska visas i body-elementet. Font-storleket har jag satt till 7 punkter som ger en rätt liten text och gör att man får plats med mer på ett papper. Vit bakgrund är ju också bra om man har något annat i sin riktiga stilmall. Grådaskiga utskrifter är inget bra och drar en hel del bläck i onödan.

body {
color : #000000;
background : #ffffff;
font-family: Verdana, Arial, Helvetica, san-serif;
font-size : 7pt;
}

De delar som inte ska vara med på utskriften sätter man till display till none, så här:

#dontPrintElementWithThisId,#header,#footer {
display:none;
}

37Signals skriver mer om hur man gömmer element på utskrifter och hur man kan formatera en blogg så den blir snygg på papper.

Sen ett sjysst tips på Snook.ca som förklarar hur man kan ange vart en ny sida ska börja när man skriver ut. Det kände jag inte till innan men har eftersökt ett sätt att göra detta på.

#alwaysStartNewPageOnThisElement {page-break-before:always;}

By Jesper Lind