Sunday, December 23, 2012

How to use Azure storage for uploading and displaying pictures.

Basic set up of Azure storage for local development and production.

This is a somewhat completion of the following guide from that also involves a practical example that I believe is commonly used, i.e. upload and present an image from a user.


First we set up for local storage and then we configure for them to work on a web role.


1. Configure connection string locally.

2. Configure model, controllers and razor views.


1. Setup connectionsstring


1.1 Right click your web role and choose “Properties”.

1.2 Click Settings.

1.3 Add setting.

1.4 Name your setting. This will be the name of the connectionstring.

1.5 Click the ellipsis to the right. (the ellipsis appear when you mark the area.

1.6 The following window appears- Select “Windows Azure storage emulator” and click ok.



Now we have a connection string to use. To be able to use it we need to make sure we have windows azure tools for storage.

2.1 Click Tools –> Library Package manager –> Manage Nuget packages for solution.

2.2 This is what it looks like after it has been added.



Now on to what the code should look like.

3.1 First we need a view which collects images to upload. Here Index.cshtml.

   1: @model List<string>   
   3: @{
   4:     ViewBag.Title = "Index";
   5: }
   7: <h2>Index</h2>
   8: <form action="@Url.Action("Upload")" method="post" enctype="multipart/form-data">
  10:     <label for="file">Filename:</label>
  11:     <input type="file" name="file" id="file1" />
  12:     <br />
  13:     <label for="file">Filename:</label>
  14:     <input type="file" name="file" id="file2" />
  15:     <br />
  16:     <label for="file">Filename:</label>
  17:     <input type="file" name="file" id="file3" />
  18:     <br />
  19:     <label for="file">Filename:</label>
  20:     <input type="file" name="file" id="file4" />
  21:     <br />
  22:     <input type="submit" value="Submit" />
  24: </form>
  26: @foreach (var item in Model) {
  28:     <img src="@item" alt="Alternate text"/>
  29: }

3.2 We need a controller to receive the post. Notice the “containername” string I send to the blobhandler. I use this as a folder for the pictures for each user. If this is not a requirement you could just call it container or anything with small characters directly when creating the container.

   1: public ActionResult Upload(IEnumerable<HttpPostedFileBase> file)
   2:         {
   3:             BlobHandler bh = new BlobHandler("containername");
   4:             bh.Upload(file);
   5:             var blobUris=bh.GetBlobs();
   7:             return RedirectToAction("Index",blobUris);
   8:         }

3.3 The handler model. I’ll let the comments speak for themselves.

   1: public class BlobHandler
   2:     {
   3:         // Retrieve storage account from connection string.
   4:         CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
   5:         CloudConfigurationManager.GetSetting("StorageConnectionString"));
   7:         private string imageDirecoryUrl; 
   9:         /// <summary>
  10:         /// Receives the users Id for where the pictures are and creates 
  11:         /// a blob storage with that name if it does not exist.
  12:         /// </summary>
  13:         /// <param name="imageDirecoryUrl"></param>
  14:         public BlobHandler(string imageDirecoryUrl)
  15:         {
  16:             this.imageDirecoryUrl = imageDirecoryUrl;
  17:             // Create the blob client.
  18:             CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
  20:             // Retrieve a reference to a container. 
  21:             CloudBlobContainer container = blobClient.GetContainerReference(imageDirecoryUrl);
  23:             // Create the container if it doesn't already exist.
  24:             container.CreateIfNotExists();
  26:             //Make available to everyone
  27:             container.SetPermissions(
  28:                 new BlobContainerPermissions
  29:                 {
  30:                     PublicAccess = BlobContainerPublicAccessType.Blob
  31:                 });
  32:         }
  34:         public void Upload(IEnumerable<HttpPostedFileBase> file)
  35:         {
  36:             // Create the blob client.
  37:             CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
  39:             // Retrieve a reference to a container. 
  40:             CloudBlobContainer container = blobClient.GetContainerReference(imageDirecoryUrl);
  42:             if (file != null)
  43:             {
  44:                 foreach (var f in file)
  45:                 {
  46:                     if (f != null)
  47:                     {
  48:                         CloudBlockBlob blockBlob = container.GetBlockBlobReference(f.FileName);
  49:                         blockBlob.UploadFromStream(f.InputStream);
  50:                     }
  51:                 }
  52:             }
  53:         }
  55:         public List<string> GetBlobs()
  56:         {
  57:             // Create the blob client. 
  58:             CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
  60:             // Retrieve reference to a previously created container.
  61:             CloudBlobContainer container = blobClient.GetContainerReference(imageDirecoryUrl);
  63:             List<string> blobs = new List<string>();
  65:             // Loop over blobs within the container and output the URI to each of them
  66:             foreach (var blobItem in container.ListBlobs())
  67:                 blobs.Add(blobItem.Uri.ToString());
  69:             return blobs;
  70:         }
  71:     }

