SEO Improvements in ASP.NET 4


In ASP.NET 4 there are a few improvements that have been made to make it easier to make tweaks to improve Search Engine Optimization (SEO) on your pages. I’ll be the first to say it and definitely not the last but these improvements are not ground breaking or “sexy” but it does make your life a little easier. There are three main improvements that have been made. First is that webforms now has a better story for routing your pages to friendly URLs, however I am going to skip that one for now because that is a whole post itself. The other two are simply just properties that hang of the base page class that allow you to specify meta tags.

Meta tags are a special tag that can be placed in html to provide meta information about that particular page. This information can be anything from the author of the page to an expiration timeout for a caching system. (More information on common/standardized types of information can be found on the W3C site). For this post the ones that we are concerned with are the “Keywords” and “Description” content types. The keyword content type provides information to search engines about what information is on the page. However, for obvious reason most search engines don’t put to much “weight” on this meta tag. The description content type on the other hand is pretty useful, as most search engines include a short description of the site below the link to the site.

image

In this case most search engines will use the description meta tag as it likely provides more human friendly context to the site.

  1. <meta content="en-us" http-equiv="Content-Language" />
  2. <meta content="By trade I am a QA member on the Microsoft ASP.NET Team. By choice I host a podcast called Coding QA and work on LTAF." name="description" />


Okay so know you know what Meta tags are lets talk about how to get them to show up in your ASP.NET pages. There are two new properties that hang off of System.Web.UI.Page; MetaDescription and MetaKeywords. You can set these in the code behind of the page or in the page directive.

  1. <%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
  2.     CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default"
  3.     MetaDescription="Description" MetaKeywords="Keywords" %>


Now I’m sure you can imagine a much more creative use for these than static text, like changing them based on the content of the page pulled from the database, but for now we will just use static text.

  1. <head>
  2.     <title>Home Page</title>
  3.     <link href="Styles/Site.css" rel="stylesheet" type="text/css" />
  4.     <meta name="description" content="Description" />
  5.     <meta name="keywords" content="Keywords" />
  6. </head>

Well, that is all there really is to these two small improvements. Like I said there is nothing ground breaking or “sexy” about them. They were simply designed to help make your life a little more easy.

author: Matthew M. Osborn | posted @ Tuesday, March 09, 2010 4:39 PM | Feedback (0)

Managing Hyper-V from Windows 7


Recently everyone on my team has switched to using Hyper-V as our primary means of virtualization. The combination of Hyper-V and differencing disks works great for our team as we install all kinds of bit that more than likely will explode our computers. We are testers after all. There was one thing that really took me awhile to figure out and quite frankly most people on my team don’t know you can do (hence the blog post), mange my Hyper-V install from another machine in this case a windows 7 machine.

imageMost people just simply have the Hyper-V machine hooked up to the KVM and switch back and forth when the need to change something or remote into it. This is great but I don’t really like that use case, so I went searching for something else. I found out the you can manage Hyper-V installs as well as pretty much every aspect of a server through the Remote Server Administration Tools. In Vista and Server OSes this is simple, just go to the “Turn Windows feature on or off” section of the control panel and check the right boxes. However, if you’re on a Windows 7 Machine you will notice that they are missing.

Okay so how do you get the option to install the Remote Server Administration Tools? This is the tricky part and what took me awhile to figure out.Why was it tricky you ask, because you have to know you need to install Remote Server Administration Tools to be able to manage Hyper-V installs. For me when I did a search on the internet on how to manage Hyper-V installs from Windows 7 all I got was some posts about installing a version of Hyper-V manager for Windows 7 Beta, all of which were dead links. After some time I figured out that it was Remote Server Administration Tools you needed to install to get Hyper-V manager. So here is how to get everything set up to remotely manage your Hyper-V installs.

  1. Download and install the Remote Server Administration Tools from Microsoft.
  2. Go to the “Turn Windows features on or off” and install the Hyper-V tools. (It’s under Remote Server Administration Tools > Role Administration Tools) image
  3. Now you can open the Hyper-V Manager Console. (Just search for Hyper-V in the start menu)image
  4. Right Click on the “Hyper-V Manager” Node in the left panel and select “Connect to a Server”.
  5. Check the “Another Computer” radio button and enter the name of the computer.image
  6. Rinse and repeat on as many computers as you like. (This is the same interface you already use to manage Hyper-V so it should be just like home)

