2012-03-21

ASP.NET MVC 3 Razor - The Ultimate Quick Reference

Reference

With the transition to the Razor view-engine in ASP.NET MVC 3 a need occurred for a quick-reference.

Sections - Replacement for 'asp:ContentPlaceHolder' and 'asp:Content'

Where you the old WebForms view-engine used to use the controls and to dynamically switch out parts of the content on a page, the Razor view-engine uses sections.

_Layout.cshtml (Equivalent to a .master-page):

<div>Template content</div>
@RenderBody()
<div>More template content</div>
@RenderSection("OtherContent", required: false)

Page.cshtml:

@section OtherContent {
    <span>Other content goes here</span>
}
<div>Main page-content</div>

In above code the RenderSection-method in the _Layout.cshtml renders the content within the matching @section in the Page.cshtml. The required-parameter indicates if the section is required and should throw an exception if the section doesn't exist. The RenderBody-method renders the rest of the content in the Page.cshtml, which is not inside any section.

Declaring the ViewModel

In the old WebForms view-engine your declaration of the view-model would look like something like this:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
    Inherits="System.Web.Mvc.ViewPage<MyViewModel>" %>

While in the Razor view-engine declaring your view-model is as easy as this:

@model MyViewModel

Inline C#-code in the HTML

If you wanted to loop over a collection in your view-model in WebForms view-engine your code would look something like this:

<% foreach(var item in Model.Items) { %>
    <% if(item.IsValid()) { %>
        <div class="<%: item.ClassName %>">&;lt;%: item.Title %></div>
    <% } %>
<% } %>

The percent-tags make it a bit hard to quickly get an overview of what is HTML and what is code. This is one of the largest upsides to the Razor view-engine, where the same code would be written much more readable like this:

@foreach(var item in Model.Items) {
    if(item.IsValid())
    {
        <div class="@item.ClassName">@item.Title</div>
    }
}

If you make a proper installation of MVC 3 you will get syntax-highlighting in Visual Studio for separating C#-code and HTML-tags.

Advanced inline C#-code

Razor is extremely intelligent when it comes to determining when code starts and ends behind the @-signs, which is very well visualized by the IntelliSense in Visual Studio.

<div>This is @Model.Name's page</div>

Since the apostrophe doesn't follow any pattern that could make it correct C#-code, Razor knows to cut the code from there.

If you want to be extra clear in your code, against other developers, but also against Razor, as to where the code starts and ends, you can use parentheses like this:

<div>This is @(Model.Name)'s page and has the status "@(Model.Status)"!</div>

Inline C#-code for logic

You can include code on the page that is not necessarily written out on the page directly, but handles logic and page-specific functionality. For this you use the @-sign, followed by curly braces.

<div>Other content</div>
@{
    string capitalizedTitle = Model.Title.ToUpper();
}
<h1>Page about @capitalizedTitle</h1>

This is used in the templates that comes with MVC 3 to set which Layout-file to use. But you can use this on your own for setting the title-text in the title-tag.

Page.cshtml:

@{  
    ViewBag.Title = "Index titel - " + Model.SubTitle;
}

_Layout.cshtml:

<head>
    <title>@ViewBag.Title</title>
    <!-- ... -->

Helpers - Reusing code specific to view-template

With the new @helper-syntax in Razor you can easily write re-usable methods that deals with output-functionality within view-templates.

@helper ShowInfo(string name, bool hasContent) {
    if(hasContent) {
        <div>This is info about @name.ToUpper()</div>
    }
}

Namespaces

Using a namespace is very easy and reminds us a lot of the old way to do it:

@namespace System.ComponentModel.DataAnnotations

Server-side comments

To do server-side comments with Razor you can click the "Comment" toolbar button or press Ctrl+K, Ctrl+C to apply a server-side comment. The commented code is place between a @* and a *@ and looks like this:

@" This is the text of the model. MUST be HTML-encoded. "@
<div class="special-elemet">@Model.Text</div>

Global settings for view-templates

If you place a file named _ViewStart.cshtml in the root of the ~/Views-folder, the Razor-code in this code will be applied as default to all view-templates in the sub-folders. In the templates that comes with MVC 3 this is used to set the default Layout-file to be used for the view-templates.

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

Not HTML-encoding content

In the old WebForms view-engine you could use a colon-character instead of an equals-sign to HTML-encode content like this:

<%= ContentToBeOutputWithoutEncoding %>  
<%: ContentToBeEncoded %>

The Razor view-engine automatically HTML-encodes whatever strings you output without explicitly using Html.Raw-method like this:

@Html.Raw(ContentToBeOutputWithoutEncoding)

The <text>-tag for Razor

