How to upload a VHD to Windows Azure

One great drawback in my opinion when it comes to Windows Azure Virtual Machines is that the gallery only contains images for Data Center edition of Windows 2012, most companies do not need data center edition and neither do I, luckily Azure provides a way of uploading you own VHD image and use that to spin up new machines.

The documentation here says that it has to be Windows 2008 R2 or 2012 I wont go into details about the guide but point out where it is wrong, this might change when Microsoft get someone to update the documentation.

In Step 2 "Create the image" do not create a large disk I tried it with 127GB disk which is the maximum size, eventhough the file after installing the OS was only ~8GB it took forever to upload and Azure allocates all 127GB, I had better luck using a 30GB disk in size, and yes I did not use a fixed sized VHD.

In Step 5 Upload the image to Windows Azure, you must create and install a certificate, this section is confusing to me:

1. It is not clear what certificate I can use but as it turns out you can create you own certificate it does not have to be a trusted Certificate Authority (CA) that creates it.

2. The guide says press preview, but that link does not exist anymore. It is moved to Settings 

3. The section about how to obtain the thumbprint of the certificate and the subscription ID is just wrong all the information can be found under Settings when the certificate is uploaded.

When you have all the information make sure that you have the Azure sdk otherwise you can get it here: http://www.windowsazure.com/en-us/develop/downloads/ or if you prefer direct downloads it's here: http://go.microsoft.com/fwlink/?LinkID=254364&clcid=0x409

DO NOT try to shortcut and use Cloudberry Explorer eventhough it is an excellent tool for moving files to and from Azure it is not usable for uploading images.

When everything is done uploading the guide leaves you with nothing, where to go from here?

I uploaded the image to a destination called http://win2012storage.blob.core.windows.net/vhd/Windows2010vhd with a label called "Windows 2012 VHD" as far as I can read the label should be used as a named but that I cant see that in the dashboard on Azure. The screenshot shows my failed 127GB VHD

What does the URL means http://win2012storage.blob.core.windows.net/vhd/Windows2010vhd, the "win2012storage" part is the name of the Storage you gave it when creating it. In the Azure Dashboard press Storage and the name should appear

 

The "blob.core.windows.net" is not to be changed and is the microsoft domain name for the storage so do not mind that. However the next part "vhd" is the name of the container where that VHD file is to be placed, this one you have to create and name your self. Inside the container is where your files are stored.

 

When everything is in place you can start using the image to create your own instances of virtual machines.

BlogEngine throws Culture is not supported. Parameter name: name xx-xx is an invalid culture identifier exception

I had this error for a couple of days and I had no idea as to what was coursing it, as far as I remembered I didn't do anything.

As it turns out you can misconfigure BlogEngine so this unhandled exception occurs, under Settings -> Feed the Language code must match exactly or you and your blog is doomed. Alternately you can leave it blank.

Using your own domain with Azure websites

In a recent post I showed how to move a simple web site to Azure but one thing is moving the site another is getting the DNS to point to the new site.

In Azure websites you have to upgrade your web site to a shared mode as a minimum or reserved.

I have created my web site and it is showing up in the web sites section https://manage.windowsazure.com/#Workspace/WebsiteExtension/websites as myblog123.azurewebsites.com, that is not quite what I want, in order to change that you have to do the following.

Select the website in the Azure dashboard and select Scale. 

 

In the General section of the Scale page select Shared mode and press save:

When pressing save a warning is displayed that this will have billing impact, but not what, but that remains to be seen Undecided

 

When the change is committed after a couple of seconds click on the Configure link:

Note how the previous warning in the domain names section now has changed and the Manage Domains button at the buttom of the page is now enabled.

Press the button and insert your domain. NOTE that you must verify that you own the domain by adding a CNAME record like the dialogue says.

When the domain is verified add a new A record to the designated IP address and wait until the DNS is updated and everything is ready to go.

 

Enjoy..!

Moving BlogEngine to Azure web sites

For the last four or five years I have been hosting my own websites but, with the new Windows Azure web sites (in preview at the moment) I thought it would be a way of getting some experience with Microsoft Windows Azure.

First sign up for a free trial here http://www.windowsazure.com/en-us/pricing/free-trial/?l=en-us

Fortunately it is really easy to set the site up just go to https://manage.windowsazure.com/#Workspace/WebsiteExtension/websites and press new:

Select New ->Web Site -> From Gallery