Hope this helps, it been working great for me as I have full control of the Hyper-V install without having to remote into the server anymore. 

author: Matthew M. Osborn | posted @ Monday, March 01, 2010 10:00 AM | Feedback (0)

Heading to Mix10


Mix10_SeeYou_blk_240So I decided that I am going to make the trip out to Las Vegas for MIX10. The cool thing about going to MIX this year is that I am going completely on my own as an attendee not a Microsoft Employee. So that means I Actually get to have fun the whole time not work during the whole thing. There are a lot of great speaker and to be honest I’m super excited to get to go learn about that that doesn’t really have to do with my daily job, like Windows Phone 7 Series development. I really haven’t had a chance to branch out try developing on other things, so this should be fun. Plus MIX10 was scheduled at the best time to be in Vegas, over St. Patty’s Day! I’m heading out the weekend before so if you’re going to be there drop me a line. Also, I think I might try to bring some of the recording equipment so if you’re interested in being on the Coding QA podcast let me know.

author: Matthew M. Osborn | posted @ Wednesday, February 24, 2010 2:33 PM | Feedback (0)

We Want You, The SQL-RS Edition


We Want You! If you're a test ninjaThe SQL Server Reporting Services (SQL-RS) Team is looking for the brightest and best testers out there. The SQL-RS team is responsible for the Microsoft Chart Control (Included in .NET 4), the Report Viewer, the Map Control, and the Gauge Control. I personally worked with the SQL-RS test team when they were shipping the Microsoft Chart Control for ASP.NET and they have a lot of bright and fun people over there. The next big thing for this team is to create Silverlight versions of these controls and increase integration in SharePoint and Office. So if this sounds like something you would like to test head over the the job posting and submit your resume.

author: Matthew M. Osborn | posted @ Thursday, February 04, 2010 2:48 PM | Feedback (0)

Updated MVC Script Helpers


Okay so if you read this title and said “wait… MVC has Script helpers?!” you should first go read my original post on MVC Script & Css Helpers. Okay now for those of you who know what they are or just finished reading about them, I was able to add a small feature from Beta to RC to the script helper that I just didn’t have time to code the first time. If you download the new RC futures assembly and add it to your project or update the existing one you will notice that the script helper now has an overload.

Overload

If you have not been able to figure out what this overload does, it allows you to specify a path to a second file to use when you are debugging. For instance it is pretty common to minify JavaScript which basically makes it impossible to read or understand. Most developer maintain to versions on the JavaScript one minified and one not for debugging purposes. In fact if you are using the ScriptManager control in ASP.NET this has the same basic functionality.

  1. <head>
  2.     <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
  3.     <%= Html.Css("Site.css") %>
  4.     <%= Html.Script("MicrosoftAjax.js", "MicrosoftAjax.debug.js") %>
  5. </head>

So you might be asking how we know when to render the debug script or the release script. This is based off the same logic that the ScriptManager control uses. If the HttpContext.IsDebuggingEnabled is set to true then we will render the debug script. There are a couple ways in which the IsDebuggingEnabled is set to false all of which can be found on MSDN.

Hopefully this makes the script helper a little more useful. I would love to continue to improve these and maybe even bring them into the main framework some day so please let me know what you think! In fact, this improvement was a request on my original post. You can download MVC Futures here.

author: Matthew M. Osborn | posted @ Friday, December 18, 2009 3:15 PM | Feedback (0)

We want you (again)! If you’re a test ninja


We Want You! If you're a test ninja

That’s right you read the title right the ASP.NET QA team is once again hosting ninja try outs. We are looking for someone who is able to help evolve the team processes, improve our tooling, and join us in the trenches as we test one of the best technologies out there. Overall the team is responsible for ASP.NET WebForms, ASP.NET MVC, Microsoft AJAX, and a whole slew of other technologies. Our technologies can be found in numerous large scale web sites such as MySpace.com, Dell.com and Deals.Woot.com.

