How do I use IIS6 style metabase paths in IIS7 AppCmd tool? - iis-7

I'm currently in the process of upgrading old II6 automation scripts that use the IISVdir tool to create/modify/update apps and virtual directories, and replacing them with AppCmd for IIS7.
The IIS6, "IISVDir" commands reference paths in that are from the metabase, eg, /W3SVC/1/ROOT/MyApp - where 1 is ID of "Default Web Site". The command doesn't actually require the display name of the site to make changes to it.
This works well, since on a different language OS, the "Default Web Site" site name could be named, for example, "既定の Web サイト" or anything else for that matter. But this flexibility is lost if AppCmd can only reference "Default Web Site" via its name, and not a language-neutral identifier.
So, how can I script AppCmd to refer to sites, vdirs and apps using language neutral identifiers to reference the "Default App Site"?
Perhaps I need to start creating my own site instead, from the start, and name it something else specific, and stop using "Default Web Site" as the root?
(Disclosure: I only have a IIS7-English machine that I am working on currently, but I have both IIS6-English and IIS6-Japanese machines for testing my old scripts - so perhaps it really is just "Default Web Site" still on IIS7-Japanese?)

The APPCMD tool appears only work with the site name (mostly). I asked a similar question on Server Fault a while back about exactly the same issue:
How do I reference a site by ID using IIS7 APPCMD? (ServerFault.com)
If you want to start working with the site by ID then you need to do this programmatically, for example:
int iisNumber = 1; // The default website
using (ServerManager serverManager = new ServerManager())
{
var site = serverManager.Sites
.Where(s => s.Id == iisNumber)
.SingleOrDefault();
if(site != null)
{
site.Stop();
// Do stuff to site...
site.Start();
}
serverManager.CommitChanges();
}

Related

Server.MapPath() Bizarre Issue

Did anyone observed or dealt with the following issue. I have couple web server (Dev, QA, Staging) all running Windows 2003, IIS 6.
Recently applied an update which uses the following lines of code:
sLogPath = Server.MapPath("../Templates/" & strFileName)
set fs = Server.CreateObject("Scripting.FileSystemObject")
If fs.FileExists(sLogPath) Then
That works fine on all dev systems but as soon as we moved it to QA I am getting an error:
The '..' characters are not allowed in the Path parameter for the MapPath method.
Line number xxx
Line number is to this line
sLogPath = Server.MapPath("../Templates/" & strFileName)
I tried replacing Server.MapPath("../Templates/") with Server.MapPath("/Templates/") but that gave me the root of IIS service (C:\InetPub\wwwroot) not the root of my sites. If I attempt to do Server.MapPath(strFileName) I am getting once again wrong path to the file because sites are not in IIS root but elsewhere on the drive.
Any ideas how this can be fixed?
The issue is you haven't got Enable parent paths enabled in the ASP application configuration.
Without it you are not permitted to use .. directory traversing in ASP functions.
For more information see Enable Parent Paths Is Disabled by Default in IIS 6.0
On a side note:
I tend to avoid the need for Parent Paths simply by configuring websites as separate web site instances in IIS rather than using %SystemDrive%\inetpub\wwwroot which is where the Default Website instance resides.
Doing this means that code like Server.MapPath("/") will be valid and point to the root of your site not the Default Web Site instance root.

ASP.NET Website Administrator Tool in VS 2013

Is there a short cut method to open website administrator in visual studio 2013, other than the method specified below
http://blogs.msdn.com/b/webdev/archive/2013/08/19/asp-net-web-configuration-tool-missing-in-visual-studio-2013.aspx
By Windows Explorer, copy folder ASP.NETWebAdminFiles and all its content to your solution folder (root folder of your WebApplications).
ASP.NETWebAdminFiles exists in %systemroot%\Microsoft.NET\Framework\v4.0.30319\
%systemroot% usually refers to C:\Windows
On VS2013+ \ Solution Explorer Window, do right click on your solution name; go over Add, on expanded menu click on Existing Web Site... item.
On opened dialog, on left pane choose File System, on right pane browse to your solution folder and select ASP.NETWebAdminFiles then click on Open button.
In added web site, in folder App_Code, find and open WebAdminPage.cs then:
4.1. find class WebAdminPage , find method OpenWebConfiguration that has 3 parameters, replace last line of code with this:
return WebConfigurationManager.OpenMappedWebConfiguration(fileMap, path, "localhost");
you can use domain name or IP Address instead of localhost
4.2. find class WebAdminModule, find method SetSessionVariables, find first if block:
if (application.Context.Request != null) { ... }
inside if block, replace two lines of codes with these:
queryStringAppPath = "/";
queryStringApplicationPhysicalPath = #"D:\PHYSICAL\PATH\OF\YOUR\MAIN\WEB\APPLICATION\";
4.3. Make sure provided physical path ends with a BACKSLASH.
4.4. [NEW] if you going to run this tool on localhost, in class WebAdminModule, find method OnEnter then find first if block:
if (!application.Context.Request.IsLocal) {...}
make whole of block as commented text:
//if (!application.Context.Request.IsLocal) {...}
4.5. On VS2013+ \ Solution Explorer Window, click on ASP.NETWebAdminFiles, on Properties Window set Windows Authentication as Enabled then set Anonymous Authentication as Disabled.
4.6. Set ASP.NETWebAdminFiles website as StartUp Project then run it.
It works, I use it for my applications over Intranet and web.
Good luck.
After a long wait, here is the replacement for the ASP.NET Website Administrator Tool:
Thinktecture.IdentityManager as a replacement for the ASP.NET WebSite Administration tool
Since then, ASP.NET has introduced ASP.NET Identity and community member Brock Allen created IdentityReboot with some significant improvements and extensions. Brock Allen and Dominick Baier have gone even further and created Thinktecture IdentityManager. It's the beginnings of a nice bootstrapped replacement for the missing ASP.NET Website Administration Tool. It is nicely factored and supports both ASP.NET Identity and their alternative called MembershipReboot.
Hope this helps.