3.4 So, when the files have been uploaded we will get them to present them to out user in the index page. Pretty straight forward. In this example we only present the image by sending the Uri’s to the view. A better way would be to save them up in a view model containing URI, metadata, alternate text, and other relevant information but for this example this is all we need.


4. Now press F5 in your solution to try it out. You can see the storage emulator UI here:




4.1 If you get any exceptions or errors I suggest to first check if the service Is running correctly. I had problem with this and they seemed related to the installation and a reboot fixed my problems.




5. Set up for Cloud storage. To do this we need to add configuration for cloud just as we did for local in step one.

5.1 We need our keys to do this. Go to the windows Azure menagement portal, select storage icon to the right and click “Manage keys”. (Image from a different blog post though).



5.2 Do as in step 1.but replace step 1.6 with:

1.6 Choose “Manually entered credentials”. Enter your account name.

1.7 Paste your Account Key from step 5.1. and click ok.



5.3. Save, publish and run!

Please feel free to ask any questions using the comments form at the bottom of this page. I will get back to you to help you solve any questions. Our consultancy agency also provides services in the Nordic regions if you would like any further support.

Friday, December 21, 2012

Connect to running web role on Azure using Remote Desktop Connection and VS2012


We want to be able to collect IntelliTrace information from our running app and also use remote desktop to connect to the IIS and look around(probably debugging).

1. Create certificate

1.1 Right-click the cloud project (marked in red) and select “Configure remote desktop”.


1.2 In the drop down list of certificates, choose <create> at the bottom.

1.3. Follow the instructions, you can set it up with default values.

1.4 When done. Choose the certificate and click “Copy to File…” as seen in the left of the picture above.

1.5. Save the file with any name you want.

Now we will save it to local storage to be able to import it to our solution through the azure configuration manager in step 3.

2. Save certificate to local storage

Now we need to attach it to our local certificate storage to be able to reach it from our confiuguration manager in visual studio. Microsoft provides the following steps for doing this:

In order to view the Certificates store on the local computer, perform the following steps:

  1. Click Start, and then click Run.
  2. Type "MMC.EXE" (without the quotation marks) and click OK.
  3. Click Console in the new MMC you created, and then click Add/Remove Snap-in.
  4. In the new window, click Add.
  5. Highlight the Certificates snap-in, and then click Add.
  6. Choose the Computer option and click Next.
  7. Select Local Computer on the next screen, and then click OK.
  8. Click Close , and then click OK.
  9. You have now added the Certificates snap-in, which will allow you to work with any certificates in your computer's certificate store. You may want to save this MMC for later use.
Now that you have access to the Certificates snap-in, you can import the server certificate into you computer's certificate store by following these steps:
  1. Open the Certificates (Local Computer) snap-in and navigate to Personal, and then Certificates.
    Note: Certificates may not be listed. If it is not, that is because there are no certificates installed.
  2. Right-click Certificates (or Personal if that option does not exist.)
  3. Choose All Tasks, and then click Import.
  4. When the wizard starts, click Next. Browse to the PFX file you created containing your server certificate and private key. Click Next.
  5. Enter the password you gave the PFX file when you created it. Be sure the Mark the key as exportable option is selected if you want to be able to export the key pair again from this computer. As an added security measure, you may want to leave this option unchecked to ensure that no one can make a backup of your private key.
  6. Click Next, and then choose the Certificate Store you want to save the certificate to. You should select Personal because it is a Web server certificate. If you included the certificates in the certification hierarchy, it will also be added to this store.
  7. Click Next. You should see a summary of screen showing what the wizard is about to do. If this information is correct, click Finish.
  8. You will now see the server certificate for your Web server in the list of Personal Certificates. It will be denoted by the common name of the server (found in the subject section of the certificate).
Now that you have the certificate backup imported into the certificate store, you can enable Internet Information Services 5.0 to use that certificate (and the corresponding private key). To do this, perform the following steps:
  1. Open the Internet Services Manager (under Administrative Tools) and navigate to the Web site you want to enable secure communications (SSL/TLS) on.
  2. Right-click on the site and click Properties.
  3. You should now see the properties screen for the Web site. Click the Directory Security tab.
  4. Under the Secure Communications section, click Server Certificate.
  5. This will start the Web Site Certificate Wizard. Click Next.
  6. Choose the Assign an existing certificate option and click Next.
  7. You will now see a screen showing that contents of your computer's personal certificate store. Highlight your Web server certificate (denoted by the common name), and then click Next.
  8. You will now see a summary screen showing you all the details about the certificate you are installing. Be sure that this information is correct or you may have problems using SSL or TLS in HTTP communications.
  9. Click Next, and then click OK to exit the wizard.
