Wednesday, February 27, 2013

Setting up an Internal Friendly URL

Note: This solution is not necessarily the best or most efficient solution in all cases.  It is, however, very simple and works with any site - even ones you have no control over.

Problem:

Internal Web System XYZ must be accessed via an ugly URL such as http://randomservername.internalexample.com:8675309/SomeCrazyPath/SomeFile.htm

Desired End State:

Internal users should be able to type in a friendly URL (such as http://myapp.internalexample.com) and get sent directly to the "homepage" of the desired system.  Search result optimization and using deep links with the friendly URL are not required.

One Solution Using IIS 7.5 (should work with earlier versions by hunting for the same options):

  • Register myapp.internalexample.com and other related host names such as dev-myapp.internalexample.com in your organization's DNS.  If the server where you will be hosting the friendly URL is more likely to change its IP address instead of its name, use a CNAME record; if the server is more likely to change its name but keep its IP address, use an A record.
  • Open your IIS Manager and right-click Sites... Add Web Site.
    • The site name should be "myapp.internalexample.com (redirect)".
    • The physical path should be a folder in a secure location local to the web server.  (whatever is appropriate for your environment - it will only require a few KB of storage).
    • Set the host name to "myapp.internalexample.com" .
    • Hit OK.  This should create the site and start it automatically.
  • Go to the "HTTP Redirect" HTTP Redirect Screenshot option under the IIS section for the new site, and check the box for "Redirect requests to this destination".
    • Set the destination to your application's "real" full URL including the protocol (http or https), port numbers, deep path, document, query string, etc.
    • Check the box for "Redirect all requests to exact destination (instead of relative to destination), but do not check the box for "Only redirect requests to content in this directory (not subdirectories)".
    • The default status code "Found (302)" is fine.
    • Click the crazy Apply button in the far upper right.  Apply Screenshot
  • Next, open the "HTTP Response Headers" option HTTP Response Headers Screenshot 
    • Click the small "Set Common Headers..." button in the actions bar (upper right).
    • You can uncheck "Enable HTTP keep-alive" and set the box to expire web content "Immediately".
    • Click OK.

Set Common HTTP Response Headers dialog

  • Clients should now get redirected to the main site by visiting the friendly URL.  Because the HTTP header indicates that the content expires immediately, the IIS server hosting the friendly URL will be hit every time.  Since the only response is an HTTP redirect enforced by IIS (< 500 bytes), the load should be very light except in the most extreme circumstances, and this gives you the ability to easily change the redirect URL at some point and have the change take effect immediately.
  • If you want to include content in the root folder for the web site to make the intention clear to a server admin browsing to this folder, you can create a default.htm file with the following content:

    <!DOCTYPE>
    <html>
    <!-- Note: This site is redirected via IIS Settings.  This  page should actually never be seen or used. -->
    <head><meta http-equiv="Refresh" content="0;url=
    http://myapp.internalexample.com" /></head>
    <body><a href="
    http://myapp.internalexample.com">Click here to continue to the site.</a></body>
    </html>

Please note, though, that this extra step is absolutely not required, though, since the IIS server should be ignoring all site content due to the HTTP Redirect setting.  It could also "get stale" in case the redirection URL is updated in IIS but not in the HTML file which could cause more confusion.

 

Raw Request to http://dev-mysite.mydomain.com (captured with Fiddler):

Fiddler capture text (Request)

Raw Response from IIS (captured with Fiddler):

image

Wednesday, February 6, 2013

Using SkyDrive at Work for Collaboration - A Quick Start Guide

It seems that many of my projects in the past year or so have required sharing files with external business partners.  I've found that SkyDrive has been quite useful for this purpose.  Here's how to get started quickly and securely sharing files.

Setting up SkyDrive sync:

1. If you don't yet have a Microsoft account, go ahead and sign up using your normal work email address - you don't need a Hotmail account or any Microsoft-specific domain name as your Microsoft user ID anymore.  Use a strong password, or better yet use a password solution like LastPass.

2. Download the SkyDrive application for your system (Windows 7 client is 5.7 MB as of Feb 2013).  This step isn't strictly needed, but it does make the integration much more seamless.

image

3. When the setup finishes, a wizard will ask you to make some unimportant choices and then one very important choice.  One of the items in setup that I personally turn off is the ability to remotely retrieve files on my work PC via the SkyDrive web user interface.  You may find this feature useful, but I've decided that it does not make sense for my scenario.

4. Once the client is installed, you should have a SkyDrive folder in your user profile folder that is set up for synchronization.

image

5. In this folder, create a folder called "Work Collaboration".  This is where you will be making subfolders for projects that you'll be sharing with different sets of people.

When you create a new folder, it will show up with the blue circular arrows indicating that it is syncing with Skydrive...

image

... and after a few seconds, it should show up with a green checkbox indicating that it has synchronized with the cloud.

image

You are now ready to share files.

Here's how sharing works:

So, you need to share a file with a business partner?  Usually, you'd launch your mail client, type an email saying "here is the sales analysis spreadsheet you wanted to look at" and begin to attach the file. However, you know this spreadsheet is going to go back and forth at least a few times with edits. That's a lot of email! Here's the better way.

1. Create a new folder in your Work Collaboration folder called (for example) "Sales Analysis" or whatever makes sense for the project.

image

2. Copy the file there using Windows Explorer. This will automatically kick off the process of synchronizing it.

image image

3. Go back up one level (backspace key in Windows Explorer), right click on the folder you're going to share and click "SkyDrive... Share".

image

4. This will open your browser and log you in to SkyDrive.  You will be presented with the option to "Send email".  Send the email to the work address of your contact(s).  You should always check the box that says "Require everyone who accesses this to sign in" if you care about keeping the files secure.  You can also indicate if the recipients of the email can edit files in the folder (if unchecked, they will have read-only access).

image

Once you click Share, the list of users with granted permissions will display. You can click Done to exit.

 

What happens on the sharing partner's computer?

1. Your partner will get an email with content like this:

image

2. If they are not registered, they will be able to click the link "Sign Up now" on the SkyDrive login page.  You need to tell them to use their work email address to sign up for a Microsoft account.

image

3. Once they're logged in, they will see the folder and can work with the shared documents using the SkyDrive web site.  Any edits or new files uploaded to the folder will be automatically synchronized to your PC when changes are made to a shared folder in your SkyDrive.  If the documents are in one of the MS Office file formats, you or your sharing partners can even use the built-in web-based Office apps to view the documents or make edits.

image

4. If one of your business partners ever wants to get back to the place on SkyDrive that you've shared, they can just log in to their SkyDrive account and click "Shared" on the left-hand pane and your SkyDrive will be listed.

image

When I'm done sharing

When you're ready to stop sharing a file or folder, open it using the SkyDrive... Share option on the right-click menu, or if you are on the SkyDrive site already, use the "Sharing" link at the top.

image

On the left-hand pane, select the individuals you want to remove permissions for, and click "Remove Permissions".  They will no longer be able to access the selected items on your SkyDrive.

 

I hope you find SkyDrive as convenient and painless as I have.  If you have any questions about SkyDrive, please ask!  I'm a member of the SkyDrive Insiders program; you can learn more about this program here.

Saturday, February 2, 2013

Using Inline “With” Blocks to Augment a VB.NET Default Constructor

Say you have a simple data transfer class that looks like this:

Public Class Employee
    Public Property Name As String
    Public Property HireDate As Date
    Public Property EmployeeID As Integer
End Class

Normally to load up this class, you might call something like this:

Dim employee As New Employee
employee.Name = "Steve"
employee.HireDate = #1/1/2013#
employee.EmployeeID = 12345

In this case there is an implied Public Sub New() that gets called for you when the class is instantiated.  However, you could also call this:

Dim employee As New Employee With {.Name = "Steve", .HireDate = #1/1/2013#, _
                                                       .EmployeeID = 12345}

Or in VB 2010 or higher which supports implied line continuation, this:

Dim employee As New Employee With {
                .Name = "Steve",
                .HireDate = #1/1/2013#,
                .EmployeeID = 12345,
            }

Note: if you happen to be inside a “With” block already, the inner “With” will take precedence over the scope of the outer “With”.  This applies to both inline “With” blocks and normal “With” blocks, though nesting “With” blocks is not recommended for code clarity’s sake.

Saturday, November 24, 2012

IIS Express Quickie Command-line

This is a reminder to my future self for how to quickly start IIS Express from the command-line on 64-bit Windows 7 or 8 assuming you already have IIS Express installed using the defaults.

  1. Open admin command line.
  2. cd\Program Files (x86)\IIS Express
  3. iisexpress /path:c:\YourApplicationRootFolder /port:WhateverPortNumber

Note: You can also specify /clr:v2.0 if you hate fun.  The default is CLR 4 which works with .NET 4 and 4.5.

This was adapted from the full article on www.iis.net: http://www.iis.net/learn/extensions/using-iis-express/running-iis-express-from-the-command-line

Monday, November 19, 2012

Surface: Standard Onscreen Keyboard

If you feel that the default on-screen keyboard on the Surface RT isn't sufficient, you can enable what I would say is the "pro" keyboard via the settings.

  • Drag in from the right hand side to show the charms and click Settings.
  • On the bottom of the settings window, click "Change PC Settings" to show the Windows 8-style control panel.
  • Under General... Touch Keyboard... turn on the option called "Make the standard keyboard layout available".

Now when you're displaying the onscreen keyboard, there will be a fifth option available which is a more "standard" Windows keyboard including up arrow, down arrow, and the option for F1-F12 if you hit the Fn key first.  I still haven't found a way to show Insert/Delete/Home/Page Up/Page Down other than with the physical keyboard.

Monday, October 1, 2012

SQL in the City - New York 2012

I was able to attend the SQL in the City event in New York this past Friday.  I highly recommend that anyone who can spare the time and travel should attend the next SQL in the City day in your area.  I found it to be a very well put-together event with useful content and excellent networking opportunities.

At the event I was able to meet both Steve Jones (who compassionately shook my hand as I walked in dripping wet from the rain during my walk over to 3rd Avenue) and Grant Fritchey (Scary DBA).  It was great to have even a brief conversation with each of them and introduce myself.  I also got to meet Product Manager David Atkinson and Developer David Simner and talk briefly about the awesome SQL Source Control and SQL Compare products.  The presentations I attended, "Database Maintenance Essentials", "Red Gate Tools - the Complete Lifecycle", and "The Whys and Hows of Database Continuous Integration" were all very informative and useful.

The highlight of the day was finding out about Red-Gate's Virtual Restore product.  This tool essentially allows you to mount a .BAK file as a database.  It supports multiple databases mounted from the same .BAK file, and it is not destructive to the .BAK file.  From the description, it works very similarly to VMs that are mounted from a disk file and then store changes in a disk "diff" file.  This tool allows you to save both space and time and sounds very awesome for developers.

I must say that I think Red-Gate has made a critical error with the marketing of this tool.  Developers hear "restore" and think "DBA tool"; in fact I think that's what the Red-Gate marketing team thought too as this application is included in their DBA bundle only.  I would absolutely use this tool as a developer and I might even use it as often as I use things like SQL Compare and the rest of the more developer-oriented tools.  It's a game-changer, and I hope Red-Gate figures out that they're doing a very bad job of marketing this product and could probably be making a lot more money from it by just getting the word out that it's not only a DBA tool.  For most of the other Red-Gate developer tools, a savvy developer could imagine cooking-up some sort of "good enough" workaround to not have to buy it (though certainly not in a shorter time than the reasonable expense for the license), but I would never even attempt creating something like Virtual Restore.  I will absolutely be trying out this software later this week.  Red-Gate - you've got to get the word out, even think about changing the name or something!!!

Thanks very much to everyone at Red-Gate for putting this event together.  I hope to see you again at the next SQL in the City.

Tuesday, August 28, 2012

PowerShell: Redirecting Console Output and Error Output to a Variable and E-mailing it

I recently had the need to script the execution of a command-line utility and thought it would be a good learning experience to try doing it with PowerShell.  The utility would sometimes output to the STDOUT, but would also send its output to STDERR if there was a problem.  This seemed to involve many different problems all at once including:

  • Running an EXE with a space in the path and multiple command-line parameters
  • Capture both STDERR and STDOUT to a variable
  • Escaping special characters/using special characters
  • Doing string concatenation
  • Doing explicit type conversion
  • Sending an email
  • Joining a string array to a single string variable
  • Doing a "FOR" loop (optional but fun).

Anyway, here's the script I came up with that runs a command-line app and takes all the output (including the error stream) and joins it into a string and then sends it in an email to me.  It's a bit ugly because I am a PowerShell novice, but it does work.  The only trouble I've noticed is that sometimes the error lines will be a bit out of sequence from the corresponding stdout lines.  If someone knows how to fix that, please let me know in the comments!!!

 

#Setup the command string - notice the `" to escape the double-quotes inside the string (deals with spaces in path)

# and the old batch file trick of doing 2>&1 to ensure STDERR is piped to STDOUT.

$command = "& `"C:\Users\myprofile\Documents\visual studio 2010\Projects\TestOutput\TestOutput\bin\Debug\testoutput.exe`" someparameter -xyz someotherparameter -abc someotherthing -rfz -a somethinghere 2>&1"
#Execute the command and put the output in an array.

$console_output_array = invoke-expression $command

#loop through the array and print out the results to the command line (optional)

for ($i=0; $i -lt $console_output_array.length; $i++)
{
    [string]$i + "=<" + $console_output_array[$i] + ">"
}

#create a single string by joining together the array

$console_output_string = [string]::join("`r`n",$console_output_array)

#send an email with the results

$emailFrom = "fromemail@example.com"
$emailTo = "toemail@example.com" 
$subject = "Email subject goes here"
$smtp = new-object Net.Mail.SmtpClient("yoursmtpserver.example.com", 25)
$smtp.Send($emailFrom, $emailTo, $subject, $console_output_string)