Need to find Default Web Site's Home Directory in IIS

My InstallShield installer needs to install a file in the IIS Default Web Site's Home Directory, and set it to the default web page.
Unfortunately, in our environments, I can't assume that the home directory is C:\Inetpub\wwwroot, but I need to find out what it is.
Any idea on how I can do this with a script? We need to support XP, 2003 and 2008.
Found it - it's dead simple:
Dim objIIsWebService
Set objIIsWebService = GetObject("IIS://localhost/W3SVC/1/ROOT")
wscript.echo objIIsWebService.Path
I knew there had to be an easy way!
You can use a script to enumerate the IIS Web Sites and query them for information.
Something like
SET objWebService = GetObject( "IIS://" & strServer & "/W3SVC" )
FOR EACH objWebServer IN objWebService
objWebService.SomeProperty
...
But I think this belongs on Server Fault.

How do I get the complete virtual path of an ASP.NET application

How do I know the the complete virtual path that my application is currently hosted? For example:
http://www.mysite.com/myApp
or
http://www.mysite.com/myApp/mySubApp
I know the application path of HttpRequest but it only returns the folder name that my application is currently hosted, but how do I get the initial part?
The domain name part of the path is not really a property of the application itself, but depends on the requesting URL. You might be able to reach a single Web site from many different host names. To get the domain name associated with the current request, along with the virtual path of the current application, you could do:
Request.Url.GetLeftPart(UriPartial.Authority) + Request.ApplicationPath
Technically, an "application" is a virtual directory defined in IIS and Request.ApplicationPath returns exactly that. If you want to get the folder in which the current request is handled, you can do this:
VirtualPathUtility.GetDirectory(Request.Path)
ASP.NET has no idea how to distinguish your sub-application from a bigger application if it's not defined as a virtual directory in IIS. Without registering in IIS, it just sees the whole thing as a single app.
Request.Url
it contains several points that you might consider to use, see the image below:
The below code will solve the purpose, however you have to do a bit tuning for two types of scenarios:
Hosted as separate web application.
Hosted as Virtual application within a web application.
HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority) + HttpRuntime.AppDomainAppVirtualPath;
In .NET 4.5
VirtualPathUtility.ToAppRelative(path)
Try this (Haven't tried it)
public string GetVirtualPath(string physicalPath)
{
string rootpath = Server.MapPath("~/");
physicalPath = physicalPath.Replace(rootpath, "");
physicalPath = physicalPath.Replace("\\", "/");
return "~/" + physicalPath;
}
Link 1
Link 2
Url.Content("~") worked great for me and is nice and simple. I used it in the view like this:
<a href="#(Url.Content("~" + attachment))">
Here my attachment is a path like "/Content/Documents/Blah.PDF".
When my app is published to a IIS site that uses a virtual directory, Url.Content("~") resolves to just the virtual directory name like, "/app-test", for example.

Read a web.config file in a virtual directory

I have an ASP.NET application (Root Application) that has a virtual directory set up to another ASP.NET application (Virtual Application). How can I make the Virtual Application read values from the Root Application's web.config file? I was looking at the WebConfigurationManager.OpenWebConfiguration() class, but I'm unsure how how to tell it to go up one level from the root. For example, I would tell it to go to ~/web.config to get the the Virtual Application's web.config file, but I need it to go up one more level to the Root Application's file structure. Is this even the correct approach?
Any help would be greatly appreciated!!
You can use the ExeConfigurationFileMap class with ConfigurationManager, like:
string configFile = new FileInfo(Server.MapPath("/Web.config")).Directory.Parent.FullName + "\\Web.config";
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = configFile;
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
Response.Write(config.AppSettings.Settings["Test"].Value);
IIS does have programmatic access to its configuration data (which is documented on MSDN and/or Technet). This will be the only supported route (i.e. will continue to work across IIS versions).
Otherwise you can hack a solution (both of these will require higher than usual rights for the process):
Parse the output from appcmd.exe:
E.g. here:
> C:\Windows\system32\inetsrv\appcmd.exe list vdir
VDIR "Default Web Site/" (physicalPath:E:\Dev\weblocal\XYZ)
VDIR "Default Web Site/DevRoot/TestWebClient" (physicalPath:E:\Dev\Tests\ClientSideWeb)
VDIR "Default Web Site/Home" (physicalPath:E:\Data\Homepages)
Read the configuration directly from C:\Windows\System32\inetsrv\config.
I think you will find that your desired behavior is in fact the default behavior.
web.config settings cascade down. Your app will look up to the next hierarchical web.config if it can't find the value.
This would allow you to just look up via AppSettings etc. for most cases.
I'm not sure what happens if you really need to direct access to the file as opposed to the various config api access methods.
I have a setup like this right now using IIS7 with multiple virtual apps configured.
I tried HectorMac's suggestion again and it still doesn't work for me. As a result I am going to seek an alternative to storing my value in the web.config file.

Resources