Oct 20 2009

Resharper 5.0 First Public Build is now available

Uhh, it's a hot day: first the visual studio 2010 beta 2 has came out and now JetBrains released first public available build of the ReSharper 5.0 :)

Here is download page: http://www.jetbrains.net/confluence/display/ReSharper/ReSharper+5.0+Nightly+Builds

What's New in ReSharper 5.0

  • External Sources
  • Structured Patterns
  • Project Refactorings
  • Call and Value Tracking
  • Internationalization
  • Visual Studio 2010 support (coming soon)
  • ASP.NET markup support
  • ASP.NET MVC support
  • Intellisense improvements
  • Bookmarks
  • Inspect project/folder
  • Upgrade-to-LINQ analysis
  • Native NUnit support
  • Xml Formatting

Here you could find more info about R# 5.0 futures: ReSharper 5.0 Overview

Oct 20 2009

Visual Studio 2010 beta 2 - Web Installer

Hi, now it is just 20th of October... but VS 2010 beta 2 will be available only at 21th :(

Can't wait? Ok, I have time machine for you:

Microsoft Visual Studio 2010 Ultimate Beta 2 — ENU (Web Installer)
http://go.microsoft.com/fwlink/?LinkId=151233

You are welcome! :)

Important: Remove ASP.NET MVC 1.1 beforeinstallation. If it does not want to uninstall saying "You first need to uninstall Microsoft Visual Studio 2010 Tools for MVC 1.1, then uninstall ASP.NET MVC 1.1 (this is the runtime component)" then delete next registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET\MVCTools 1.1 (if you run 64bit OS then that key will be under HKLM\SOFTWARE\Wow6432Node node)

P.S.

If you have problems with TFSObjectModel during uninstalling VS 2010 beta 1 then just uninstall it from Programs and Futures manually ;)

 

It's a great day! :)

Jul 01 2009

ReSharper for Visual Studio 2010 (Preview) is almost here

Greate news for ReSharper fans: the ReSharper for Visual Studio 2010 (Preview) is almost here!!!

Guys already made a page for Nightly Builds. They wrote: "We need few more days to run a quick QA run around the bits."

Also, it will be a technical preview not a betta:

ReSharper for Visual Studio 2010 (preview) - is an early build for those who are trying out Visual Studio 2010 and cannot live without ReSharper. It is neither 4.5.1 for VS10, nor 5.0 for VS10. It is intermediate result of our attempts to integrate with Visual Studio 2010 extensibility model, plus preliminary state of some of ReSharper v5 features (you will find some of them enabled). Complete roadmap for ReSharper v5 will be published soon.

Jun 04 2009

Optimize PNG image or just replace it with silverlight content to minimize page size.

Today I’ve opened my first blog post and firebug showed me that page size is almost 150KB. No, no, no.. too much for a simple page with a couple of lines of text. 

So, I decided to optimize my blog load time. I found that the most traffic consuming part is a blog skin. It's a really huge.

But if you look at it you will fined that it is simple enough to be created as vector graphic. Great, I could use my favorite Silverlight to replace skin images and backgrounds with it!!!

Lets start!

Prerequisites

  1. I will use Visual Studio 2010 Beta for web development
  2. Expression Blend 3 to create a Silverlight control
  3. And of course Silverlight 3 Beta SDK

Picture

Lets take this cute 'Web 2.0' image as our first patient Smile

Really I'm not so good designer Smile so I will use a simplest technic to create 'clone' of this picture. So, lets open Expression Blend 3 and create a new project named Web20Image:

 

 Then add new UserControl named 'Web20.xaml'. Now we are ready to 'clone' our picture.

I put source 'Web 2.0' image to the canvas of the created UserControl, so that I could use it as a base:

 

Then with Pen tool I will add a polyhedron.

Remark: There is no build in polyhedron in Blend so I need to create it manually

 

Now we need to make sides of the polyhedron round. To do it just hold 'alt' key, press left button on middle of side and drug it out.

 

We could remove source 'Web 2.0' image now case we don't need it anymore.
The next step is to color our shape, set border thikness and etc. At the end we should have shape like this:

 

 In the source picture was a gradient area with bevelled side. To create it simply copy shape and past it again. Then remove unnessary vertexes and make a bevel. Set gradient for border and background of the shape. At the end you should get this:

 

