Convert.ToString();

SharePoint 2007 ONET.xml AlternateHeader

This is true for SharePoint 2007 B2 TR1:


Even though AlternateHeader does not show up in the schema for ONET.xml, you can still use it in the same way you would in SharePoint 2003. The only difference this time is that MS has bundled the alternate header logic into a control (see below). As far as I can see this control is only present on pages that use the application.master i.e. any pages that live under /_layouts/..., so you will have to add it to your master pages to get a consistant look around your site.


<%@ Register TagPrefix="wssuc" TagName="TopNavBar" src="~/_controltemplates/TopNavBar.ascx" %>


Moss 2007: File Not Found error on Login.aspx page when using anonymous access

This post saved my sanity, hopefully it will save yours. If you have experienced the File Not Found error on the Login.aspx page when using anonymous access this will solve your problem.


http://www.infusionblogs.com/blogs/kguenther/archive/2006/06/27/608.aspx

Using the ASP.NET Web Site Administration Tool with IIS

On this Canadian Thankgiving weekend my thoughts take me through the year gone by, and I wonder...Where did my "The Internet Is Awesome!" t-shirt go?...Why am I still waiting for the final installment of the Seinfeld DVDs to be released?...and Why the hell can I not get the ASP.NET Web Site Administration Tool to work on any IIS web site except for the Default Web Site?


This is a question one hell of a lot of people have been asking, anyone who tries to do this on any site except for the Default Web Site ends up with the following error:



An error was encountered. Please return to the previous page and try again.

The following message may help in diagnosing the problem:


System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. Parameter name: site at System.Web.Configuration.WebConfigurationHost.InitForConfiguration(String& locationSubPath, String& configPath, String& locationConfigPath, IInternalConfigRoot configRoot, Object[] hostInitConfigurationParams) at System.Configuration.Configuration..ctor(String locationSubPath, Type typeConfigHost, Object[] hostInitConfigurationParams) at System.Configuration.Internal.InternalConfigConfigurationFactory.System.Configuration.Internal.
IInternalConfigConfigurationFactory.Create(Type typeConfigHost, Object[] hostInitConfigurationParams) at System.Web.Configuration.WebConfigurationHost.OpenConfiguration(WebLevel webLevel, ConfigurationFileMap fileMap, VirtualPath path, String site, String locationSubPath, String server, String userName, String password, IntPtr tokenHandle) at System.Web.Configuration.WebConfigurationManager.OpenWebConfigurationImpl(WebLevel webLevel, ConfigurationFileMap fileMap, String path, String site, String locationSubPath, String server, String userName, String password, IntPtr userToken) at System.Web.Configuration.WebConfigurationManager.OpenMappedWebConfiguration(WebConfigurationFileMap fileMap, String path) at System.Web.Administration.WebAdminPage.OpenWebConfiguration(String path, String appPhysPath, Boolean getWebConfigForSubDir) at System.Web.Administration.WebAdminPage.OpenWebConfiguration(String path, Boolean getWebConfigForSubDir) at System.Web.Administration.WebAdminPage.VerifyAppValid()


Isn't that pretty!


It would seem that MS only wants this site to work with Cassini, i.e. the web server that comes with Visual Studio 2005. Well it is a great site, and it saves you so much work, so I wanted to include it in a project I am working on, so I set out this morning determined to figure out the problem and get it working, and I did.


The web site itself lives in C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ASP.NETWebAdminFiles\App_Code, and if you look inside the App_Code folder you will find the code behind class for the default.aspx page, it is called WebAdminPage.cs. If you have a look inside this class, at around line 328, you will find a function called OpenWebConfiguration:



        private Configuration OpenWebConfiguration(string path, string appPhysPath, 
bool
getWebConfigForSubDir) {
// check if session expired
if (String.IsNullOrEmpty(ApplicationPath) ||
String.IsNullOrEmpty((string)Session[APP_PHYSICAL_PATH])) {
Server.Transfer("~/home2.aspx");
}

if (String.IsNullOrEmpty(path)) {
return WebConfigurationManager.OpenWebConfiguration(null);
}

string appVPath = (string)Session[APP_PATH];
if (!getWebConfigForSubDir) {
appVPath = path;
}

WebConfigurationFileMap fileMap = new WebConfigurationFileMap();
fileMap.VirtualDirectories.Add(appVPath, new VirtualDirectoryMapping(appPhysPath, true));
return WebConfigurationManager.OpenMappedWebConfiguration(fileMap, path);
}