The way Razor analyzes the code to find the start and end only makes it it possible to have one element (with multiple children of course) inside an expression. To resolve this Razor introduces a <text>-tag, where you can nest multiple lines of code:

<text>
    <div>One nested item</div>
    <span>Another nested item</span>
</text>

2012-02-12

jMapMarker - jQuery-Plugin to Easily Add Google Maps with Markers to Your Website

jQuery

Just uploaded my new project called jMapMarkers to GitHub.

It's a jQuery-plugin that easily allows the user to add one or more Google Maps-maps with markers and info-windows to the website.

It uses a simple object-literal as an argument for configuration when calling. To add a map to a div-tag with and ID, simple use the following code:

$('#map-placeholder').jMapMarkers({
    mapOptions: { // Straight Google Maps API-configuration
        zoom: 1,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        mapTypeControl: false
    },
    markers: [
        { lat: '59.329444', long: '18.068611', title: 'Stockholm', desc: 'Capital of Sweden' },
        { lat: '59.949444', long: '10.756389', title: 'Oslo', desc: 'Capital of Norway' }
    ]
});

You can even add on more markers after the initial map has been added. Just leave out the mapOptions-argument in the configurations-arguments, like this:

$('#map-placeholder').jMapMarkers({
    markers: [
        { lat: 52.500556, long: 13.398889, title: 'Berlin', desc: 'Capital of Germany' },
        { lat: 48.8567, long: 2.3508, title: 'Paris', desc: 'Capital of France' },
        { lat: 51.507222, long: -0.1275, title: 'London', desc: 'Capital of England' }
    ]
});

You can find examples in the demo.html-file in the GitHub-project.

A big bonus-feature is that if you don't state otherwise the plugin will automatically zoom and move the map so that all markers are visible, after markers are added to the map.

As it say in the GitHub-README: please feel free to fork and/or give feedback.

2011-09-27

Microsoft Word Macro: Convert Word-files to PDF-files

Microsoft Word Macro

This post comes out of me helping a colleague with a quick macro, for Microsoft Office Word, that he needed to speed up service towards a customer.

I simply recorded a macro while converting one Word-file into a PDF-file and then Googled for some code to access files on disc and put it all together in a loop.

Sub ConvertWordsToPdfs()

    Dim directory As String    
    directory = "C:\Wordup"
  
    Dim fso, newFile, folder, files
    Set fso = CreateObject("Scripting.FileSystemObject")
    
    Set folder = fso.GetFolder(directory)
    Set files = folder.files
    
    For Each file In files

        Dim newName As String
        newName = Replace(file.Path, ".doc", ".pdf")
                
        Documents.Open FileName:=file.Path, _
            ConfirmConversions:=False, ReadOnly:=False, AddToRecentFiles:=False, _
            PasswordDocument:="", PasswordTemplate:="", Revert:=False, _
            WritePasswordDocument:="", WritePasswordTemplate:="", Format:= _
            wdOpenFormatAuto, XMLTransform:=""
            
        ActiveDocument.ExportAsFixedFormat OutputFileName:=newName, _
            ExportFormat:=wdExportFormatPDF, OpenAfterExport:=False, OptimizeFor:= _
            wdExportOptimizeForPrint, Range:=wdExportAllDocument, From:=1, To:=1, _
            Item:=wdExportDocumentContent, IncludeDocProps:=True, KeepIRM:=True, _
            CreateBookmarks:=wdExportCreateNoBookmarks, DocStructureTags:=True, _
            BitmapMissingFonts:=True, UseISO19005_1:=False
        
        ActiveDocument.Close
      
    Next

End Sub

I guess I won't update or tune this macro a lot, but you can find this macro as a Github Gist as well.

2011-05-18

Add Facebook Like, Twitter Tweet and Other Social Links to Your Blog

If you want people to be able to quickly and easily link to your blog-posts or pages in general you can take some shortcuts to get that functionality by using AddThis.

There are several ways to include buttons from AddThis to your page, but for standard functionality with a good overview I would say point to using regular HTML with some automatic JavaScript-magic happening in the background.

The basic code looks like this:

<div class="addthis_toolbox addthis_default_style">
    <a class="addthis_button_facebook"></a>
    <a class="addthis_button_tweet"></a>
    <a class="addthis_button_email"></a>
</div>

There is a very well documented and detailed API Reference on AddThis' website.

Customizing

There are some additional classes you can add to the link-tags to make specialized customization to the buttons. If you add addthis_32x32_style the icon will become larger and stick out more. It could be used on the more popular social sharing services.

