h3mm3's blog

Stories from behind the keyboard

  • RSS
  • Twitter
Showing posts with label Razor. Show all posts
Showing posts with label Razor. Show all posts

Summary

When I customize a web site template, I always replace the color palette looking for a consistent set of colors. In this series I’ll tell how I managed to speed up the whole process, by building a set of Razor functions and push the Razor syntax inside a CSS stylesheet.

In PART ONE we saw how to create a gradient programmatically in order automate a CSS stylesheet using the Razor engine. We started from a base color in the RGB space and converted it to the HSL space. Given its Lightness we could easily build shades and highlights of the starting color.

Let’s agree on some convention

  • RGB : The space where color are defined by their Red, Green and Blue channels. Both R,G and B ranges from 0 to 255
  • HSL: The space where color are defined by their Hue, Saturation and Lightness. Hue ranges in [0,360), Saturation in [0,240], Lightness in [0,240]
  • Hsb: A transform of the HSL space where s is a normalized Saturation and b (brightness, as Microsoft called it) is a normalized Lightness. H is the same Hue of the HSL space.
  • I use lower case for normalized coordinates, UPPER CASE for classic coordinates.

Traveling back to the RGB space

From the HSL representetion of a color we can build a gradient just varying its Lightness. For instance, starting from Blue (H = 240, S = 240, L=120) we can go DarkBlue (L=65) in the shadows, or light blue (say L=160) in the highlighs. In order to get their HTML codes, we have to convert their HSL coordinates to RGB. A useful method written by Oliver in a Stackoverflow thread builds a System.Drawing.Color from αHsb coordinates (α is the opacity of the color, we can stick it to 255). Here comes his method:

/// 
/// Creates a Color from alpha, hue, saturation and brightness.
/// 
/// The alpha channel value.
/// The hue value.
/// The saturation value.
/// The brightness value.
/// A Color with the given values.
public static Color FromAhsb(int alpha, float hue, float saturation, float brightness)
{
    if (0 > alpha
        || 255 < alpha)
    {
        throw new ArgumentOutOfRangeException(
            "alpha",
            alpha,
            "Value must be within a range of 0 - 255.");
    }

    if (0f > hue
        || 360f < hue)
    {
        throw new ArgumentOutOfRangeException(
            "hue",
            hue,
            "Value must be within a range of 0 - 360.");
    }

    if (0f > saturation
        || 1f < saturation)
    {
        throw new ArgumentOutOfRangeException(
            "saturation",
            saturation,
            "Value must be within a range of 0 - 1.");
    }

    if (0f > brightness
        || 1f < brightness)
    {
        throw new ArgumentOutOfRangeException(
            "brightness",
            brightness,
            "Value must be within a range of 0 - 1.");
    }

    if (0 == saturation)
    {
        return Color.FromArgb(
                            alpha,
                            Convert.ToInt32(brightness * 255),
                            Convert.ToInt32(brightness * 255),
                            Convert.ToInt32(brightness * 255));
    }

    float fMax, fMid, fMin;
    int iSextant, iMax, iMid, iMin;

    if (0.5 < brightness)
    {
        fMax = brightness - (brightness * saturation) + saturation;
        fMin = brightness + (brightness * saturation) - saturation;
    }
    else
    {
        fMax = brightness + (brightness * saturation);
        fMin = brightness - (brightness * saturation);
    }

    iSextant = (int)Math.Floor(hue / 60f);
    if (300f <= hue)
    {
        hue -= 360f;
    }

    hue /= 60f;
    hue -= 2f * (float)Math.Floor(((iSextant + 1f) % 6f) / 2f);
    if (0 == iSextant % 2)
    {
        fMid = (hue * (fMax - fMin)) + fMin;
    }
    else
    {
        fMid = fMin - (hue * (fMax - fMin));
    }

    iMax = Convert.ToInt32(fMax * 255);
    iMid = Convert.ToInt32(fMid * 255);
    iMin = Convert.ToInt32(fMin * 255);

    switch (iSextant)
    {
        case 1:
            return Color.FromArgb(alpha, iMid, iMax, iMin);
        case 2:
            return Color.FromArgb(alpha, iMin, iMax, iMid);
        case 3:
            return Color.FromArgb(alpha, iMin, iMid, iMax);
        case 4:
            return Color.FromArgb(alpha, iMid, iMin, iMax);
        case 5:
            return Color.FromArgb(alpha, iMax, iMin, iMid);
        default:
            return Color.FromArgb(alpha, iMax, iMid, iMin);
    }
}

