2

I have a code library I have written which can be utilized in both desktop applications and on a web server. That library sometimes needs to know which environment it's running in.

In the past I have relied on System.Web.Hosting.HostingEnvironment.IsHosted to tell if the code is running on a web server. Unfortunately asp.net core mvc does not have access to the System.Web namespace so I need another mechanism.

How can the code tell if it's running on a web server if one of those possibilities is asp.net core mvc?

teo van kot
  • 12,350
  • 10
  • 38
  • 70
RonC
  • 31,330
  • 19
  • 94
  • 139
  • Honestly have the calling app pass in a value indicating this fact in your constructor... don't make a mountain out of a molehill... if you can... Another option is I'm thinking you can get the current user your app is running under and in asp.net I believe it runs on the aspnetusr account or something like that... – Adam Heeg Apr 14 '16 at 14:04
  • I could add a config setting and then pass that config setting into the library but I'd much rather just have the code sense the environment on it's own. – RonC Apr 14 '16 at 14:24
  • 1
    maybe this answer helps? http://stackoverflow.com/questions/9540437/programmatically-determine-if-code-is-running-under-iis-express – Adam Heeg Apr 14 '16 at 14:27
  • 1
    What decisions do you make based on the answer? I have to wonder if those are even relevant anymore. – Tratcher Apr 14 '16 at 16:13
  • Tratcher - There is a lot of stuff actually. For example if the code is running on a web server it needs to get information about the referring url but if running on a desktop application it shouldn't attempt to get such info. Also, when running on the server it uses server side caching but when running as part of a desktop application it doesn't need to. These are just a few examples. – RonC Apr 14 '16 at 16:32
  • So how did your library gain access to the referring URL, etc.? How many errors do you get if you compile it as a net-core DLL? This might be a catalyst into a more modularly designed library. – Berin Loritsch Apr 14 '16 at 17:47
  • 1
    Not sure if this will work in your scenario but is it possible to just ship two libraries and let the consumers decide if they run it on the server or somewhere else? – Victor Hurdugaci Apr 15 '16 at 01:36
  • Victor - thanks for the suggestion. In some scenarios that could work great. But often I find that the code that needs to run in the two places (web and desktop app) are nearly identical with just a few small differences. In such cases it's nice from a DRY perspective to handle both with the same library and just handle the minor differences via conditional statements. – RonC Apr 15 '16 at 13:10

2 Answers2

2

Answering my own question in case it helps others.

It's been mentioned that one way to determine whether the code is running on a web server or desktop app is to look at the name of the process it's running in. This is definitely possible, but I have little control over what the process name is for a web application and the name is likely to change in the future if history is any indication.

So instead, I chose to make the determination based on the application's config file name. This file name is different for web apps and desktop apps and it's something that's more under my control as a developer.

The method I wrote to do this is:

public bool IsWebServer {
        get {
            string file = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile.ToLower();

            //web.config used by asp.net 4.X, 
            //app.config used by MVC Core
            //NameOfTheApp.exe.config used by desktop applications
            if(file.Contains("web.config") || file.Contains("app.config")) {
                return true;
            }

            return false;
        }
    }
RonC
  • 31,330
  • 19
  • 94
  • 139
  • 1
    This solution no longer works since as of ASP.NET Core 1.0 `AppDomain.CurrentDomain.SetupInformation.ConfigurationFile.ToLower()` returns a exe.config file. So it looks exactly the same as if running as a desktop application. So I resorted to just manually setting a config parameter to indicate if the code is running on a web server. – RonC Oct 31 '16 at 14:23
1

Unfortunately, there is no currently equivalent API. When you look at how that property works, you can easily do something equivalent yourself--without making assumptions about which server is hosting your application.

You'll have to set up your API with a static public property:

namespace My.Project
{
    public static HostingEnvironment
    {
        public static bool IsHosted { get; private set; }

        public static void SetIsHosted(this IServicesCollection services)
        {
            // you can grab any other info from your services collection
            // if you want.  This is an extension method that you call
            // from your Startup.ConfigureServices method

            IsHosted = true;
        }
    }
}

So now you have something that works with both ASP.Net MVC 5 and 4.5. You would integrate it in your Startup.ConfigureServices() method.

public void ConfigureServices(IServiceCollection services)
{
    // Set up whatever services you want here.
    // Make sure you have your My.Project namespace
    // in your using statements so you can use the IsHosted()
    // extension method

    services.SetIsHosted();
}

The only difference between this solution and the legacy System.Web.Hosting.HostingEnvironment.IsHosted solution is that the flag was set by the framework when the application was started by IIS automatically. This is probably as close of an equivalent solution as you are going to get, while still allowing the ability to host anywhere.

Berin Loritsch
  • 11,400
  • 4
  • 30
  • 57
  • Berin - thank you for your well documented answer. Your approach does contain some insights, but at the end of the day it still boils down to hard coding an a variable at startup and checking it later. I'd prefer to have the code determine whether it's running on a web server or not based on something it can observe from the environment which is not specific to my application. – RonC Apr 14 '16 at 15:44
  • 1
    That's essentially how the code worked before, it was just set by the framework for you. The only thing you can observe in the environment is process names, but that's also problematic as you aren't guaranteed a static list of process names to work with. It may be the only option available. – Berin Loritsch Apr 14 '16 at 17:44