The only thing left is a text 'web 2.0'. I don't have a font which was used to create initial picture and I don't want to enlarge size of xap file by adding external font in it. I will use standard font instead. I'd like 'Times New Roman' font.

Also I'd like to add drop shadow effect to the text to make it look same as on source picture. You coulf find it in Miscellaneous section (showed in red ellipse on picture below).

Great! Most difficult part is done and we have silverlight user control which looks like below:

 

If we will compile project now then we find that the size is pretty big. Ok, don't worry we will optimize it.

XAP Optimization

Lets look at xaml code which we got for our shape.

 

   1:  <UserControl
   2:      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   5:      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   6:      mc:Ignorable="d"
   7:      x:Class="Web20Image.Web20"
   8:      d:DesignWidth="640" d:DesignHeight="480">
   9:      <Canvas>
  10:          <Path Stretch="Fill" 
  11:              Data="M167.83333...125.16666 z" 
  12:              StrokeThickness="2">
  13:              <Path.Stroke>
  14:                  <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
  15:                      <GradientStop Color="#FFCBE248"/>
  16:                      <GradientStop Color="#FF84A718" Offset="1"/>
  17:                  </LinearGradientBrush>
  18:              </Path.Stroke>
  19:              <Path.Fill>
  20:                  <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
  21:                      <GradientStop Color="#FFE1EF97" Offset="0"/>
  22:                      <GradientStop Color="#FFDBEA85" Offset="1"/>
  23:                  </LinearGradientBrush>
  24:              </Path.Fill>
  25:          </Path>
  26:          <Path Stretch="Fill" StrokeThickness="2" 
  27:              Data="M235.95343...119.59759 z" Canvas.Top="17.333" Canvas.Left="16" 
  28:              Visibility="Visible">
  29:              <Path.Fill>
  30:                  <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
  31:                      <GradientStop Color="#FFC5DF33" Offset="0"/>
  32:                      <GradientStop Color="#FF84A718" Offset="1"/>
  33:                      <GradientStop Color="#FFB6D22D" Offset="0.691"/>
  34:                      <GradientStop Color="#FF94B51F" Offset="0.957"/>
  35:                  </LinearGradientBrush>
  36:              </Path.Fill>
  37:              <Path.Stroke>
  38:                  <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
  39:                      <GradientStop Color="#FFC5DF33" Offset="0"/>
  40:                      <GradientStop Color="#FF84A718" Offset="1"/>
  41:                      <GradientStop Color="#FFB6D22D" Offset="0.691"/>
  42:                      <GradientStop Color="#FF94B51F" Offset="0.957"/>
  43:                  </LinearGradientBrush>
  44:              </Path.Stroke>
  45:          </Path>
  46:          <TextBlock Text="web" FontSize="24" Canvas.Top="22" Canvas.Left="25"
  47:              FontFamily="Times New Roman" FontWeight="Bold"
  48:              Foreground="#FFFFFFFF" TextAlignment="Center">
  49:              <TextBlock.Effect>
  50:                  <DropShadowEffect ShadowDepth="1" BlurRadius="1" Color="#FF8B8989"/>
  51:              </TextBlock.Effect>
  52:          </TextBlock>
  53:          <TextBlock Text="2.0" FontSize="32" Canvas.Top="39" Canvas.Left="26"
  54:              FontFamily="Times New Roman" FontWeight="Bold"
  55:              Foreground="#FFFFFFFF" TextAlignment="Center">
  56:              <TextBlock.Effect>
  57:                  <DropShadowEffect ShadowDepth="1" BlurRadius="1" Color="#FF8B8989"/>
  58:              </TextBlock.Effect>
  59:          </TextBlock>
  60:      </Canvas>
61: </UserControl>

 

We see a lot of code here. XAML will be compeleted to the byte representation called BAML but it will have the same structure as XAML so we need to clean-up code of our user control to make it as less as possible. Lets go throw the code now: 

  1. First of all we need to remove lines 6, 7 and 8 case they usefull only for Blend designer
  2. Next Path.Fill and Path.Stroke on lines 29-36 and 37-44 are the same. We could move them to resources
  3. Same as 2. could be done with TextBlock.Effect sections, lines 49-51 and 56-58
  4. And at the and both text boxes has pretty same parameters lets extract them to resources also