Once again we would like to find someone that shares our passion for our technology and our trade and someone that has spent sometime in the trenches. So if this sounds like something you’re interested in polish your nun chucks, practice your disappearing skills, and slice your way through our job posting. In the meantime while your sword is out for sharpening send Mark Berryman (one of our managers) an email.

PS: If you listen to the Coding QA podcast you can get a good feel for what it is like being the frontline testing ninjas for ASP.NET. We had a great turn out last time and please feel free submit your resume again it can’t hurt.

author: Matthew M. Osborn | posted @ Tuesday, December 01, 2009 12:57 PM | Feedback (1)

Overriding the HTTP Verb in ASP.NET MVC 2


The Problem

Okay so lets start with a little bit of background on what a HTTP verb is. Raise your hand if you know what they are… Okay put it down people in your office are starting to stare at you. So without dragging out the explanation the HTTP verb is basically the way in which a request tells the server what it is trying to do. Most developers are familiar with the concept of a POST and GET request, however those are not the only types of HTTP verbs. There is also PUT, DELETE, and HEAD requests. Up until the advent of the “RESTful” buzz word the only verbs that ever really got used on a large scale were HEAD, GET, and POST. In fact most of the standard browsers can only issue those types of requests.

So what is the problem? We’ll some people out there (including some on ivory towers) like to have very thing be semantic. So if you have an action that deletes a row from the database the request should use the DELETE verb. Now we could argue the relevance of the need to follow this method but I don’t feel like it and its my blog post. If you remember what I said earlier about browsers you’ve probably already figured out the problem. That is right most browser can’t issue a DELETE request.

The Solution

The solution in ASP.NET MVC 2 is a rather small feature that was added to the framework as the result of the WCF team creating the REST Start Kit for MVC. That feature is the ability to override the HTTP verb in one of several ways so that the client, in this example the browser, is still issuing a POST request but the framework treats the request like the verb specified in the override.

There is three ways in which a developer can choose to override the HTTP verb and they all use the special cased key “x-http-method-override”. First, is to add a HTTP header to the request. This scenario is primarily for AJAX requests and in ASP.NET MVC 2 our AJAX helpers will add this header when need. The Second way is to add a hidden field to the form. The Last way is to use the query string to override the verb. The order of precedence works from the header version to the hidden field version to the query string version. If you are familiar with the way model biding works in ASP.NET MVC this is basically the same order of precedence. There is also some restrictions on what can be override. For instance a GET request cannot be overridden to anything else.

The Sample Code

HTTP Header

When you override the verb using the header method you need to add a http header with the special cased key “x-http-method-override” and the value of what you would like to override the verb to. When you use the AJAX helpers to issue a request this is done for you if you specify one of the verb types that needs to be overriden.

<% using(Ajax.BeginForm(new AjaxOptions(){HttpMethod="Delete"})){ %>
     <input type="submit" value="Delete Using Http Header" />
<% } %>

Now if you look at the request you can see that there is an additional header added with the new value and ASP.NET MVC will treat that request as that verb type.

HttpHeader

Hidden Input

This method is basically the same as the header method but instead of a header it is a hidden input with the name and value.

<% using (Ajax.BeginForm(new AjaxOptions())){ %>
    <input type="hidden" name="x-http-method-override" value="Put" />
    <input type="submit" value="Put Using Hidden Field" />
<% } %>

Query String

Once again this works very similar to the other two methods. All you need to do is add the parameter “x-http-method-override” with the value of the desired override in the query string of URL that form will POST to. In this sample this is done using the overload to BeginForm that takes a RouteValue Collection because if the values are not used in the matching route they will get tacked on the URL in the query string.

<% using(Ajax.BeginForm("HttpVerbOverride", new RouteValueDictionary(){{"x-http-method-override", "Delete"}}, new AjaxOptions())){ %>
    <input type="submit" value="Delete using Query String" />
<% } %>

Summary

This is a pretty simple solution a problem that not all of you will face but I choose to write about it because it is one of the little know improvements we are making to version two of the framework. If you choose not to use this feature the only impact will be that “x-http-method-override” is now effectively a reserved/key word.

Demo Website: HttpVerbOverrideDemo.zip

author: Matthew M. Osborn | posted @ Tuesday, November 24, 2009 11:09 PM | Feedback (0)

MVC Script & Css Helpers


