Posts
  • CarlosAg Blog

    "EXCEL.EXE is not a valid Win32 application" problem in Windows Vista

    • 3 Comments

    Every now and then after leaving my computer running for several weeks I would get a weird error message when trying to launch Excel saying something like:

    C:\PROGRA~1\MICROS~1\Office12\EXCEL.EXE is not a valid Win32 application.

    or

    This file does not have a program associated with it for performing this action. Create an association in the Set Associations control panel.

    I tried several things to make it run again, but only a restarting would solve the problem. Finally, I decided to investigate a bit more and turns out there is a fix that solves the problem that you can download from Microsoft support:

    http://support.microsoft.com/kb/952709

    This update improves the reliability of Windows Vista SP1-based computers that experience issues in which large applications cannot run after the computer is turned on for extended periods of time. For example, when you try to start Excel 2007 after the computer is turned on for extended periods of time, a user may receive an error message that resembles the following:

    EXCEL.EXE is not a valid Win32 application

    I just installed it and so far so good, no more weird errors but I guess I need to wait a few weeks before I can testify it works. Either way I though this could be helpful for others.

    Direct links for the fix download are:

    Windows Vista, 32-bit versions
    Download the Update for Windows Vista (KB952709) package now. (http://www.microsoft.com/downloads/details.aspx?FamilyId=DF72A9B0-564E-4326-894E-05CBA709CB39)
    Windows Vista, 64-bit versions
    Download the Update for Windows Vista for x64-based Systems (KB952709) package now. (http://www.microsoft.com/downloads/details.aspx?FamilyId=C3536CAA-7B71-4525-9D23-21A5B3D4507F)

  • CarlosAg Blog

    Using the IIS 7.0 Managed Configuration API

    • 3 Comments

    More than a year ago I wrote about Microsoft.Web.Administration.dll and how it was a new API we were creating for managed code developers to be able to easily set any configuration settings of IIS, however I purposely ignored the configuration part of the API.

    Later I talked about the way configuration was organized in IIS 7.0 and how configuration files inherited and worked.

    Recently I was asked about some samples on how to modify IIS configuration and decided it was about time to talk about the configuration part of Microsoft.Web.Administration.

    The first thing to really emphasize is that Microsoft.Web.Administration in a way has two different ways of reading configuration:

    1. Run time: This is a read-only version of configuration that is meant to be used when running inside a worker process in IIS. It is exposed through a class called Microsoft.Web.Administration.WebConfigurationManager and its GetSection() method with several overloads. Since this blog is about changing configuration I will not be mentioning this API, but suffice to say, it works the same except you get a read-only section.
    2. Design time: This API is our management story for modifying configuration from managed code, it is exposed through the class ServerManager and several of its methods listed below:
    public sealed class ServerManager : IDisposable { 

        
    // Note: some properties and methods were ignored since I'll focus on only these 

        
    public void CommitChanges()

        public void 
    Dispose()

        public 
    Configuration GetAdministrationConfiguration()

        public 
    Configuration GetApplicationHostConfiguration(...)

        public 
    Configuration GetRedirectionConfiguration(...)

        public 
    Configuration GetWebConfiguration(...)

        public static 
    ServerManager OpenRemote(string serverName)
    }

    Whenever you work with the configuration system in IIS you need to:

    1. Figure out which section you want to modify

      The entire configuration in IIS is organized in sections inside configuration files. Sections are composed of elements, attributes, collections and potentially even methods. If you want to know what is the section you are looking you can search it in %windir%\System32\Inetsrv\Config\schema which is the folder where we place all the "schema" files that entirely describe the configuration in IIS.

    2. Figure out for which object you want to manage

      The configuration systemin IIS 7.0 is distributed and as such each child object inherits the configuration of its parent, so for example an application inherits the configuration of the site and the site inherits configuration from the server. So now you need to decide which objects you want to manage, for example, do you want to enable Windows Authentication for the entire server or do you only want to enable it for a particular site or application.

    3. Determine in which place you want to make the change

      As the previous bullet mentions the configuration system is distributed so now you can actually make the changes in different levels for the same object, for example you can modify applicationHost.config with a locationPath "Default Web Site" or you can obtain the same behavior by modifying a web.config file inside wwwroot directory. The concept that really impacts this decision is configuration locking since based on the settings that the server administrator has configured it might be invalid to set authentication in the web.config and might only be possible to set it in applicationHost.config.

    OK, after all that talking lets go to the some actual examples and apply the 3 steps above.

    All the code below assumes you have added a reference to Microsoft.Web.Administration.dll (located at %windir%\system32\inetsrv\) and that you are adding a "using Microsoft.Web.Administration;" at the top of your C# file.

    Enable Directory Browsing for Default Web Site

    1. Looking into system32\inetsrv\config\schema\IIS_Schema.xml you will find that the correct name of the section I'm looking for is system.webServer/directoryBrowse
    2. I only want to modify Default Web Site
    3. Since I now that IIS by default is not locked then I'll make the change directly in the web.config of the site so that when you XCopy my site to another server it remains working the same way.

    Code:

        using (ServerManager manager = new ServerManager()) {

          Configuration webConfig 
    manager.GetWebConfiguration("Default Web Site");

          
    ConfigurationSection directoryBrowseSection =

          
    webConfig.GetSection("system.webServer/directoryBrowse");

          
    directoryBrowseSection.SetAttributeValue("enabled"true);

          
    manager.CommitChanges();

        

    The code uses ServerManager to get the web.config of the web site and then queries the directoryBrowse section and sets the attribute 'enabled' to true. If you open IIS_Schema.xml you will see that this section defines the 'enabled' attribute as a Boolean.

    <sectionSchema name="system.webServer/directoryBrowse">
      <attribute name="enabled" type="bool" defaultValue="false" />
      ...
    </sectionSchema>

    As you can see this API offers a loosely typed object model to ready and modify configuration, with the most important objects being Configuration, ConfigurationElement and ConfigurationAttribute.

    Adding a Handler for the application MyApp underneath Default Web Site

    1. Looking into system32\inetsrv\config\schema\IIS_Schema.xml you will find that the correct name of the section I'm looking for is system.webServer/handlers
    2. I only want to modify Default Web Site/MyApp
    3. In this example let's actually modify applicationHost.config.

    Code:

        using (ServerManager manager = new ServerManager()) {

          Configuration webConfig 
    manager.GetApplicationHostConfiguration();

          
    ConfigurationSection handlersSection =
              
    webConfig.GetSection("system.webServer/handlers""Default Web Site/MyApp");

          
    ConfigurationElementCollection handlersCollection handlersSection.GetCollection();

          
    ConfigurationElement handlerElement handlersCollection.CreateElement();

          
    handlerElement.SetAttributeValue("name""MyHandler");
          
    handlerElement.SetAttributeValue("path""*.myhandler");
          
    handlerElement.SetAttributeValue("verb""GET");
          
    handlerElement.SetAttributeValue("type""CarlosAg.IIS.Samples.MyHandler");

          
    handlersCollection.Add(handlerElement);

          
    manager.CommitChanges();
        

    In this case the handlers Section has a default collection which is where we want to add our handler. For that we use the CreateElement() method to get a new element that we can set the attributes and then add it.

    Removing our Handler

    1. Same system.webServer/handlers
    2. Same Default Web Site/MyApp
    3. Same applicationHost.config.

    Code:

        using (ServerManager manager = new ServerManager()) {

          Configuration webConfig 
    manager.GetApplicationHostConfiguration();

          
    ConfigurationSection handlersSection =
                  
    webConfig.GetSection("system.webServer/handlers""Default Web Site/MyApp");

          
    ConfigurationElementCollection handlersCollection handlersSection.GetCollection();

          foreach 
    (ConfigurationElement handlerElement in handlersCollection) {

            
    if (String.Equals((string)handlerElement.GetAttributeValue("name"), "MyHandler", StringComparison.OrdinalIgnoreCase)) {
              handlersCollection.Remove(handlerElement)
    ;
              break;
            
    }
          }

          manager.CommitChanges()
    ;

        
    }

    Unfortunately currently there is no way to search collections so your only option is to iterate through elements and find the match you are looking for, in this case I'm matching by the name and then removing it from the collection.

    Hopefully that should give a good initial steps on how to start working with configuration using Microsoft.Web.Administration, there are several other options I'll be mentioning in other post on how to lock configuration, how to set metadata, how to enumerate configurations and how to do much more advanced stuff for the few developers that will actually need advanced control of IIS configuration.

  • CarlosAg Blog

    Sudoku and Tetris Game for Windows Mobile

    • 3 Comments

    During my last two business trips (to Barcelona for TechEd and Mexico for ReMix) I was way too bored on the plane and since I recently got my Motorola Q9 (which is a sweet Windows Mobile Phone) decided to write myself a Tetris game and to port my Sudoku game to Windows Mobile as a way to do my "first steps" in the .NET Compact Framework.

    To my surprise it was really easy to write them and even more to port the desktop version of Sudoku to run in all the .NET Compact Framework platforms.

    Since holidays are coming I thought of share them as a gift for this holiday's season.

    Bottom line (with the risk of sounding like a marketing dude, which I'm not) .NET is a cool technology that makes it really easy to code for many devices, from high-end servers to hand held devices to mobile phones. In this case, I have tested these applications with a Pocket PC, Smartphone 2003, Windows Mobile 5 and Windows Mobile 6. And best of all, the code base is pretty much the same as the Desktop version.

    You can install both games by browsing from your mobile device to http://www.carlosag.net/mobile/ where you will find instructions on how to install the .cab files, or just click the images below to go to the download page for each game.

    Sudoku for Windows Mobile            Tetris for Windows Mobile

     Happy holidays!

     

     

  • CarlosAg Blog

    Windows Live Writer Plugin to insert Colorized Code

    • 3 Comments

    When I installed Windows Live Writer for the first time I was skeptical of having a different blog writer, so far I was very happy using Microsoft Word 2007 as my blog editor. However I decided to give it a try and see what I could get from it.

    Now, I can only tell you that I love it, the biggest reason is because it comes with a simple API that allows you to extend it and add functionality to it. This approach of exposing the platform really makes me feel I can do everything, and if I can't, then I can just extend it to do what I need.

    In my case every time I blog something that uses code, I always try to "colorize" it (personally find it easier to read when code is formatted using colors). That is the reason I wrote my original Code Colorizer application so that I could just paste the code in, and get the HTML that I would then tweak manually directly in the blog engine.

    Now that I'm using Windows Live Writer, I decided to test-drive the extensibility model they expose and wrote my Code Colorizer for Windows Live Writer so that I don't need to hand edit anything.

    The idea is that you just download the DLL into the Plugins (C:\Program Files\Windows Live\Writer\Plugins) directory, launch Live Writer and now, you will get a task "Insert Colorized Code..." that will show you a dialog where you can either type the code or just paste it and the right HTML will be inserted in your blog.

    This for the first time makes it really easy for me to insert formatted code without the need to tweak anything by hand.

    You can download it for free at: http://www.carlosag.net/Tools/WindowsLiveWriter/Default.aspx

    The following video uses Silverlight to show how this works (Click the image to start playing):

    The following image shows a snapshot of the tool in action:

  • CarlosAg Blog

    IIS Admin Pack: Configuration Editor

    • 3 Comments

    Today I will be talking about one of the features included in the new IIS Admin Pack called Configuration Editor.

    Configuration Editor is an IIS Manager feature that will let you managed any configuration section available in your configuration system. Configuration Editor exposes several features from configuration that are not exposed anywhere else in IIS Manager, including:

    1. Schema Driven - Config Editor is entirely driven by the configuration schema (found in \windows\system32\inetsrv\config\schema\), this means that if you extend the configuration system creating your sections, they will be available for managing inside config editor, no need to build additional UI for them.
    2. Additional Information - Config Editor exposes more information such as the deepest place where the section is being used, or where a particular element in a collection is coming from (where is it inherited from?), etc.
    3. Script Generation - Allows you to make changes and it generates the code to automate those tasks, generating Managed Code (using Microsoft.Web.Administration), JavaScript (using AHADMIN) or Command Line (using AppCmd).
    4. Searching - Allows you to quickly perform scoped searches of the configuration system for all the sections and where they are being used, becoming a great way to get a bigger picture of the server as well as to prevent configuration locking violations and many other uses.
    5. Locking - Allows you to do advanced locking such as locking specific attributes so that they cannot be used in deeper locations, lock individual items in a collection or lock the entire section, etc.

    Please give us feedback on things you would like to see or change at the IIS Forums: http://forums.iis.net/1149.aspx

    OK, but rather than keep with more and more text, I will just show you a video on how it looks and all its features (for those of you who like text, there is a transcript below).

    Transcript:

    So I have here Windows Vista SP 1 with the IIS Admin Pack installed, in my machine I have very few applications installed but should be good to show some of the features on config editor. When entering Config Editor, first thing you will notice is that at the top you have a drop-down list that shows all the sections currently schematized and ready to be used in your system.

    Since this is sorted alphabetically, the first section that gets selected is AppSettings, for I can very easily switch between ASP.NET configuration sections, such as system.web/authentication, or the IIS configuration sections such as system.webServer/defaultDocument or the system.applicationHost/sites that contains all the sites configuration for IIS.

    As you can see the user interface displays the configuration elements and properties of the section that is selected, providing you an easy way to see every single configuration property available in the system.

    At the top you'll get a label specifying the deepest path where this section is being used relevant to your scope, so in this case its telling us that its been set in ApplicationHost.config. After that, all the elements and properties are shown in a Property Grid, that displaye elements as a collapsible set of properties. One of the interesting things is that we provide validation for the properties for example, when entering string characters in a numeric property type an error message will be displayed giving you the details of the expected types. Additionaly other benefits such as type editors, so that when editing a property of type boolean, you get the True/False drop-down, or when a property that is of type enumeration such as the LogFormat inside the SiteDefaults, you will get a drop-down list with only the list of options that are allowed for that enumeration. Same way, when editing a property of type flags such as the logExtFileFlags that contains the fields to include in the log file, you will get a multi-select drop-down list where you can select and de-select the different options. Also, you will notice that additional information is displayed as you select the different properties, giving you details of their data type as well as additional validations for those that have some, for example, the truncateSize property has specified that only a certain range is considered valid, if I type a value that is not within that range it will show this message giving me details of the problem.

    Making Changes

    Now, lets move to a simpler section so that we can show other features of the Configuration Editor. For example here in default documents, if I want to disable it I just change it to False and click Apply. As you would expect all the changes are applied and to see what changes this actually made in my system I'm going to show a Diff of the configuration that I have backed up and indeed the only change that happened in my configuration system is that it changed from true to false.

    Collection Editor

    As you will notice there is a collection in this section, all the collections are shown in an advanced collection editor that will let you see all the information of the items on it, including the ability to add, remove and clear the collection, as well as lock individual items on it. It additionally shows where each of the individual items is coming from making it easier to understand the distributed configuration.

    Another thing you will notice is that this collection editor shows some visual cues to help you deal with data, for example this little key here tells you that this property is the unique key of the collection item.

    So lets actually add a new one, for that I just need to click Add and fill the values, in this case, lets add Home.aspx as a new default document. After doing that, I can close dialog and click Apply. And lets take a look at what happened to my configuration. As you can see the new item was added. So as you can see its really easy to see and change configuration in collections.

    Script Generation

    Now, one of the interesting things that it also has is those changes that I just did, its great but sometimes I don’t want to apply them immediately but instead automate them so that I can apply them at a later time. For example, lets just change the attribute Enabled back to true, and rather than just applying the change as we did before, I want to generate the script cause probably I'm creating a provisioning script for my site and I want to include this as part of it, so just by clicking Generate Script I get this dialog that gives you the code for Managed Code using Microsoft.Web.Administration in C#, and as you can see its quite easy to read. It also gives you JavaScript code that uses a COM library that our configuration system ships called Microsoft.ApplicationHost, and just as the managed code version it just sets the value. It also gives you command line for it, so you don’t need to build code or scripts, you can just run the command line and to prove that, lets actually just run this command line. First lets show the diff again so that we see that its set to false. Now lets run the command line AppCmd which lives in Inetsrv directory. Now lets show the difference again, and as you can see it actually sets the value as expected. As you can see this will help you write scripts or code to manipulate IIS and ASP.NET settings without requiring additional knowledge.

    Locking

    Another interesting feature is locking, for example if I want to make sure that my default documents are always enabled and no one else can override them, I can go here and select the enabled attribute and click lock attribute which will prevent it from being changed in any other web.config file.

    Search Configuration

    Now, another interesting feature which is probably one of the most powerful features is the ability to search configuration so that you can see a high-level overview of the configuration system and all the web.config files on it. Just click Search Configuration. This shows me this dialog that shows me the root web.config that includes all the section that are being set on it, it also shows me applicationHost.config that includes again all the sections being used on it, as well as a location tag for a particular application that includes also some sections for it. you will notice that I also have a couple of applications that include web.config's in their folders, and sub-folders. where we can see how for example in this web.config it includes some

    one of the neat features is that you can actually click any of this nodes and it will immediately display the content of the section as well as where its coming from. For example if I click the web.config my entire web.config is displayed, if I click a specific section it only displays the content of the section. I can even click the locationPath that I'm interested and only get that particular one.

    Additionally you can easily search who is changing the authorization settings from asp.net and as easy as that you can see all the places in your server where the authorization settings are being set and quickly identify all the settings that are being used in your server. This feature is extremely useful because now, you can easily search for example default Document and make sure nobody is changing it and make sure no one else is violating the locking we just did.

    It also allows you to see the files in a flat view where it gives you all the different paths and files where each of them is coming from. You get the exact functionality, its just a different visual representation of the config.

    Schema-Driven

    Another interesting thing is that if you want to build your own sections and extend our configuration system, you can go to the schema folder and write your own configuration section, declare it using our schema notation, here I'm just defining a section named mySection, that includes an attribute called enabled of type bool and an attribute called message of type string and an attribute password of type string that should be encrypted.. Now, I just need to edit applicationHost.config to define the section so that config system knows we are going to consume it . Just by doing that, now I can go back to config editor and refresh the window, and my section is now available in the drop down, and as you would expect it displays all of the properties I defined, and I can just go ahead and set them, and I get all the locking functionality, I get all the script generation, I get all the UI validation.

    And if I apply, you will see that as expected the changes are done, the password attribute is encrypted, etc.

    So as you can see configuration editor is an extremely powerful feature that will be really useful for successfully managing the web.config's in your system.

  • CarlosAg Blog

    IIS SEO Toolkit - New Reports (Redirects and Link Depth)

    • 3 Comments

    In the new version of the IIS SEO Toolkit we added two new reports that are very interesting, both from an SEO perspective as well as from user experience and site organization. These reports are located in the Links category of the reports

    Redirects

    This report shows a summary of all the redirects that were found while crawling the Web site. The first column (Linking-URL) is the URL that was visited that resulted in redirection to the Linked-URL (second column). The third column (Linking-Status code) specifies what type of redirection happened based on the HTTP status code enumeration. The most common values will be MovedPermanently/Moved which is a 301, or Found/Redirect which is a 302. The last column shows the status code for the final URL so you can easily identify redirects that failed or that redirected to another redirect.

    image

    Why should you care

    This report is interesting because Redirects might affect your Search Engine rankings and make your users have the perception that your site is slower. For more information on Redirects see: Redirects, 301, 302 and IIS SEO Toolkit

     

    Link Depth

    This is probably one of my favorite reports since it is almost impossible to find this type of information in any other 'easy' way.

    The report basically tells you how hard it is for users that land in your home page to get to any of the pages in your site. For example in the image below it shows that it takes 5 clicks for a user to get from the home page of my site to the XGrid.htc component.

    image

    This is very valuable information because you will be able to understand how deep your Web site is, in my case if you were to walk the entire site and layout its structure in a hierarchical diagram it would basically be 5 levels deep. Remember, you want your site to be shallow so that its easily discoverable and crawled by Search Engines.

    Even more interesting you can double click any of the results and see the list of clicks that the user has to make it to get to the page.

    image

    Note that it shows the URL, the Title of the page as well as the Text of the Link you need to click to get to the Next URL (the one with a smaller index). So as you can see in my case the user needs to go to the home page, click the link with text "XGrid", which takes it to the /XGrid/ url (index 3) which then needs to click the link with text "This is a new...", etc.

    Note that as you select the URLs in the list it will highlight in the markup the link that takes you to the next URL.

    The data of this report is powered by a new type of query we called Route Query. The reason this is interesting is because you can customize the report to add different filters, or change the start URL, or more.

    For example, lets say I want to figure out all the pages that the user can get to when they land in my site in a specific page, say http://www.carlosag.net/Tools/XGrid/editsample.htm:

    In the Dashboard view of a Report, select the option 'Query->New Routes Query'. This will open a new Query tab where you can specify the Start URL that you are interested.

    image

    As you can see this report clearly shows that if a user visits my site and lands on this page they will basically be blocked and only be able to see 8 pages of the entire site. This is a clear example on where a link to the Home page would be beneficial.

     

    Other common scenarios that this query infrastructure could be used for is to find ways to direct traffic from your most common pages to your conversion pages, this report will let you figure out how difficult or easy it is to get from any page to your conversion pages

  • CarlosAg Blog

    Using the SEO Toolkit to generate a Sitemap of a remote Web Site

    • 3 Comments

    The SEO Toolkit includes a set of features (like Robots Editor and Sitemap Editor) that only work when you are working with a local copy of your Web Site. The reason behind it is that we have to understand where we need to save the files that we need to generate (like Robots.txt and Sitemap XML files) without having to ask for physical paths as well as to verify that the functionality is added correctly such as only allowing Robots.txt in the root of a site, etc. Unfortunately this means that if you have a remote server that you cannot have a running local copy then you cannot use those features. (Note that you can still use Site Analysis tool since that will crawl your Web Site regardless of platform or framework and will store the report locally just fine.)

    The Good News

    The good news is that you can technically trick the SEO Toolkit into thinking you have a working copy locally and allow you to generate the Sitemap or Robots.txt file without too much hassle (“too much” being the key).

    For this sample, lets assume we want to create a Sitemap from a remote Web site, in this case I will use my own Web site (http://www.carlosag.net/ , but you can specify your own Web site, below are the steps you need to follow to enable those features for any remote Web site (even if it is running in other versions of IIS or any other Web Server).

    Create a Fake Site

    • Open IIS Manager (Start Menu->InetMgr.exe)
    • Expand the Tree until you can see the “Sites” node.
    • Right-click the “Sites” node and select “Add Web Site…”
    • Specify a Name (in my case I’ll use MySite)
    • Click “Select” to choose the DefaultAppPool from the Application Pool list. This will avoid creating an additional AppPool that will never run.
    • Specify a Physical Path where you will want the Robots and Sitemap files to be saved. I recommend creating just a temporary directory that clearly states this is a fake site. So I will choose c:\FakeSite\ for that.
    • Important. Set the Host name so that it matches your Web Site, for example in my case www.carlosag.net.
    • Uncheck the “Start Web site immediately”, since we do not need this to run.
    • Click OK

    This is how my Create site dialog looks like:

    image

    Use the Sitemap Editor

    Since we have a site that SEO Toolkit thinks it is locally now you should be able to use the features as usual.

    • Select the new site created above in the Tree
    • Double-click the Search Engine Optimization icon in the Home page
    • Click the link “Create a new Sitemap”
    • Specify a name, in my case Sitemap.xml
    • Since this is a remote site, you will see that the physical location option shows an empty list, so change the “URL structure” to will use the “<Run new Site Analysis>..” or if you already have one you can choose that.
    • If creating a new one, just specify a name and click OK (I will use MySite). At this point the SEO Toolkit starts crawling the Remote site to discover links and URLs, when it is done it will present you the virtual namespace structure so you can work with.
    • After the crawling is done, you can now check any files you want to include in your Sitemap and leverage the Server response to define the changed date and all the features as if the content was local. and Click OK

    This is the way the dialog looks when discovered my remote Web site URLs:

    image

    You will find your Sitemap.xml generated in the physical directory specified when creating the site (in my case c:\FakeSite\Sitemap.xml").

    Use the Robots Editor

    Just as with the Sitemap Editor, once you prepare a fake site for the remote server, you should be able to use the Robots Editor and leverage the same Site analysis output to build your Robots.txt file.

    image

    Summary

    In this blog I show how you can use the Sitemap and Robots Editor included in the SEO Toolkit when working with remote Web sites that might be running in different platforms or different versions of IIS.

  • CarlosAg Blog

    Get IIS bindings at runtime without being an Administrator

    • 3 Comments

    Today there was a question in StackOverflow asking whether it was possible to read the IIS binding information such as Port and Protocols from the ASP.NET application itself to try to handle redirects from HTTP to HTTPS in a way that was reliable without worrying about using different ports than 80/443.

    Turns out this is possible in the context of the IIS worker process by using Microsoft.Web.Administration.

    The following function will take care of that by reading the Worker Process isolated configuration file and find the HTTP based bindings.

        private static IEnumerable<KeyValuePair<string, string>> GetBindings(HttpContext context) {
           
    // Get the Site name 
            string siteName = System.Web.Hosting.HostingEnvironment.SiteName;

           
    // Get the sites section from the AppPool.config
            Microsoft.Web.Administration.ConfigurationSection sitesSection =
               
    Microsoft.Web.Administration.WebConfigurationManager.GetSection(null, null, "system.applicationHost/sites");
            
           
    foreach (Microsoft.Web.Administration.ConfigurationElement site in sitesSection.GetCollection()) {
               
    // Find the right Site
                if (String.Equals((string)site["name"], siteName, StringComparison.OrdinalIgnoreCase)) {

                   
    // For each binding see if they are http based and return the port and protocol
                    foreach (Microsoft.Web.Administration.ConfigurationElement binding in site.GetCollection("bindings")) {
                       
    string protocol = (string)binding["protocol"];
                       
    string bindingInfo = (string)binding["bindingInformation"];

                       
    if (protocol.StartsWith("http", StringComparison.OrdinalIgnoreCase)) {
                           
    string[] parts = bindingInfo.Split(':');
                           
    if (parts.Length == 3) {
                               
    string port = parts[1];
                               
    yield return new KeyValuePair<string, string>(protocol, port);
                           
    }
                       
    }
                   
    }
               
    }
           
    }
       
    }

     

    If you want to try it, you could use the following page, just save it as test.aspx and add the function above, the result is a simple table that shows the protocol and port to be used:

    <%@ Page Language="C#" %>
    <%@ Import Namespace="System.Collections.Generic" %>
    <script runat="server">
       
    protected void Page_Load(object sender, EventArgs e) {
           
    Response.Write("<table border='1'>");
           
    foreach (KeyValuePair<string, string> binding in GetBindings(this.Context)) {
               
    Response.Write("<tr><td>");
               
    Response.Write(binding.Key);
               
    Response.Write("</td><td>");
               
    Response.Write(binding.Value);
               
    Response.Write("</td></tr>");
           
    }
           
    Response.Write("</table>");
       
    }
    </script>



    Also, you will need to add Microsoft.Web.Administration to your compilation assemblies inside the web.config for it to work:

    <?xml version="1.0"?>
    <configuration>
      
    <system.web>
        
    <compilation debug="true">
          
    <assemblies>
            
    <add assembly="Microsoft.Web.Administration, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
          </
    assemblies>
        
    </compilation>
      
    </system.web>
    </configuration>
  • CarlosAg Blog

    Razor Migration Notes 1: Moving a SitemapPath Control to ASP.NET Web Pages

    • 2 Comments

    After many years I decided that it is time to rewrite my Web site using Razor. A bit of history, I started it around 2003 using ASP.NET 1.1. When .NET 2.0 came around in 2005 I migrated to it and it was great being able to leverage features like MasterPages, Themes, Sitemaps, and many other features. Honestly it is a pretty simple Web site, with mostly content, so very few controls, Sitemap, my own custom Menu control, and a couple more. Last week it was moved to use .NET 4.0 and it feels its about time to go back and update it a bit, both in look and features. So this (if time permits) will be the first of a series of migration notes that I discover as I move it to use ASP.NET Razor (aka WebPages). Do note that this is not meant to be a best practice in anyway, I would never claim I can make such a thing, these will be only my personal notes as I discover more details in ASP.NET WebPages features and as I move my own implementation to use them.

    So with that, one of the first things I faced during this migration, was the use of a Sitemap control (asp:SiteMapPath) in my MasterPage (future post about moving from MasterPages coming). I knew about Sitemap API, so I just decided to write a simple Sitemap helper that I can now use anywhere in Razor. The code is pretty simple, it basically generates an unordered list of links using <ul> and <li> with <a> inside, and used CSS to layout them in a way that I liked.

    SitemapPath Control in WebForms

    The original code I was using in my MasterPage looked like the following:

    <asp:SiteMapPath CssClass="HeaderText" runat="server" ID="siteMap" ShowToolTips="true" NodeStyle-ForeColor="White" CurrentNodeStyle-Font-Bold="true" />

    And generated the following markup:

    <span id="siteMap" class="HeaderText"><a href="#siteMap_SkipLink"><img alt="Skip Navigation Links" height="0" width="0" src="http://blogs.msdn.com/WebResource.axd?d=S2jbW9E-HYlS0UQoRCcsm94KUJelFI6yS-CQIkFvzT6fyMF-zCI4oIF9bSrGjIv4IvVLF9liJbz7Om3voRpNZ8yQbW3z1KfqYr4e-0YYpXE1&amp;t=634219272564138624" style='border-width:0px;' /></a><span><a title='Home' href='/' style='color:White;'>Home</a></span><span> &gt; </span><span><a title='Free tools for download' href='/Tools/' style='color:White;'>Tools</a></span><span> &gt; </span><span style='color:White;font-weight:bold;'>Code Translator</span><a id='siteMap_SkipLink'></a></span>

    Which looks like the following in the browser:

    image

    I used some CSS to set the color, and background and other stuff, but still to set the last item to bold required me to use a property in the Sitemap to get it to look the way I wanted.

    My Sitemap Helper in Razor

    Since I was familiar with the Sitemap API and my goal was to change as “little” as possible as part of this first migration, I decided to write a Sitemap helper that I can use in my Layout pages. The code in the Page is as simple as it gets, you just call @Helpers.Sitemap() and that’s it (added the Div below to get some context in the markup, but that was already there with the SitemapPath control anyway):

    <div class="bannerPath">
    @Helpers.Sitemap()
    </div>

    This new helper version generates the markup below. I don’t know about you, but I can sure make more sense of what it says, and I imagine Search Engines will as well, I decided to use more semantically correct markup using a <nav> to signal navigational section and use a list of links.

    <nav>
        <ul class="siteMap">
            <li><a href="http://blogs.msdn.com/" title="Home">Home</a>&nbsp;&gt;&nbsp;</li>
            <li><a href="http://blogs.msdn.com/Tools/" title="Free tools for download">Tools</a>&nbsp;&gt;&nbsp;</li>
            <li><span>Code Translator</span></li>
        </ul>
    </nav>

    And it looks like the following in the browser (I decided to remove the underlining, and have more padding, and a new font, but all of that is CSS):

    image

    The Sitemap helper code

    The code to do the Sitemap was pretty simple, just use the SiteMap API to get the current node. Since I’m picky and I wanted to generate the markup in the “right” order (note you could use CSS to float them to the right instead), I used a Stack to push the nodes while traversing them up. Finally just generate the <li>.

    @helper Sitemap()
    {
        SiteMapNode currentNode = SiteMap.CurrentNode;
        <nav>
        <ul class="siteMap">
        @if (currentNode != null)
        {
            // Push into a stack to reverse them
            var node = currentNode;
            var nodes = new Stack<SiteMapNode>();
            while (node.ParentNode != null)
            {
                nodes.Push(node.ParentNode);
                node = node.ParentNode;
            }
           
            while(nodes.Count != 0)
            {
                SiteMapNode n = nodes.Pop();
                <li><a href="@n.Url" title="@n.Description">@n.Title</a>&nbsp;&gt;&nbsp;</li>
            }
            <li><span>@currentNode.Title</span></li>
        }
        else
        {
            <li><span>@Page.Title</span></li>
        }
        </ul>
        </nav>
    }

     

    To make it look the way I wanted I used the following CSS:

    .siteMap

      { float:right; font-size:11px; color:White; display:inline; margin-top:3px; margin-bottom:3px; margin-left:0px; margin-right:10px; } .siteMap li,span { float:left; list-style-type:none; padding-left:5px; border-width:0px;} .siteMap span { font-weight:bold; } .siteMap a,a.Visited { color:White; text-decoration:none; }

     

    Conclusion

    SitemapPath control gives you a really easy way to put together a navigation control based on the Sitemap APIs (and the Web.Sitemap file in my case). Creating a simple ASP.NET Razor helper is actually pretty easy since all the functionality needed is there in the base API’s and although it required some code (20 lines of code) now I feel like I have more control over my markup, can style it in anyway I want using CSS and have cleaner markup rendered.

    I’m sure there are better ways to do this, but as I said, the goal of this first pass is to push my site soon with as little changes possible while keeping the same functionality first.

  • CarlosAg Blog

    IIS SEO Toolkit Available in 10 Languages

    • 2 Comments

    A couple of months ago I blogged about the release of the v1.0.1 of the IIS Search Engine Optimization Toolkit. In March we released the localized versions of the SEO Toolkit so now it is available in 10 languages: English, Japanese, French, Russian, Korean, German, Spanish, Chinese Simplified, Italian and Chinese Traditional.

    Here are all the direct links to download it.

    Name Language Download URL
    IIS SEO Toolkit 32bit english http://download.microsoft.com/download/A/C/A/ACA8D740-A59D-4D25-A2D5-1DCFD1D9A01F/IISSEO_x86.msi
    IIS SEO Toolkit 64bit english http://download.microsoft.com/download/A/C/A/ACA8D740-A59D-4D25-A2D5-1DCFD1D9A01F/IISSEO_amd64.msi
    IIS SEO Toolkit 32bit ja-jp http://download.microsoft.com/download/3/6/1/36179752-3497-4C2C-B2C5-9B4FA14EAC3A/IISSEO_x86_ja-JP.msi
    IIS SEO Toolkit 64bit ja-jp http://download.microsoft.com/download/3/6/1/36179752-3497-4C2C-B2C5-9B4FA14EAC3A/IISSEO_amd64_ja-JP.msi
    IIS SEO Toolkit 32bit fr-fr http://download.microsoft.com/download/D/C/5/DC576407-7273-412C-9AC8-AE78E4CFE017/IISSEO_x86_fr-FR.msi
    IIS SEO Toolkit 64bit fr-fr http://download.microsoft.com/download/D/C/5/DC576407-7273-412C-9AC8-AE78E4CFE017/IISSEO_amd64_fr-FR.msi
    IIS SEO Toolkit 32bit ru-ru http://download.microsoft.com/download/8/6/A/86A0BCE1-419F-4550-968E-A8E5A8467B32/IISSEO_x86_ru-RU.msi
    IIS SEO Toolkit 64bit ru-ru http://download.microsoft.com/download/8/6/A/86A0BCE1-419F-4550-968E-A8E5A8467B32/IISSEO_amd64_ru-RU.msi
    IIS SEO Toolkit 32bit ko-kr http://download.microsoft.com/download/F/8/6/F8654213-40C6-4706-9128-536A6A4BC570/IISSEO_x86_ko-KR.msi
    IIS SEO Toolkit 64bit ko-kr http://download.microsoft.com/download/F/8/6/F8654213-40C6-4706-9128-536A6A4BC570/IISSEO_amd64_ko-KR.msi
    IIS SEO Toolkit 32bit de-de http://download.microsoft.com/download/1/8/1/1813318E-6358-4BDC-B148-C1826A74994D/IISSEO_x86_de-DE.msi
    IIS SEO Toolkit 64bit de-de http://download.microsoft.com/download/1/8/1/1813318E-6358-4BDC-B148-C1826A74994D/IISSEO_amd64_de-DE.msi
    IIS SEO Toolkit 32bit es-es http://download.microsoft.com/download/1/6/6/166C82C0-4B72-4282-9A86-47C85CE7E20C/IISSEO_x86_es-ES.msi
    IIS SEO Toolkit 64bit es-es http://download.microsoft.com/download/1/6/6/166C82C0-4B72-4282-9A86-47C85CE7E20C/IISSEO_amd64_es-ES.msi
    IIS SEO Toolkit 32bit zh-cn http://download.microsoft.com/download/D/6/C/D6C6DE59-2EE8-4DD3-9E30-739A5BE42F3C/IISSEO_x86_zh-CN.msi
    IIS SEO Toolkit 64bit zh-cn http://download.microsoft.com/download/D/6/C/D6C6DE59-2EE8-4DD3-9E30-739A5BE42F3C/IISSEO_amd64_zh-CN.msi
    IIS SEO Toolkit 32bit it-it http://download.microsoft.com/download/6/1/F/61FC149C-A950-40F4-9795-F3D4F2115721/IISSEO_x86_it-IT.msi
    IIS SEO Toolkit 64bit it-it http://download.microsoft.com/download/6/1/F/61FC149C-A950-40F4-9795-F3D4F2115721/IISSEO_amd64_it-IT.msi
    IIS SEO Toolkit 32bit zh-tw http://download.microsoft.com/download/6/1/F/61FC149C-A950-40F4-9795-F3D4F2115721/IISSEO_x86_zh-TW.msi
    IIS SEO Toolkit 64bit zh-tw http://download.microsoft.com/download/6/4/0/64067386-3BF6-493E-B7DB-4423839C316B/IISSEO_amd64_zh-TW.msi

    Here is a screenshot of how the SEO Toolkit running in Spanish.

    seo-toolkit-in-spanish

    If you want to read the download files in the Microsoft Download Center you can click the links below:

    IIS Search Engine Optimization Toolkit - 32bit ja-jp
    IIS Search Engine Optimization Toolkit - 32bit fr-fr
    IIS Search Engine Optimization Toolkit - 32bit ru-ru
    IIS Search Engine Optimization Toolkit - 32bit ko-kr
    IIS Search Engine Optimization Toolkit - 32bit de-de
    IIS Search Engine Optimization Toolkit - 32bit es-es
    IIS Search Engine Optimization Toolkit - 32bit zh-cn
    IIS Search Engine Optimization Toolkit - 32bit it-it
    IIS Search Engine Optimization Toolkit - 32bit zh-tw

    To learn more about the SEO Toolkit you can visit:

    http://blogs.msdn.com/carlosag/archive/tags/SEO/default.aspx

    http://www.iis.net/expand/SEOToolkit

    And for any help or provide us feedback you can do that in the IIS.NET SEO Forum.

Page 5 of 10 (94 items) «34567»