Oliver’s method sticks to Microsoft naming convention, where “Brightness” is actually a value in the “Lightness” dimensions and ranges from 0 to 1. “Saturation” is normalized in [0,1] too. “Hue” ranges from 0 to 360.

All in all, FromAhsb(α,H,s,b) is the Transformation function we need to convert a color from HSL to RGB (is our metaphorical star gate back to the RGB space, if you remember the travel took in PART ONE).

From System.Drawing.Color to HTML coding

Getting the HTML code of a System.Drawing.Color is easy as calling this method:

var blue = System.Drawing.Color.Blue;
var blueHtml = System.Drawing.ColorTranslator.ToHtml(blue);

So all we have to do at this time is to put all this stuff together and maybe spice the recipe with a bunch of handy color transformation functions.

Towards a dynamic CSS

At this point we know how to start from an RGB color and build a number of gradations. To use these colors in an ASP.NET MVC project we have to inject their HTML codes into the Site.css style sheet. We don’t want to hard code them, since we aim to build a dynamic template, based on some parameter. For instance, the following Razor code builds a palette of five color swatches:

@{
  var basecolor = "#960000";
  var bg = basecolor.Brightness(0.4f); 
  var fg = "black";
  var menu_bg = basecolor.Delta(brightness:0.5f);
  var anchor_fg = basecolor.Brightness(0.15f); 
}

Starting from any base color, I build a background color setting its brightness to 0.4 (that’s a Luminosity of 0.4x240 = 96). The foreground color is black. The other two color swatches are based from the basecolor too.

Delta(..) and Brightness(..) are two handy extension methods that increment any dimension of an Hsb color or set its brightness component to a chosen value; they return the HTML code of the built color for our convenience.

Our dynamic CSS can be a “razor’d” version of the default Stile.css file. Just rename it to Stile.cshtml and write something like this:

/*----------------------------------------------------------
@using MyColorHelpers;
@{    
    var basecolor = "#960000";
    var bg = basecolor.Brightness(0.4f); 
    var fg = "black";
    var menubg = basecolor.Delta(brightness:0.5f);
    var afg = basecolor.Brightness(0.15f); 
}
Date: @DateTime.Now

The base color for this template is @basecolor. If you'd like
to use a different color start by replacing all instances of
@basecolor with your new color.
----------------------------------------------------------*/
body {
    background-color: @bg;
    font-size: .85em;
    font-family: "Trebuchet MS", Verdana, Helvetica, Sans-Serif;
    margin: 0;
    padding: 0;
    color: @fg;
}
/* [...] */

As you can see, Razor syntax and a couple of extension methods is all we need to have a dynamic CSS.

In the following post we will put all this stuff together; happy programming and stay tuned!

Summary

When I customize a web site template, I always replace the color palette looking for a consistent set of colors. In this series I’ll tell how I managed to speed up the whole process, by building a set of Razor functions and push the Razor syntax inside a CSS stylesheet.

PS: We won’t use LESS.

Refreshing a pre-cooked template

One of the tasks I have to accomplish anytime I start a new web project is how to design the interface and chose consistent colors. Nonetheless, especially for little projects or back-office web sites, what I need mostly is to customize the default web site template that comes with Visual Studio ASP.NET MVC3 projects.

The process of customization is basically a combination of two tasks: customizing the color palette and defining a new layout; if you are using the default ASP.NET MVC3 template, those tasks implicate the manipulation of a couple of files: “/Content/Site.css” and “/Views/Shared/_Layout.cshtml”.

As you can see running you project (or reading the Site.css code):

/*----------------------------------------------------------
The base color for this template is #5c87b2. If you'd like
to use a different color start by replacing all instances of
#5c87b2 with your new color.
----------------------------------------------------------*/

image