You should now have an SSL/TLS-enabled Web server. Be sure to protect your PFX files from any unwanted personnel.

Image of a typical MMC.EXE with the certificates up.



3. Import the certificate to you visual studio project.

3.1 Now right click your equivalent to the MvcWebRole1 (as seen in the first picture under the red oval) and choose properties.

3.2 Choose Certificates. Right click the ellipsis to the right of the “thumbprint” and you should be able to select your newly created certificate here. After selecting it- save the file.



4. Upload the certificate to your Azure subscription.

4.1 Go to the azure management portal, click the services menu icon to the left and choose the service. Click Upload in the bottom menu.




5. Connect to server.

Since I tried to use account settings(have to use another name) we have to set up a new name for the connection. No biggie.

5.1 Go to azure management portal, select your service and in the bottom menu, choose “REMOTE”. This will display the configuration for remote connection. It will actually change your ServiceConfiguration.cscfg file. After you change It here it might be good to choose download and replace the one in your project. Set a name that is not your windows azure account name and not Administrator.


5.2 Goto visual studio, click Server Explorer. Choose as selected in the picture below and click “COnnect using remote desktop”.


5.2 You will now be able to log in with the name and password set up in step 5.1.

and voila! Windows server 2012, IIS and other nice stuff!



To do this one I’ve been using where you can collect some of this information and additional one.

Intellitrace bug causes “Operation could destabilize the runtime” exception


We cant use it when we use simplemembership to handle external authorizations.


Server Error in '/' Application.

Operation could destabilize the runtime.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Security.VerificationException: Operation could destabilize the runtime.
Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

[VerificationException: Operation could destabilize the runtime.]
DotNetOpenAuth.OpenId.Messages.IndirectSignedResponse.GetSignedMessageParts(Channel channel) +943
DotNetOpenAuth.OpenId.ChannelElements.ExtensionsBindingElement.GetExtensionsDictionary(IProtocolMessage message, Boolean ignoreUnsigned) +282
DotNetOpenAuth.OpenId.ChannelElements.<GetExtensions>d__a.MoveNext() +279
DotNetOpenAuth.OpenId.ChannelElements.ExtensionsBindingElement.ProcessIncomingMessage(IProtocolMessage message) +594
DotNetOpenAuth.Messaging.Channel.ProcessIncomingMessage(IProtocolMessage message) +933
DotNetOpenAuth.OpenId.ChannelElements.OpenIdChannel.ProcessIncomingMessage(IProtocolMessage message) +326
DotNetOpenAuth.Messaging.Channel.ReadFromRequest(HttpRequestBase httpRequest) +1343
DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingParty.GetResponse(HttpRequestBase httpRequestInfo) +241
DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingParty.GetResponse() +361
DotNetOpenAuth.AspNet.Clients.OpenIdClient.VerifyAuthentication(HttpContextBase context) +136
DotNetOpenAuth.AspNet.OpenAuthSecurityManager.VerifyAuthentication(String returnUrl) +984
Microsoft.Web.WebPages.OAuth.OAuthWebSecurity.VerifyAuthenticationCore(HttpContextBase context, String returnUrl) +333
Microsoft.Web.WebPages.OAuth.OAuthWebSecurity.VerifyAuthentication(String returnUrl) +192
PrioMvcWebRole.Controllers.AccountController.ExternalLoginCallback(String returnUrl) in c:hiddenforyou
lambda_method(Closure , ControllerBase , Object[] ) +127
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +250
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +39
System.Web.Mvc.Async.<>c__DisplayClass39.<BeginInvokeActionMethodWithFilters>b__33() +87
System.Web.Mvc.Async.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49() +439
System.Web.Mvc.Async.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49() +439
System.Web.Mvc.Async.<>c__DisplayClass37.<BeginInvokeActionMethodWithFilters>b__36(IAsyncResult asyncResult) +15
System.Web.Mvc.Async.<>c__DisplayClass2a.<BeginInvokeAction>b__20() +34
System.Web.Mvc.Async.<>c__DisplayClass25.<BeginInvokeAction>b__22(IAsyncResult asyncResult) +221
System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__18(IAsyncResult asyncResult) +28
System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +15
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +42
System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +15
System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__3(IAsyncResult asyncResult) +42
System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +15
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +523
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +176

Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.17929