During development of MVC 2 Preview 2 I was lucky enough (I’m on the QA team after all) to get to code and check in a feature that I wanted to MVC Futures. In all actuality it is two separate “features” that basically do the same thing. Okay, I think I might be blowing it out of proportion they are basically two new HTML helpers “Script” and “Css

The Problem:

When you add links to to files (aka Scripts and CSS) the URLs are normally relative to the current page’s URL. This means that if you have “../../Scripts/jquery-1.3.2.js” it means go up two segments then down to the scripts segment. This works great but when you start using routing the pattern starts to fall apart. By this I mean that because routes change often and don’t map nicely to folders going up two segments and down one might not get you to the right folder on all your pages. To get around this most people use app rooted paths “~/Script/jquery-1.3.2.js”. The “~” basically means go to the app root and then go down. However, this is not a concept that browsers understand “~” is handled by the web framework in this case ASP.NET and ends up getting converted to the proper relative path before being sent to the client. Like I just said HTML has no concept of what “~” means when you use it in the href or src of and HTML element “most” of the time the framework detects that and converts it for you. For instance ASP.NET will convert Link tags if they are in the head tag with the attribute “runat” set to “server”. However other tags like Script tags will not have their paths converted. So to get around this it is best practice to use the “Content” method hanging off the “URL” helper which will convert an app rooted path to the correct path.

  1. <head runat="server">
  2.     <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
  3.     <link href="~/Content/site.css" rel="stylesheet" type="text/css" />
  4.     <script src="<%= Url.Content("~/Scripts/jquery-1.3.2.js")%>" type="text/javascript"></script>
  5. </head>

 

 

The Solution:

So you can see for yourself how this can make your code look ugly and then you have that “runat” attribute on the head tag that is some kind of left over from your web forms programming days. I soon grew very tried of copy and pasting the same tag over and over for each script and just changing the name. so I figured that the ASP.NET MVC framework had helpers for everything else so why not Scripts and CSS? So after a little bit of clever coding there is now a Script helper and a CSS helper.

There are a couple of ways to use them first and the most simple to to just give it a file name or a folder that is inside the default location. For Scripts that is “~/Scripts” and for CSS that is “~/Content”.

  1. <head>
  2.     <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
  3.     <%= Html.Css("BlueTheme/site.css") %>
  4.     <%= Html.Script("jquery-1.3.2.js") %>
  5. </head>

Basically there is some very simple logic that says if the path doesn’t start with “~”, “../”, “HTTP”, or “HTTPS” it is a file name or a path that is under the default folder for each type. That leads me to my next point which is that if the path you give the helper looks like you are trying to give it a full path (aka the strings mentioned above) then it will still create the nice tag for you but wont add to the file path. This means that you can use this with the New AJAX CDN and still have all your script tags look the same at that top of the page. Hey call me vain but I like to have pretty code.

  1. <head>
  2.     <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
  3.     <%= Html.Css("~/myThemes/BlueTheme/site.css") %>
  4.     <%= Html.Script("http://ajax.microsoft.com/ajax/jquery/jquery-1.3.2.js") %>
  5. </head>

However there is an extra overload that the CSS helper that allows you to pass a media type. For those unfamiliar with CSS every time you link to a StyleSheet you can add the media type attribute that allows you to specify when to apply that style. The most common use of this is to define a “Print” style so when a user goes to print out part of your page the website will optimize itself for printing. If you choose not to specify a media type that style will be used for all the media that doesn’t have a StyleSheet defined for it (no media type is the helpers default).

  1. <head>
  2.     <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
  3.     <%= Html.Css("~/myThemes/BlueTheme/site.css", "screen") %>
  4.     <%= Html.Css("~/myThemes/BlueTheme/print.css", "print") %>
  5. </head>

Also as I mentioned before notice that you no longer need to include the “runat” attribute on the head tag. This isn’t anything special but hey it looks cleaner.

The drawback:

Okay so this solution isn’t perfect, sorry I know I got you all excited and now I’m letting you down. The problem is that Visual Studio does not know to parse these new helpers when it updates intellisense. So yes that means not intellisense, sorry! However if you followed best practice and used the URL helpers you wouldn’t have got intellisense either. Previously I found myself not using the URL helper when I was developing and then just changing it to use the URL helper after I was done and I do the same thing with the new helpers.