The problem occurs in the WebConfigurationManager.OpenMappedWebConfiguration(fileMap, path); function. The WebConfigurationManager class lives inside the System.Web dll, inside the System.Web.Configuration namespace. The OpenMappedWebConfiguration function has three alternates, the first one we have already seen, the third one we are not internested in, and the second one will help us solve our problem.


public static System.Configuration.Configuration OpenMappedWebConfiguration
(WebConfigurationFileMap fileMap, string path, string site)
{
return WebConfigurationManager.OpenWebConfigurationImpl(WebLevel.Path, fileMap, path, site, null,
null
, null, null, IntPtr.Zero);
}

You can see the this version of the OpenMappedWebConfiguration function takes an extra parameter called site, and this corrisponds to the name of the IIS website which the call came from. The solution to our problem is this...when this web site is being used by IIS we need to use the second version of the OpenWebConfigurationImpl and pass it the name of the current IIS website, if we are not using IIS then we just use the first version of OpenWebConfigurationImpl.


So why will this website work on the Default Web Site in IIS, without any modifications, I really don't know. I used Reflector and found that the errors were coming from the three functions below, which can be found in the System.Configuration dll, in the System.Configuration namespace, in the Configuration class, the problem is around IsVirtualPathConfigPath returning false, I would guess, but unfortunatly, there is no real way to debug this.

public override void InitForConfiguration(ref string locationSubPath, out string configPath, 
out
string locationConfigPath,
IInternalConfigRoot configRoot,
params
object[] hostInitConfigurationParams)
{
WebLevel level1 = (WebLevel) hostInitConfigurationParams[0];
ConfigurationFileMap map1 = (ConfigurationFileMap) hostInitConfigurationParams[1];
VirtualPath path1 = VirtualPath.CreateAbsoluteAllowNull((string) hostInitConfigurationParams[2]);
string text1 = (string) hostInitConfigurationParams[3];
if (locationSubPath == null)
{
locationSubPath = (string) hostInitConfigurationParams[4];
}
base.Host.Init(configRoot, hostInitConfigurationParams);
this.SetConfigRoot(configRoot);
this.ChooseAndInitConfigMapPath(false, null, map1);
WebConfigurationHost.GetConfigPaths(this._configMapPath, level1, path1, text1,
locationSubPath, out this._appPath,
out
this._appSiteName, out this._appSiteID,
out
configPath, out locationConfigPath);
this._appConfigPath
= WebConfigurationHost.GetConfigPathFromSiteIDAndVPath(this._appSiteID, this._appPath);

if (WebConfigurationHost.IsVirtualPathConfigPath(configPath))
{
string text2;
VirtualPath path2;
WebConfigurationHost.GetSiteIDAndVPathFromConfigPath(configPath, out text2, out path2);
string text3 = this._configMapPath.MapPath(text2, path2);
if (string.IsNullOrEmpty(text3))
{
throw new ArgumentOutOfRangeException("site");
}
}
}

internal static void GetSiteIDAndVPathFromConfigPath(string configPath, out string siteID,
out
VirtualPath vpath)
{
if (!WebConfigurationHost.IsVirtualPathConfigPath(configPath))
{
siteID = null;
vpath = null;
}
else
{
int num3;
int num1 = "MACHINE/WEBROOT".Length + 1;
int num2 = configPath.IndexOf('/', num1);
if (num2 == -1)
{
num3 = configPath.Length - num1;
}
else
{
num3 = num2 - num1;
}
siteID = configPath.Substring(num1, num3);
if (num2 == -1)
{
vpath = VirtualPath.RootVirtualPath;
}
else
{
vpath = VirtualPath.CreateAbsolute(configPath.Substring(num2));
}
}
}