Select the Blogengine "app" verything is an app at the moment Wink

Select an url, region and the subscription you want to use it is possible to have more then one. Also note that the url has to be unique on the entire azurewebbsites.net domain it is possible to change it though.

After a short the site is configured

But wait, what kind of url is that my I want my blog to be on another domain, more about that in a later post. 

Fancy Captcha in BlogEngine 1.6.0

In my previous post I tried to get rid of all the comments spam and succeeded! But I decided to upgrade to Blogengine 1.6.0 due to the new comments moderation features, and it's ok, the thing that still bothers me are that I’m still getting mails about the spam comments, surely it's easy to go in mark them and delete all the comment from a central point but still, I don't want to see those mails. So why not configure Blogengine not to send any mails? Well, I could but then I wouldn’t get alerted when real users leave their comments. So the only solution was to update the captcha package to match Blogengine 1.6.0.


First of all the structure of the package is simplified by grouping the JQuery files under the captcha folder.


It should be a simple copy and paste EXCEPT for the web.config file do not override your own with mine, it only shows what to change to enable session state. As usual backup your files in case something goes wrong.


Insert this in HTML head section under Settings in Blogengine

<script type="text/javascript" src="../captcha/latest-jquery/jquery-1.3.2.min.js"></script>
 <script type="text/javascript" src="../captcha/latest-jquery-ui/jquery-ui-1.7.2.custom.min.js"></script>

<script type="text/javascript" src="../captcha/jquery.captcha.js"></script>
 <link href="../captcha/captcha.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" charset="utf-8">
$j = jQuery.noConflict();
 $j(document).ready(function(){
       $j("#btnSaveAjax").attr("disabled","disabled");
  $j(function() {
   $j(".ajax-fc-container").captcha({
    borderColor: "silver",
    text: "Verify that you are a human,<br />drag <span>scissors</span> into the circle."   });
  });
  });
 </script>

And all is good. No more spam. As always the credit goes to http://www.webdesignbeach.com

 

Download the source from this link:

captcha.rar (58,41 kb)

Upgradeing to Blogengine 1.6

The process of upgradeing to Blogengine 1.6 from 1.4.5 was really easy, unfortunately my new and super cool implementation of fancy ajax capcha is no longer to be found on my blog, and since the new version has a better administration of blog comments/spam, I doubt it will return.

Enable fancy JQuery captcha in Blogengine 1.4.5.0 (UPDATED)

First of all you need to download the files from here http://www.webdesignbeach.com/ajax-fancy-captcha-php.zip I won’t waste time writing how to install the files since there is a good explanation on the website http://www.webdesignbeach.com/beachbar/ajax-fancy-captcha-jquery-plugin

But copy the files into your Blogengine folder

 

The first problem I faced was that it was made with PHP in mind and since BlogEngine are using .NET I had to change the captcha.php file to a .NET version.
So I created a new file in the captcha folder called captcha.aspx looking like this:

<%@ Page Language="C#" AutoEventWireup="true" %>
<%
    if(Request["REQUEST_METHOD"] == "POST" && !string.IsNullOrEmpty(Request["captcha"]) && Request["captcha"] == Session["captcha"])
 {
  Response.Write( "Passed!"); /* YOUR CODE GOES HERE */
  Session["captcha"] = string.Empty; /* this line makes session free, we recommend you to keep it */
 }
else if(Request["REQUEST_METHOD"] == "POST" && !string.IsNullOrEmpty(Request["captcha"]))
 {
  Response.Write("Failed!");
 }
/* in case that form isn't submitted this file will create a random number and save it in session */
else
 {
    Random r = new Random();
   
  int random = r.Next(0,4);
  Session["captcha"] = r.Next(0,4);;
        Response.Write(Session["captcha"]);
 }
     %>

I really don’t care much about anything  in here besides the Session handling that’s because .NET and Blogengine both submits form data using javascript and I don’t like to mess with the mechanics so nothing special happens here, except the random numbers generated.

The original plug-in was made so a post could not happen without the right icon was chosen, but in this version the submit button is merely disabled/enabled.

Make sure that you have enabled session in the web.config or nothing will happen.

In the jquery.captcha.js file find the following line and comment it out

 //$("#" + options.formId).append("<input type=\"hidden\" style=\"display: none;\" id=\"captcha\" name=\"captcha\" value=\"" + rand + "\">");

Insert thes after the line above
$("#captcha").val(rand);