Conclusion:

Like I said its not perfect but its a small improvement over the way things were done before. I would love to continue to improve these and maybe even bring them into the main framework if there is enough requests for them so please let me know what you think! But be nice this is my first try at coding a “feature”. You can download MVC Futures here.

author: Matthew M. Osborn | posted @ Monday, October 12, 2009 11:46 PM | Feedback (8)

ASP.NET MVC 2 Preview 2 Released


I am proud to announce that ASP.NET MVC 2 Preview 2 has been released! So what are you waiting for? Go download it, its okay I’ll wait here… If you are running MVC 1.0 the good news is that just like Preview 1, Preview 2 can live side by side with it. However, as with previous preview releases, it is recommended that you uninstall Preview 1 prior to installing Preview 2. Currently there is no glamorous way of converting a MVC 1.0 project to a MVC 2 project but it is a pretty simple process and instructions can be found in the released notes.

Okay now for some more interesting stuff, the new features that are in Preview 2. If you missed Preview 1 you can read Phil’s post to see what was in that release.

  • Single-Project Areas: For those of you familiar with Multi-Project Areas from Preview one this should be a span. If not, an area is simply a way of segregating logical units of  your application. For instance, think of segmenting the blog and store in a company website. The difference now is that this can all be done inside of a single project file.
  • Client Side Validation: Client side validation was something that the ASP.NET MVC framework was missing, well not anymore. Basically out of the box we support the ability to have nice client side validation when you annotate your model objects use Data Annotations. However, this is completely extensible and you can create your providers both for client side and server side validation.
  • ModelMetaData: As MVC 2 started to grow in its feature set it became apparent that the ability to easily access metadata about the model was very important. So after a few rubs on the oil lamp and a chat with a genie, poof we now have and object call ModelMetaData that hangs off of the ViewDataDictionary. Just like client validation this is completely extensible and you have the ability to create your own provider. Out of the box we have built in functionality for Data Annotations.
  • HTTP Verb Overrides: Anyone that has worked with ASP.NET MVC for any amount of time is familiar with HTTP Verbs. Basically a HTTP Verb is a value passed to the server such as GET or POST that tell the server what the client is trying to do. However, there are several lesser known verbs like PUT and DELETE, because quite simply most browser can only use three verbs, HEAD, GET, and POST. This is not true anymore! Well at least for ASP.NET MVC 2 that is. We know allow you to override the POST verb with any of the others. Along with that we have also create some nice shortcut attributes to use when marking actions in your controller just like the HttpPost one in Preview 1.
  • Tons of Other Stuff: To try to keep this post some what short I decide to wrap some of the smaller items into one bullet point as it would take a long time to explain them all. The short of it is that there is lots of cool features, bug fixes, and some API changes in Preview 2. Some of the notable ones are new code snippets, additional default templated helpers, and a new attribute to mark an action as needing HTTPS.

So please go download it, try it out, and give us your feedback! After all that is the whole idea of releasing these previews. Also I would like to give a big thanks to everyone on the team that helped to make this a successful release!

author: Matthew M. Osborn | posted @ Thursday, October 01, 2009 12:28 AM | Feedback (2)

We want you! If you’re a test ninja


We Want You! If you're a test ninja Okay everyone, here is the deal, the ASP.NET QA Team has a position open and we are looking for the stealthiest ninja we can find! We are looking for someone who is able to help evolve the team processes, improve our tooling, and join us in the trenches as we test one of the best technologies out there. Overall the team is responsible for ASP.NET WebForms, ASP.NET MVC, Microsoft AJAX, and a whole slew of other technologies

We would like to find someone that shares our passion for our technology and our trade and someone that has spent sometime in the trenches. So if this sounds like something you’re interested in pick up your best uniform from the dry cleaner, polish your throwing stars, and visit our job posting. [If the job listing site is having trouble email your resume to Leslie Dietz, our test manager, please include “SDET Position” in the subject line]

FYI: If you listen to the Coding QA podcast you can get a good feel for what it is like being the frontline testing ninjas for ASP.NET.

author: Matthew M. Osborn | posted @ Tuesday, September 01, 2009 12:34 AM | Feedback (2)