internal static bool IsVirtualPathConfigPath(string configPath)
{
return (configPath.Length > "MACHINE/WEBROOT".Length);
}
So, here is the solution to our problem:

  1. Backup the WebAdminPage.cs i.e. Copy and past the WebAdminPage.cs class and rename it to WebAdminPage.cs_old
  2. Add the following function somewhere into the WebAdminPage class:
            /// 
    /// Checks to see if the request has come in through an IIS web server
    ///(i.e. not Cassini), and

    /// if so, gets the IIS website instance and returns it's name
    ///

    /// The incoming request
    /// The name of the iis website through which the call has come in from.
    ///If this is anything other

    /// than an IIS website and empty string will be returned.
    private string GetSiteName(HttpRequest request)
    {
    ///the server variables key for iis instance id
    const string instanceIdKey = "INSTANCE_ID";

    ///the server variable key for the type of server the call came from
    const string serverSoftwareKey = "SERVER_SOFTWARE";

    ///the iis properties key for the name of the website in IIS
    const string serverCommentKey = "ServerComment";

    ///the name of the IIS server w/o version
    const string iisServerName = "Microsoft-IIS";

    ///the base path name of the website in iis w/o its instance id
    const string iisPathBase = "IIS://localhost/W3SVC/";

    ///get the instance id of the iis website that the call came from
    string instanceId = request.ServerVariables[instanceIdKey];

    ///get the type of web server that the call has come from
    string webServer = request.ServerVariables[serverSoftwareKey];

    ///we only want to perform these operations if this is an IIS website
    if (webServer.ToLower().IndexOf(iisServerName.ToLower()) > -1)
    {
    ///get the iis website
    System.DirectoryServices.DirectoryEntry webSiteDir =
    new
    System.DirectoryServices.DirectoryEntry(iisPathBase + instanceId);

    ///get the property which contains its name
    return (string)webSiteDir.Properties[serverCommentKey].Value;
    }
    else
    return string.Empty;
    }

  3. Alter the
    private Configuration OpenWebConfiguration(string path, 
    string
    appPhysPath,
    bool
    getWebConfigForSubDir)
    function to look like this:
            private Configuration OpenWebConfiguration(string path, string appPhysPath, 
    bool
    getWebConfigForSubDir) {
    // check if session expired
    if (String.IsNullOrEmpty(ApplicationPath) ||
    String.IsNullOrEmpty((string)Session[APP_PHYSICAL_PATH])) {
    Server.Transfer("~/home2.aspx");
    }

    if (String.IsNullOrEmpty(path)) {
    return WebConfigurationManager.OpenWebConfiguration(null);
    }

    string appVPath = (string)Session[APP_PATH];
    if (!getWebConfigForSubDir) {
    appVPath = path;
    }

    WebConfigurationFileMap fileMap = new WebConfigurationFileMap();
    fileMap.VirtualDirectories.Add(appVPath,
    new
    VirtualDirectoryMapping(appPhysPath, true));

    ///get the name of the website, this will only have a value if we are using IIS
    string siteName = GetSiteName(Context.Request);

    ///if it is null or empty we are not using IIS, so we do not
    ///need to supply the site name

    if(string.IsNullOrEmpty(siteName))
    return WebConfigurationManager.OpenMappedWebConfiguration(fileMap, path);
    else
    return WebConfigurationManager.OpenMappedWebConfiguration(fileMap, path, siteName);
    }

  4. Finally add the following code the the web.config file in C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ASP.NETWebAdminFiles inside the System.Web tag
            <compilation>
    <assemblies>
    <add assembly="System.DirectoryServices, Version=2.0.0.0, Culture=neutral,
    PublicKeyToken=B03F5F7F11D50A3A"
    />
    assemblies>
    compilation>

Now you can just create your website in IIS, create a virtual directory and point it to C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ASP.NETWebAdminFiles, here is how do do that:



  1. Create a website in IIS
  2. Make sure it is set to run using ASP.NET 2.0
  3. Create a new virtual directory called ASP.NETWebAdminFiles and point it to C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ASP.NETWebAdminFiles.
  4. Right click on the Virtual Directory and select Properties
  5. Click on the Virtual Directory tab and click the Create button beside Application Name.
  6. Change Execute Permissions to Scripts Only.
  7. Click on the Directory Security tab, click on Edit button for, Authentication and access control.
  8. Unclick Enable anonymous access and make sure Integrated Windows Authentication is the only check box clicked under Authenticated Access
  9. You can now go to the site using the following url as a template http://localhost:8081/asp.netwebadminfiles/default.aspx?applicationPhysicalPath=C:\Documents%20and%20Settings\Administrator\My%20Documents\Visual%20Studio%202005\WebSites\WebSite1\&applicationUrl=/WebSite1
  10. You may have to set read/write permissions on the Web.config of the web site that are trying to control the security for, as the ASP.NET admin site will try to edit it.

I hope this helps out a few people, please let me know if I need to make some corrections on this.


Thanks.




© 2006 Convert.ToString(); | Blogger Templates by GeckoandFly.
No part of the content or the blog may be reproduced without prior written permission.