Next a little configuration of Blogengine is required, bear in mind that this is only tested in version 1.4.5.0, but in the settings page the references to the scripts are inserted


 <script type="text/javascript" src="../latest-jquery/jquery-1.3.2.min.js"></script>
 <script type="text/javascript" src="../latest-jquery-ui/jquery-ui-1.7.2.custom.min.js"></script>

<script type="text/javascript" src="../captcha/jquery.captcha.js"></script>
 <link href="../captcha/captcha.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" charset="utf-8">
$j = jQuery.noConflict();
 $j(document).ready(function(){
       $j("#btnSaveAjax").attr("disabled","disabled");
  $j(function() {
   $j(".ajax-fc-container").captcha({
    borderColor: "silver",
    text: "Verify that you are a human,<br />drag <span>scissors</span> into the circle."   });
  });
  });
 </script>

BlogEngine uses the $ sign too so in order to avoid problems with JQuery make sure that you add $j = jQuery.noConflict(); that cause some grief on my behalf but luckily I found this blog http://www.dscoduc.com/2008/09/jquery-goodness-for-blogenginenet/

Back in the file system locate the User Controls folder in BlogEngine and open the CommentView.aspx file and insert the following:
<!-- Begin of captcha --> 
<div class="ajax-fc-container">You must enable javascript to see captcha here</div>
<!-- End of captcha -->

This is the container for the Plugin so place it somewhere fitting like before the submit button. Before this line: 
<input type="button" id="btnSaveAjax" value="<%=Resources.labels.saveComment %>" onclick="if(Page_ClientValidate('AddComment')){AddComment()}" tabindex="7" />   

Insert the following line in the same file <input type="hidden" name="captcha" id="captcha" value="" /> this is the value generated by the captcha script.

Lastly you must edit the AddComment() method in the blog.js file after all the variable declarations replace:

 WebForm_DoCallback('ctl00$cphBody$CommentView1',argument, callback,'comment',null,false);

with
var cap = $("captcha");
if(cap.value != "") {
  WebForm_DoCallback('ctl00$cphBody$CommentView1',argument, callback,'comment',null,false);
}

This will make sure the submit will never run unless the hidden field has a value. Alternatively you could move the check into the comments.ascx.cs file and  check the value against the session value. But so far I have'nt got any spam.

That’s it time will tell if it solves the spam problem but why don’t try it out and leave a comment.

Pretty neat if I might say so, all credits to http://www.webdesignbeach.com of cause.


 

Assigning values to more then one property using Lambda expressions

I got an interesting question today. "Is it possible to assign values to more then one property in a collection. Using List.ForEach(Action<T>) and lambda expressions?"

Well how hard can that be so I naturally googled it, and came up with no usable results what so ever, I dont blame Google here might be me thats using the wrong search expression. The closest I could get was this article on MSDN: http://msdn.microsoft.com/en-us/library/bb397687.aspx

I dont think this is something you do every day, and I have a hard time figuring out why this was desireable but then again i did'nt ask.

First we need a class:

class test
{
  public int prop1 { get; set; }
  public int prop2 { get; set; }
}

Next a small console application:

class Program
{
  static void Main(string[] args)
  {
   
List<test> l = new List<test>();
    l.Add(
new test());
    l.Add(new test());
    l.ForEach(p => { p.prop1 = 2; p.prop2 = 4; });
   
foreach (test item in l)
    {
     
Console.WriteLine(item.prop1 + item.prop2);
    }
    Console.ReadLine();
  }
}

Certified Scrum Master

I just recieved my certification as a scrum master so I just wanted to flash my brand new certificate on my blog

Mobile LOB webpart pages in Sharepoint

One of the things Microsoft never quit has got its grip about is the support for mobile devices in Sharepoint, I know that it’s possible to get mobile views of lists and navigation by appending an m to the url like this http://servername/m what this does is simply redirecting you to /_layouts/mobile/mbllists.aspx page, one thing comes to mind here is that you are redirected to the _layouts folder which indicates this is an application, the pages are of the SPMobilePage type which inherits System.Web.UI.MobileControls.MobilePage that inherits the normal Page class like a normal LayoutsPageBase does via UnsecuredLayoutsPageBase.

But what’s the problem?

The problem as I see it are that you do not have a way of extending the pages with webparts if you need it, and on the other hand if you create a normal web part page and saves it to a page library the total page size will be very large and prevent the mobile device performing at a acceptable pace.

