We are developing several applications in Visual Studio 2010 using C# and .NET 4.0 on Windows. Two SilverLight applications using services from several WCF projects. Another is a console application.
We want to put some "common" functionality in a separated Library project in order to factorize and reuse code. This library needs to know if the application is hosted (IIS, ASP.NET...) like the WCF services or is running as a console application, due to different file path handling.
Googling this question, people indicates the use of System.Web.dll in order to know if the code is hosted, using HttpContext, HostingEnvironment.IsHosted... The problem is that such approach requires to include a reference to System.Web int he Library project, being not acceptable if this Library will be referenced by a Console project with Client Profile.
The idea is to use another technique that do not involve the use of System.Web assembly.
If you only need to get the path to a file in the folder containing the application (as in the comment on question), you can use:
Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "filename")
For an ASP.NET application, this will be the root folder (same as MapPath("~/" + filename)), for a console application it will be the folder containing the executable.
From the comment to the original question:
when running a as console application, just use the filename as a relative path
I wouldn't recommend using a relative path. This will be relative to the current working directory, which may not be the same as the application directory.
There are several ways to check if an application is ASP.NET or not.
Check the name of the configuration file
if ("web.config".Equals(Path.GetFileName(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile), StringComparison.OrdinalIgnoreCase))
{
// ASP.NET application
}
An ASP.NET application does not have an entry assembly
if (Assembly.GetEntryAssembly() == null)
{
// ASP.NET application
}
An ASP.NET application uses shadow copies of all .dll files. However, I'm not sure if this is possible in other types of applications.
if (AppDomain.CurrentDomain.ShadowCopyFiles)
{
// ASP.NET application (probably)
}
Another reflection idea: use System.Web, but through reflection:
AppDomain.CurrentDomain.GetAssemblies()
to see if System.Web is loaded; if not, you're not hostedTurns out that's easier said than done, but this seems to do the trick:
public static bool IsHosted()
{
try
{
var webAssemblies = AppDomain.CurrentDomain.GetAssemblies()
.Where(a => a.FullName.StartsWith("System.Web"));
foreach(var webAssembly in webAssemblies)
{
var hostingEnvironmentType = webAssembly.GetType("System.Web.Hosting.HostingEnvironment");
if (hostingEnvironmentType != null)
{
var isHostedProperty = hostingEnvironmentType.GetProperty("IsHosted",
BindingFlags.GetProperty | BindingFlags.Static | BindingFlags.Public);
if (isHostedProperty != null)
{
object result = isHostedProperty.GetValue(null, null);
if (result is bool)
{
return (bool) result;
}
}
}
}
}
catch (Exception)
{
// Failed to find or execute HostingEnvironment.IsHosted; assume false
}
return false;
}
The reflection is probably expensive so execute once and cache the result. I'm also not sure what the best way to find the specific assembly and type is, but this way works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With