<div class="addthis_toolbox addthis_default_style">
    <a class="addthis_button_facebook addthis_32x32_style"></a>
    <a class="addthis_button_twitter addthis_32x32_style"></a>
    <a class="addthis_button_digg addthis_32x32_style"></a>
    <a class="addthis_button_delicious addthis_32x32_style"></a>
    <a class="addthis_button_google"></a>
    <a class="addthis_button_googlebuzz"></a>
    <a class="addthis_button_blogger"></a>
    <a class="addthis_button_tumblr"></a>
    <a class="addthis_button_posterous"></a>
</div>

Which produces a result that looks like this:

With this code Facebook, Twitter, Digg and Delicious are twice the size of the other ones.

AddThis has an extremely long list of supported sharing services supported.

2011-04-27

Language Localization with Google Maps API

Google Maps

When you include a Google Maps to your website via the Google Maps JavaScript API uses the browser's set preferred language to display the texts. Sometimes this doesn't turned out as planned and you want to be able to override this with your own choice.

Changing language is done with an additional argument when referencing the script-file. The argument used is language.

<script type="text/javascript"
    src="http://maps.google.com/maps/api/js?sensor=false&language=ja">

There is of course a reference to the supported languages and their language codes.

Region Localization

To set the language of the names of the countries, cities and other places, you can use the Region Localization.

2011-04-18

Javascript: Timeout on a Textbox using jQuery

jQuery

Here is a quick post about how to use a JavaScript-timer to only execute a textbox's functionality after a certain amount of time.

Worth noticing in the code is that we handle a key-press on the Enter-button instantly, while otherwise we only execute the functionality after the user left the keyboard alone for 0,5 seconds.

var filterTimeoutId = 0;

var textboxFunction = function() {
   // The function the textbox should perform
};

$('input#TextBox').keypress(function (e) {
    if (e.which === 13) { // Enter-key
        e.preventDefault(); // Prevent page postback
        clearTimeout(filterTimeoutId);

        textboxFunction();
        return;
    }

    clearTimeout(filterTimeoutId);
    var timeout = 500; // Timeout in milliseconds
    filterTimeoutId = setTimeout(textboxFunction, timeout);
});

2010-09-08

Visual Studio 2010: Dropped Assembly References Workaround

After adding some references to external assemblies like to NLog or Munq I found out that on some projects Visual Studio 2010 had a tendency to drop the reference to some of these assemblies.

After the usual searching of Google and Stackoverflow I've put together a combination of different solutions that seems to solve this issue.

  • Step 1: Expand your references and bring up the properties-window. Set Specific Version to True:
  • Step 2: Right click on the project and click Untload Project:
  • Step 3: Right click again on the project and click Edit ...csproject.
  • Step 4: Add an XML-element with the name SpecificVersion with the value True beneath the reference in question:
  • Step 5: Right click on the project and click Reload Project.

This works for me so far.

2010-09-01

Conditional Scrolling Banner with YUI

I was in need of a banner that would scroll along on the page, even when the user had scrolled passed it. After Googling with Bing for any done JavaScript to achieve this, I still only found plug-ins for different PHP-based CMS:es.

After spending almost as much time searching for something already built as it would have taken to build it, I did just that, I took matters into my own hands.

In my case I solved it with Yahoo's YUI 2, but you can do it just as well in any other Javascript-library, like jQuery.

<!-- Static banners above conditional scrolling one -->
<div id="scrollBanner" class="scrollBanner">
<!-- Image and/or flash-banners -->
<img src="Banner.gif" alt="Banner" />
</div>

What we need to do is to find the element to scroll in the DOM and find it's initial Y-position. Then we add a listener to the scroll-event and just flip the CSS-class of the element, depending if we've scrolled past it or not.

var scrollBanner = document.getElementById("scrollBanner");
// Initial banner Y-position
var bannerYPos = YAHOO.util.Dom.getY(scrollBanner);

YAHOO.util.Event.addListener(window, 'scroll',
    function() {
        var isBannerAboveScrollTop = (YAHOO.util.Dom.getDocumentScrollTop() > bannerYPos);
        var oldClassName = isBannerAboveScrollTop ? "scrollBanner" : "scrollBanner_fixed";
        var newClassName = isBannerAboveScrollTop ? "scrollBanner_fixed" : "scrollBanner";
        YAHOO.util.Dom.replaceClass(scrollBanner, oldClassName, newClassName);
    }
);

Just style your scrollingBanner_fixed-class with a fixed position and the width you want it to have. Adjust the top-setting to set how high up on the screen the scrolling banner should be. You could also use padding to make the scrolling-experience more smooth.

.scrollingBanner_fixed {
    position: fixed;
    top: 0px;
    width: 100px;
}

This code could of course also be used for good, to have some kind of toolbar that would scroll along on a page.