At the end we will have next xaml: 

   1:  <UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   2:      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   3:      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   4:      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
   5:      <Canvas>
   6:          <Canvas.Resources>
   7:              <LinearGradientBrush x:Key="darkPartBrush" 
   8:                  EndPoint="0.5,1" StartPoint="0.5,0">
   9:                  <GradientStop Color="#FFC5DF33" Offset="0"/>
  10:                  <GradientStop Color="#FF84A718" Offset="1"/>
  11:                  <GradientStop Color="#FFB6D22D" Offset="0.691"/>
  12:                  <GradientStop Color="#FF94B51F" Offset="0.957"/>
  13:              </LinearGradientBrush>
  14:              <DropShadowEffect x:Key="textShadowEffect" ShadowDepth="1" BlurRadius="1" 
  15:                  Color="#FF8B8989"/>
  16:              <Style TargetType="TextBlock" x:Key="textStyle">
  17:                  <Setter Property="FontFamily" Value="Times New Roman"/>
  18:                  <Setter Property="FontWeight" Value="Bold"/>
  19:                  <Setter Property="Foreground" Value="#FFFFFFFF"/>
  20:                  <Setter Property="TextAlignment" Value="Center"/>
  21:                  <Setter Property="Effect" Value="{StaticResource textShadowEffect}"/>
  22:              </Style>
  23:          </Canvas.Resources>
  24:          <Path Stretch="Fill" Data="M167.83333...125.16666 z" StrokeThickness="2">
  25:              <Path.Stroke>
  26:                  <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
  27:                      <GradientStop Color="#FFCBE248"/>
  28:                      <GradientStop Color="#FF84A718" Offset="1"/>
  29:                  </LinearGradientBrush>
  30:              </Path.Stroke>
  31:              <Path.Fill>
  32:                  <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
  33:                      <GradientStop Color="#FFE1EF97" Offset="0"/>
  34:                      <GradientStop Color="#FFDBEA85" Offset="1"/>
  35:                  </LinearGradientBrush>
  36:              </Path.Fill>
  37:          </Path>
  38:          <Path Stretch="Fill" Fill="{StaticResource darkPartBrush}" 
  39:              Stroke="{StaticResource darkPartBrush}" StrokeThickness="2" 
  40:              Data="M235.95343...119.59759 z" Canvas.Top="17.333" Canvas.Left="16"/>
  41:          <TextBlock Text="web" Style="{StaticResource textStyle}" 
  42:              FontSize="24" Canvas.Top="22" Canvas.Left="25"/>
  43:          <TextBlock Text="2.0" Style="{StaticResource textStyle}" 
  44:              FontSize="32" Canvas.Top="39" Canvas.Left="26"/>
  45:      </Canvas>
  46:  </UserControl>
 

 

Looks better now

The next step will be to remove unessary files (which makes no sense for us) from a project. It's next files:

Next step will be to remove all unessary code and comments from app.xaml.cs and web20.xaml.cs. Don't forget to replace 'this.RootVisual = new MainControl();' with 'this.RootVisual = new Web20();' in app.xaml.cs in OnStartup method.

Now we are done. Choose Release and build the project.

Repack XAP

Really XAP file is a simple zip file and during compilation not the best method of compression is used. So unpack files from Web20Image.xap file and repack them againg using highest zip compression.

After repackprocedure I got ~3KB XAP file. PNG picture was ~5,5KB in size. Not bad for such small image Smile

Let's embede XAP file into website skin.

Embede Silverlight plugin into website

It's pretty simple step.

Create ClientBin folder at root of the web site. Copy Web20Image.xap file into that folder.

Add Silverlight.js file to web site. Add reference for it in the site.master headers section.