Unfortunately replacing the base color (#5c87b2)doesn’t suffice, since quite all the elements of the page are tuned with it, providing a consistent look. What you should really do is chose a new base color and build a set of harmonious colors based on it.

A starship travel

It is probable that the simplest way to build a consistent color palette is to chose a base color and then stretch a gradient around it, both towards shadows and highlights.

image

Each color is defined in the RGB space by a triplet of integer numbers ranging from 0 to 255, known as Red, Green and Blue channels. This is a convenient way to think a color, since it is the nearest to how our eyes-brain system perceives lights and how electrical devices create colored light (just think about CRT and LCD displays). But if have to build shadowed or highlighted version of a color, you cannot start from its RGB representation. A more useful starting point is to convert the RGB triplet into an HSL triplet (that is similar to take a starship and travel from the RGB universe to the HSL universe. In this case, the black hole that let out starship change universe is a transformation function),

The HSL acronym stands for Hue, Saturation and Lightness (of course you can find more info here). In this space, the Lightness is all we want to change (zero means absence of light, that’s to say BLACK, maximum value means maximum light, that’s to say WHITE). Any color with a minimum amount of light is defined by the two other coordinates: Hue and Saturation.

Talking about Microsoft .Net and C#, you can easily travel to the HSL space, but System.Drawing can only sell you a  one-way ticket: you can extract Hue, Saturation and Lightness from a System.Color but you cannot build a System.Color from an HSL triplet.

Confusing enough, you extract a Hue via Color.GetHue() method, Saturation via Color.GetSaturation() method, BUT Lightness via Color.GetBrightness(). Basito

Moreover, GetHue() ranges between 0 and 360 (degrees),  but GetSaturation() and GetBrightness() range from 0 and 1 (ok, we can live with it.. just multiply them by, say, a 240 scale value to get handy integer values to deal with).

The following LINQpad snippet lets you travel to the HSL space at light speed!

var colors = from n in new[]{"Red","Green","Blue","White","Black","DarkBlue"}
    let c = Color.FromName(n)
    select new {
     c.Name,
     c.R, c.G, c.B,
     H = (int)c.GetHue(),
     S = (int)(240*c.GetSaturation()),
     L = (int)(240*c.GetBrightness())

colors.Dump();

This is the result:

image

In order to automate the creation of a nice gradient, we need to:

  • Get the HSL of our base color
  • Vary the Lightness value towards shadows or highlights (easy like adding or subtracting a number)
  • Build the RGB triplet from the rendered HSB color.

As we have seen, Step 1 is provided courtesy by Microsoft and Step 2 is simple math. But Step 3 means traveling back to the RGB space, and Microsoft starship doesn’t fly there.

In my next post I’ll tell how to find a star gate back to the RGB space and build a convenient set of Razor C# functions to easily manipulate all this colored stuff. Finally we will integrate this rocket science technology to the CSS language, building a system similar to LESS (but LESS-less) Occhiolino

Happy programming and stay tuned!

..or go to Part 2.

ASP.NET WebPages, a.k.a. WebMatrix web sites, are built upon the ASP.NET stack and, as a consequence, they are subjected to the so-called ”request validation”.

In effect ASP.NET provides a basic anti-XSS form validation service, preventing an user to insert HTML/Javascript code inside HTML fields. Within a WebMatrix project, you can bypass this kind of validation by using the Unvalidated(..) extension method defined in System.Web.Helpers.Validation.

For instance, if you want to read a field named “atext” and skip the request validation, you can write:

//Reading a form value and skipping the detection of dangerous-strings..


var value = Request.Unvalidated("atext"); //"atext" is the name of the form field

On the contrary, if you try to read a value using the classic indexer (e.g. calling Request["atext"]) or by similar methods – like accessing the Form collection), the code will implicitly invoke the private method HttpRequest.ValidateString(..). The standard behavior of ValidateString(..) is to prevent dangerous input, by invoking the internal static method CrossSiteScriptingValidation.IsDangerousString(..). The method is defined like this:

//The CrossSiteScriptingValidation.IsDangerousString(..) method:
internal static bool IsDangerousString(string s, out int matchIndex)
{
  //returns true if the string is considered to be "dangerous"
}

If the method returns true, the calling code - e.g. HttpRequest.ValidateString() - will throw an HttpRequestValidationException exception.

Happy programming!

In a previous post I told how I implemented a simple Mandelbrot fractal generator by using WebMatrix. At last the page is accessible to everyone at http://www.hemme.somee.com/MandelPage.cshtml.

The fractal image is computed server-side by a razor C# script. The computation is fired directly by a standard HTTP request (no JSON, just an old- plain-GET-url) like the following one
(you can read more about the interior of Get.cshtml in my previous post):

domain/Mandelbrot/Get.cshtml/Mandelbrot/Get.cshtml
   ?w=470&h=350&maxiter=1000&minr=-2.2&maxr=1&mini=-1.15

After the image returns to the client, the user can zoom it with her mouse. The zoom works just like the HTML5+Javascript implementation that I described in this post. What's different here is that now the page must load a new image from the server, GETting a new URL (instead of computing the image client-side using javascript code). This task is easily accomplished with the help of a JQuery instruction. Actually, the following code registers an handler for the mouse click on the image; the mouse coordinates are then converted in the complex plane and the vertices of the zoomed region are written in the querystring of the new HREF of the image [1]. At this point the HREF attribute is rewritten and the browser reloads the image (that will be computed by the razor server script).

$("#mandel").click(function (e) {
    
     var x = e.pageX - this.offsetLeft;
     var y = e.pageY - this.offsetTop;
    
    $("#spinwheel").css("visibility","visible");

     var halfdeltare = (Mr - mr)/(zoom * 2.0);
     var halfdeltaim = (Mi - mi)/(zoom * 2.0);

     var refac = (Mr - mr) / (w - 1);
     var imfac = (Mi - mi) / (h - 1);
     minre = mr + x * refac - halfdeltare;
     minim = mi + (@h - y) * imfac - halfdeltaim;
     maxre = minre + 2*halfdeltare;
     maxim = minim + 2*halfdeltaim;
    
    $("#mandel img").attr("src","@(Html.Raw(Href("~/Mandelbrot/Get.cshtml")+"?w="+w+"&h="+h))&maxiter="+(maxiter *= 1.5)+"&minr="+minre+"&maxr="+maxre+"&mini="+minim);
    
    mr = minre;
    Mr = maxre;
    mi = minim;
    Mi = maxim;
    
})

The code contains some razor syntax (basically, every identifier starting with '@') since I cut'n'pasted it from the CSHTML source file.

Happy programming!

[1] Note how the region is described by only three numbers, minr, mini and maxr, since the fourth (maxi) can be deduced by the former.

The Post/Redirect/Get (PRG) pattern is a practical remedy against the “refresh-your-page-after-you-sent-form-data” troubles. In this article I present a simple way to implement this pattern in a WebMatrix website.

The pattern

Simply put, in the PRG pattern, the server, after receiving data from a form page P1, answers with a REDIRECT message to a different page (P2). Doing so, the browser will REQUEST the page P2 and if the user will try to refresh the page (e.g. hitting F5) the browser will simply reload the page P2, without sending any more data to the server.

The Post/Redirect/Get pattern

Image courtesy Wikimedia Common. Original URL: [http://en.wikipedia.org/wiki/File:PostRedirectGet_DoubleSubmitSolution.png]

The solution

In order to keep things clear and simple, my solution is built around three files:

  • A form page (form.cshtml)
  • A server-side page that collects data from the form page (formaction.cshtml)
  • An answer page (result.cshtml)

In form.cshtml we write a simple HTML form, like this:


<body>
   <h1>Enter something</h1>
   <form action="formaction" method="post">
     <input type="text" name="textbox"/>
    <input type="submit"/>
   </form>
</body>

Notice how the action attribute of the form points to the formaction.cshtml page (look ma: no extension! ...more details here).

In formaction.cshtml we read form data from the Request, validate them and finally answers the browser with a REDIRECT, putting an exit code directly inside the URL:

@* A pure server-side page *@
@{
    var textvalue = Request["textbox"];
    
    if (textvalue.IsEmpty()) {
        Response.Redirect("result/ko");
    } else {
        Response.Redirect("result/ok");
    }
}

The last page is result.cshtml. Here we read the exit code from the request (it is in the UrlData List) and write in the page accordingly.

@* The answer page *@
@{
    var result = UrlData[0];
}
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title></title>
    </head>
    <body>
        @switch (result){
            case "ok":
                <text>All right!</text>
                break;
            case "ko":
                <text>Something left!</text>
                break;
            default:
                <text>Dunno...</text>
                break;
        }
        Back to your <a href='@Href("~/form")'>form</a>.
    </body>
</html>

Happy programming!

When time permits, I like to experiment mixing some old algorithm and new technologies. This time it was up to Mandelbrot fractals generation (an old algorithm) and the WebMatrix (a new application development tool) plus Razor (a new templating engine for ASP.NET web pages). In effect, the Mandelbrot set is a well-known geometric guy, but it never ends to amaze me, especially when it’s time to figure out and try new coloring algorithms. This time it was also the occasion to practice the Razor syntax inside a vanilla WebMatrix project.

imageThe solution

My solution is built around two methods: the Mandelbrot fractal algorithm and a PNG picture generator, that creates a colored image from the fractal data generated by the former algorithm. Both methods are described ahead in this post. The home page Default.cshtml is a simple HTML page, including an <div id=”mandel” /> tag that will host the fractal image.

<!DOCTYPE html>
<html lang="en">     
<head>
        <meta charset="utf-8" /> 
        <title>Razor Mandelbrot Generator</title>
        <script src='@Href("~/Scripts/jquery-1.4.4.min.js")' type='text/javascript'></script> 
    </head> 
    <body>  
        <h1>Razor Mandelbrot Generator</h1>  
        <div id="mandel">@H.MandelbrotHtmlImage(w,h,minR,maxR,minI,maxiter)</div>  
        <!--Zoom box will go here-->
    </body>  
</html>
An <img /> tag will go inside the div#mandel and it’s build by an helper snippet declared in an /App_Code/H.cshtml file, as follows:

@helper MandelbrotHtmlImage(int w, int h, double minr, double maxr, double mini, int maxiter)
{
  <img alt="Mandelbrot Fractal" src="@Href("~/Get?w=" + w + "&h=" + h + "&maxiter=" + maxiter + "&minr=" + minr + "&maxr=" + maxr + "&mini=" + mini)" />
}
As you can see, the image’s href is a request to a Get “page” – in effect WebMatrix will route the request to a Get.cshtml file, as described here). This request gives the page all the parameters it needs to create a fractal image (more details ahead).

Getting the fractal image as a binary stream

The Get.cshtml page does tree things:

  1. Calculating the fractal data
  2. Building and coloring a PNG image from the fractal data
  3. Returning the image as a binary stream
The first and the last tasks are accomplished invoking helper @functions declared inside H.cshtml. The following code is the main fragment of Get.cshtml:

//The Get.cshtml main fragment:

@{
    var data = H.GetMandelbrotSet(w,h,minR,maxR,minI,maxiter);

    var img = new Bitmap(w, h); 
 
   // The coloring algorithm stuff
   // ...

   var ram = new MemoryStream();
   img.Save(ram,ImageFormat.Png);
   ram.Seek(0, SeekOrigin.Begin);
   H.BinaryResponse(ram, String.Format("mandel_{0}_{1}_{2}.png", minR, maxR, minI), "image/png");
}
Starting from the bottom,  the BinaryResponse() method is a @function declared inside H.cshtml page, as follows:

@functions {
  public static void BinaryResponse(Stream s, string filename, string mimetype)
  {
      Response.Clear();
      Response.Buffer = true;

      Response.AddHeader("Content-Length", s.Length.ToString());
      Response.AddHeader("Content-Disposition", "inline; filename=" + filename.Replace(" ", "_"));
      Response.ContentType = mimetype;

      s.CopyTo(Response.OutputStream);
      Response.End();
  }
  // other functions…
}
Also the GetMandelbrotSet() method is declare inside H.cshtml page. It is a classic Mandelbrot algorithm; w and h are respectively the width and the height of the image, minr and mini are the coordinates of the lower-left Complex point and maxr is the Real part of the rightmost point, maxiter is the maximum number of iterations for each single point in the complex plane.

public static int[][] GetMandelbrotSet(
            int w, int h, double minr, double maxr, double mini, long maxiter)
{
    var image = new int[w][];
    for (int i = 0; i < w; i++)
        image[i] = new int[h];

    //Boring implementation details about generating a Mandelbrot fractal
    //...

    return image;
}
In the next article I will describe how I implemented a zooming capability using jQuery and javascript.
Edit: I finally published the second part of the article .

Stay tuned and happy programming!

mandel_-0_794068504594819_-0_682957393483708_0_228786727456941mandel_-0_807063956186762_-0_794718277174417_0_175446076775865mandel_-0_656811782542777_-0_655440040430294_0_343173133450913