This is caused by Sharepoint, because it injects links to external js and css files that the device must load. I was recently hired as a consultant where the customer used Sharepoint and integrated with DynamicsAX.

Dynamics comes with a lot of webparts that was required to run on a Motorola hand terminal, which was used to scan barcodes. The problem was that the total page size was so large that the terminal was slowed down; the users didn’t need any special rights on the portal so Site Actions was not shown, and the need for the webpart menu wasn’t needed either.

But whenever Sharepoint sees a webpart it automatically loads core.css, init.js, ie55up.js (depending on browser) and core.js.

The challenge

We need to be able to select what the page returns depending on what you want to do. E.g. editing a page or using it from a hand terminal. So we need a way to control the output from Sharepoint without scarifying the functionality of the page. The goal was that an entire page must not exceed 10kb.

The measurements

I created a new master page based on the default.master called mobile.master, and a new page for testing purposes called mobilepage.aspx.

I used Fiddler2 to measure the payload of the page the result was as follows:

Even with everything removed from the Mobilepage.aspx and the masterpage we still have a payload of approx. 150KB that’s about 15 times more than acceptable also the chart says it all, about 80% is javascript, which is totally unnecessary in this scenario, in this demo the only thing want to show is this:

 

Naturally a more rich webpart will be used in a real world scenario.

Request filters and httpmodule to the rescue

After trying a few different approaches, one of them was to insert <Sharepoint:ScriptLink runat=”server”/> web control into the masterpage. That solved some of the issues concerning the core.js, but that’s only 70KB of the 140KB needed. I was still stuck with a lot of javascript.

Step 1 Create a httpmodule in C#

To do that two things have to be done first create a class that implements the IHttpModule interface and update web.config in the <httpModules> section      

<add name="MobileModule" type="Minimum_Payload.HttpFilter, Minimum Payload, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c23d6c989c59848d" />               

namespace Minimum_Payload
{
 
public class HttpFilter :IHttpModule   
 
{

    #region IHttpModule Members        
     
public void Dispose()       
     
{}
      HttpApplication _context = null;       
     
public void Init(HttpApplication context)       
     
{
           
       
_context = context;
           
       
context.ReleaseRequestState += new EventHandler(context_ReleaseRequestState);       
     
}
      void context_ReleaseRequestState(object sender, EventArgs e)        
      
{
        if (string.IsNullOrEmpty(_context.Request.QueryString["mobile"])) return;            
       
_context.Context.Response.Filter = new MobileFilter(_context.Context.Response.Filter);
       
     
}
                     
   
#endregion
   
  
}
} 

One of the requirements was the ability to control whether it was a normal browser or a mobile device, for this demo I choose the querystring.

Step 2 Create the Filter

I used this post as inspiration from 4guysfromrolla

public class MobileFilter : MemoryStream   
{
        Stream _output = null;
        public MobileFilter(Stream output)
        {
            _output = output;
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            string page = UTF8Encoding.UTF8.GetString(buffer);
            if(page.ToLower().Contains("<script>"))
            {
                int indexOfScript = page.IndexOf("<script>") + 8;
                int indexOfLastScript = page.IndexOf("</script><SCRIPT LANGUAGE='JavaScript' >");
                page = page.Remove(indexOfScript, indexOfLastScript - indexOfScript);
            }
            if (page.ToLower().Contains("</title>"))
            {
                int indexOfTitle = page.IndexOf("</title>");
                int indexOfLastTitle = page.IndexOf("<title>",indexOfTitle);
                page = page.Remove(indexOfTitle, indexOfLastTitle - indexOfTitle);
            }
            _output.Write(UTF8Encoding.UTF8.GetBytes(page), offset, UTF8Encoding.UTF8.GetByteCount(page));
         }
    }

This filter is very simple and I won't recommend that you use it in a production environment, but as an example it works well. The result of the payload of the page are shown here

smallpayload

Conclusion

It is possible to reduce the payload of the page and truly enable mobile devices using webparts. However I do not think that this scenario are supported by Microsoft and I also think that you should take great care in when using custom httphandlers in Sharepoint. Mainly because all request will pass through it, and this could degrade performance.

Source code

Minimum Payload.rar (8,62 kb)

About the author

Jesper is a serlfemployed IT-consultant and owner of Nsight ApS.

His primary focus is on SharePoint and Microsoft online services like Azure and Office 365

Month List

Page List