Then add javascript procedure for errors handling:

   1:  <script type="text/javascript">
   2:          function onSilverlightError(sender, args) {
   3:              if (args.ErrorCode == 8001) {
   4:                   var msg = "This sample application was built with Silverlight 3 Beta.\n";
   5:                   msg += "You currently have Silverlight installed, but not the version required to view this sample.\n\n";
   6:                   msg += "For more information about Silverlight 3, please visit: \n";
   7:                   msg += "<a href=\"http://go.microsoft.com/fwlink/?LinkID=141205\">Silverlight 3 Coming Soon</a>.";
   8:   
   9:                   var hostContainer = document.getElementById("silverlightControlHost");
  10:                   hostContainer.innerHTML = msg;
  11:               }
  12:              
  13:              var appSource = "";
  14:              if (sender != null && sender != 0) {
  15:                  appSource = sender.getHost().Source;
  16:              }
  17:              var errorType = args.ErrorType;
  18:              var iErrorCode = args.ErrorCode;
  19:   
  20:              var errMsg = "Unhandled Error in Silverlight 2 Application " + appSource + "\n";
  21:   
  22:              errMsg += "Code: " + iErrorCode + "    \n";
  23:              errMsg += "Category: " + errorType + "       \n";
  24:              errMsg += "Message: " + args.ErrorMessage + "     \n";
  25:   
  26:              if (errorType == "ParserError") {
  27:                  errMsg += "File: " + args.xamlFile + "     \n";
  28:                  errMsg += "Line: " + args.lineNumber + "     \n";
  29:                  errMsg += "Position: " + args.charPosition + "     \n";
  30:              }
  31:              else if (errorType == "RuntimeError") {
  32:                  if (args.lineNumber != 0) {
  33:                      errMsg += "Line: " + args.lineNumber + "     \n";
  34:                      errMsg += "Position: " + args.charPosition + "     \n";
  35:                  }
  36:                  errMsg += "MethodName: " + args.methodName + "     \n";
  37:              }
  38:   
  39:              throw new Error(errMsg);
  40:          }
  41:      </script>

 

And now place Silverlight Control Host definition:

 

   1:  <div id="web-20">
   2:      <div id="silverlightControlHost">
   3:          <object data="data:application/x-silverlight-2," 
                           type="application/x-silverlight-2" width="95" height="98">
   4:              <param name="source" value="../../ClientBin/Web20Image.xap"/>
   5:              <param name="onerror" value="onSilverlightError" />
   6:              <param name="minRuntimeVersion" value="3.0.40307.0" />
   7:              <param name="background" value="#00FFFFFF" />
   8:              <param name="windowless" value="true" /> 
   9:              <param name="autoUpgrade" value="false" />
  10:          </object>
  11:          <iframe style='visibility:hidden;height:0;width:0;border:0px'></iframe>
  12:      </div>
  13:  </div>

This code is almost usual, but there is some special moment which I need to highlite a little bit.

First thing is that I use Silverlight 3 beta. It's not release version and by default if user has Silverlight 2 installed then he will be forwarded to latest release version download page. Which is actualy Silverlight 2...

To avoid this redirection we set 'minRuntimeVersion' to "3.0.40307.0" (version of the Silverlight 3 beta), 'autoUpgrade' option to false and point 'onerror' to the our javascript function for errors handling. At the begin of the function you could find next block of code:

   1:  if (args.ErrorCode == 8001) {
   2:       var msg = "This sample application was built with Silverlight 3 Beta.\n";
   3:       msg += "You currently have Silverlight installed, but not the version required to view this sample.\n\n";
   4:       msg += "For more information about Silverlight 3, please visit: \n";
   5:       msg += "<a href=\"http://go.microsoft.com/fwlink/?LinkID=141205\">Silverlight 3 Coming Soon</a>.";
   6:   
   7:       var hostContainer = document.getElementById("silverlightControlHost");
   8:       hostContainer.innerHTML = msg;
   9:   }

The 8001 code mean that version of the Silverlight installed on a client computer is lower then 'minRuntimeVersion' value (in our case it is "3.0.40307.0"). In that case message box with description of the problem and with a link to Silverlight download page will be shown to the user.

Summary

Congratulations, now we have page element which looks same as source picture but written with help of Silverlight and has less size then initial image. Sure, 2KB is a not so big difference and added silverlight.js file adds some more kilobytes to our page. But we need to include js file only onec and many silverlight controls will be able to reuse it.