Skip to content
This repository has been archived by the owner on Dec 19, 2018. It is now read-only.

IIS Hosting Issues #629

Closed
Mady007 opened this issue Mar 8, 2016 · 27 comments
Closed

IIS Hosting Issues #629

Mady007 opened this issue Mar 8, 2016 · 27 comments
Milestone

Comments

@Mady007
Copy link

Mady007 commented Mar 8, 2016

I'm trying to host application on IIS, windows server 2008 R2, under default website. I tried to access the site through browser and it loads forever with below error in logs file.

Error: Unable to load application or execute command 'Microsoft.AspNet.Server.WebListener'. Available commands: web, ef. System.IO.FileNotFoundException: The system cannot find the file specified. (Exception from HRESULT: 0x80070002) at System.Reflection.RuntimeAssembly.nLoadFile(String path, Evidence evidence) at System.Reflection.Assembly.LoadFile(String path) at Microsoft.Dnx.Runtime.Loader.LoadContext.LoadFile(String assemblyPath) at Microsoft.Dnx.Runtime.Loader.PackageAssemblyLoader.Load(AssemblyName assemblyName, IAssemblyLoadContext loadContext) at Microsoft.Dnx.Host.LoaderContainer.Load(AssemblyName assemblyName) at Microsoft.Dnx.Runtime.Loader.AssemblyLoaderCache.GetOrAdd(AssemblyName name, Func2 factory)
at Microsoft.Dnx.Runtime.Loader.LoadContext.ResolveAssembly(Object sender, ResolveEventArgs args)
at System.AppDomain.OnAssemblyResolveEvent(RuntimeAssembly assembly, String assemblyFullName)`

_However when I run web.cmd in command line the application starts listening. As long as it is live I can access the url from browser the pages are served. _
image

I have used MSDeploy to publish the code to file system and I uploaded those files to server under the directory MySite , which is physical path of the application.
MySite
image

App pool Settings:
image

Control Panel HttpPlatformHandler
image

I have gone through the integration issues thread IIS Integration Issues. And added environment variable to web.config and added Configure1 method in startup.cs as suggested by Poul Kjeldager Sørensen
s093294

web.config
<configuration> <system.webServer> <handlers> <add name="httpplatformhandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" /> </handlers> <httpPlatform processPath="..\approot\web.cmd" arguments="web" stdoutLogEnabled="true" stdoutLogFile="..\logs\stdout.log" startupTimeLimit="3600"> <environmentVariables> <environmentVariable name="VIRTUAL_PATH" value="/MySite" /> </environmentVariables> </httpPlatform> </system.webServer> </configuration>

Startup.cs
`

     public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory       loggerFactory)
     {
           if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("VIRTUAL_PATH")))
                app.Map(Environment.GetEnvironmentVariable("VIRTUAL_PATH"), (myAppPath) =>  this.Configure2(myAppPath, env, loggerFactory));
          else
            Configure2(app, env, loggerFactory);
     }

    private void Configure2(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory    loggerFactory)
    {
         //Other settings which I skipped

         app.UseIISPlatformHandler(options => options.AuthenticationDescriptions.Clear());

        app.UseApplicationInsightsExceptionTelemetry();

        app.UseStaticFiles();

        app.UseIdentity();

        // To configure external authentication please see http://go.microsoft.com/fwlink/?LinkID=532715

        app.UseMvc(routes =>
        {
            routes.MapRoute("Admin", "Admin/{*anything}", new { controller = "Home", action = "Admin" });

            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
     }`

Project.json

`

        {
             "userSecretsId": "aspnet5-MySite-XXXXXXXXXXXXXXXXXXXX",
             "version": "1.0.0-*",
             "compilationOptions": {
             "emitEntryPoint": true
         },

      "dependencies": {
           "EntityFramework.Commands": "7.0.0-rc1-final",
           "EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final",
           "Microsoft.ApplicationInsights.AspNet": "1.0.0-rc1",
           "Microsoft.AspNet.Authentication.Cookies": "1.0.0-rc1-final",
           "Microsoft.AspNet.Diagnostics.Entity": "7.0.0-rc1-final",
           "Microsoft.AspNet.Identity.EntityFramework": "3.0.0-rc1-final",
           "Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final",
           "Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
           "Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-rc1-final",
           "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
           "Microsoft.AspNet.Server.WebListener": "1.0.0-rc1-final",
           "Microsoft.AspNet.StaticFiles": "1.0.0-rc1-final",
           "Microsoft.AspNet.Tooling.Razor": "1.0.0-rc1-final",
           "Microsoft.Extensions.CodeGenerators.Mvc": "1.0.0-rc1-final",
           "Microsoft.Extensions.Configuration.FileProviderExtensions": "1.0.0-rc1-final",
           "Microsoft.Extensions.Configuration.Json": "1.0.0-rc1-final",
           "Microsoft.Extensions.Configuration.UserSecrets": "1.0.0-rc1-final",
           "Microsoft.Extensions.Logging": "1.0.0-rc1-final",
           "Microsoft.Extensions.Logging.Console": "1.0.0-rc1-final",
           "Microsoft.Extensions.Logging.Debug": "1.0.0-rc1-final",
           "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0-rc1-final",
           "AngularJs": "1.5.0",
           "AutoMapper": "4.2.0"
          },

         "commands": {
         "web": "Microsoft.AspNet.Server.WebListener --server.urls https://MyMainSite.com/MySite",
          "ef": "EntityFramework.Commands"
       },

     "frameworks": {
         "dnx451": {
             "dependencies": {
                "MYSite.Core": "1.0.0",
                "MYSite.Data": "1.0.0",
                "MYSite.Infrastructure": "1.0.0",
                 "MYSite.Services": "1.0.0"
            }
        }
    },

        "exclude": [
          "wwwroot",
       "node_modules"
        ],
        "publishExclude": [
              "**.user",
           "**.vspscc"
         ],
        "scripts": {
          "prepublish": [ "npm install", "bower install", "gulp clean", "gulp min" ]
         }
     }

`
I have followed the diagnosing dependency issue from davidfowl

Apart from above issue I have following questions.

  1. Why the packages have to be on the server instead of bin folder with assemblies?
  2. For new project which have to go to prod in next few months would asp.net 5 is reliable? what are the things to watch for?

I really appreciate your help.

@Tratcher
Copy link
Member

Tratcher commented Mar 8, 2016

WebListener cannot be used with IIS/Express, you must use Kestrel: aspnet/IISIntegration#8

@Mady007
Copy link
Author

Mady007 commented Mar 8, 2016

I did tried using Kestrel. I have got the following errors.

In Log file:

Error: Unable to load application or execute command 'Microsoft.AspNet.Server.Kestrel'. Available commands: web, ef. System.IO.FileNotFoundException: The system cannot find the file specified. (Exception from HRESULT: 0x80070002) at System.Reflection.RuntimeAssembly.nLoadFile(String path, Evidence evidence) at System.Reflection.Assembly.LoadFile(String path) at Microsoft.Dnx.Runtime.Loader.LoadContext.LoadFile(String assemblyPath) at Microsoft.Dnx.Runtime.Loader.PackageAssemblyLoader.Load(AssemblyName assemblyName, IAssemblyLoadContext loadContext) at Microsoft.Dnx.Host.LoaderContainer.Load(AssemblyName assemblyName) at Microsoft.Dnx.Runtime.Loader.AssemblyLoaderCache.GetOrAdd(AssemblyName name, Func2 factory) at Microsoft.Dnx.Runtime.Loader.LoadContext.ResolveAssembly(Object sender, ResolveEventArgs args) at System.AppDomain.OnAssemblyResolveEvent(RuntimeAssembly assembly, String assemblyFullName)

When I run web.cmd in command line.

Microsoft.AspNet.Server.Kestrel.Networking.UvException: Error -4092 EACCES permission denied at Microsoft.AspNet.Server.Kestrel.Networking.Libuv.Check(Int32 statusCode) at Microsoft.AspNet.Server.Kestrel.Networking.Libuv.tcp_bind(UvTcpHandle handle, sockaddr& addr, Int32 flags) at Microsoft.AspNet.Server.Kestrel.Networking.UvTcpHandle.Bind(String host, Int32 port) at Microsoft.AspNet.Server.Kestrel.Http.TcpListener.CreateListenSocket(String host, Int32 port) at Microsoft.AspNet.Server.Kestrel.Http.Listener.<>c__DisplayClass5_0.b__0(Object _)

@Tratcher
Copy link
Member

Tratcher commented Mar 8, 2016

@halter73?

@Mady007
Copy link
Author

Mady007 commented Mar 8, 2016

You want me talk to @halter73?

@davidfowl
Copy link
Member

No, he's making @halter73 aware of the issue

@Mady007
Copy link
Author

Mady007 commented Mar 8, 2016

Thanks for the quick response.

There seems to be some issue with Https schema. I tried to set manually as suggested here Manually setting Https Schema

Also,
I came across article here which talks about accessing certificates thru middle ware as follows. To make the site accessible from client machine do I have to do the same as suggested for handling certificates?

`

             private static RequestDelegate ChangeContextToHttps(RequestDelegate next)
             {
                         return async context =>
                        {
                            context.Request.Scheme = "https";
                            await next(context);
                        };
            }

            public void Configure(IApplicationBuilder app, 
                                IHostingEnvironment env,
                                IApplicationEnvironment appEnv,
                                ILoggerFactory loggerFactory)

                 var certFile = applicationEnvironment.ApplicationBasePath + "\\democertificate.pfx";
                var signingCertificate = new X509Certificate2(certFile, "democertificate.io");

                app.Use(ChangeContextToHttps);
                app.UseKestrelHttps(signingCertificate);

    }

`

@Tratcher
Copy link
Member

Tratcher commented Mar 8, 2016

You only need to configure the server certificate with Kestrel if you're accessing kestrel directly rather than via IIS. When you proxy through IIS it only uses SSL/TLS/HTTPS between the client and IIS, it uses HTTP between IIS and Kestrel.

@halter73
Copy link
Member

halter73 commented Mar 9, 2016

@Mady007 Are you still having the permission issue when running web.cmd? If so, can you provide the full output of the command including the address you are attempting to listen on?

@Mady007
Copy link
Author

Mady007 commented Mar 9, 2016

Yes, I do have the permission issue but however I could get it go away when I provided the port number as part of server urls argument in project.json. But that is not what I desire.

"web": "Microsoft.AspNet.Server.WebListener --server.urls https://MyMainSite.com:1234/dir1/dir2/MySite"

When I'm attempt to listen on something similar to https://MyMainSite.com/dir1/dir2/MySite, without port number by running web.cmd following is output of the command. which has the same permission exception.

Note: I'm trying to host my application on IIS under default web site. where dir1/dir 2/ Mysite is virtual path.

image

Please let me know if you need further information. Thanks for your response.

@halter73
Copy link
Member

halter73 commented Mar 9, 2016

So the error indicates you're running into a permissions issue trying to bind to port 443 but not 1234. Typically, if it's simply that another process is already listening on the same port, you would get an error like:

UvException: Error -4091 EADDRINUSE address already in use

@Tratcher do you know why there might be a problem with permissions? On my Windows machine I'm able to bind to 443 even without an elevated prompt.

@Tratcher
Copy link
Member

Tratcher commented Mar 9, 2016

I'd bet IIS is already running on 80 and 443.

@Mady007
Copy link
Author

Mady007 commented Mar 9, 2016

@Tratcher is correct. IIS is already running on 80 and 443. There are multiple asp.net 4 applications which are deployed under the default website and they are up and running.

Does IIS have to be configured as reverse proxy?

@Tratcher
Copy link
Member

Tratcher commented Mar 9, 2016

Kestrel cannot share ports with IIS, you have to give IIS the port and have it reverse proxy the request to Kestrel on a random port.

@Mady007
Copy link
Author

Mady007 commented Mar 9, 2016

Ok. It would be great help if you can point to some documentation ?

@guardrex
Copy link
Contributor

@Mady007 There is the official doc at https://docs.asp.net/en/latest/publishing/iis.html and my notes for IIS that apply to rc1-final at #364 (comment).

@Mady007
Copy link
Author

Mady007 commented Mar 10, 2016

@guardrex Thank you! I have gone through those both links earlier. I have requested the documentation of reverse proxy the request from IIS to Kestrel. Anyways, I'm on it. There is no luck so far but will update once I'm done.

@Tratcher : You mentioned "..reverse proxy the request to Kestrel on a random port".So the application has to listen on the random port. How to make application listen on the random port? Hosting in IIS is enough ? or have to run web.cmd in some kind of windows service?
The reason I'm asking this question is I have set up application to listen on http://localhost:9898 via server.url in project.json And application is in IIS but when I access the url http://localhost:9898 in browser it does not work. I have to run web.cmd then the url works in the browser.

I appreciate your response.

@Tratcher
Copy link
Member

In RC1 Hosting automatically listens on the port specified by IIS via environment variable. See https://github.com/aspnet/Hosting/blob/1.0.0-rc1/src/Microsoft.AspNet.Hosting/Internal/HostingEngine.cs#L262-L276

This will move in RC2.

@Mady007
Copy link
Author

Mady007 commented Mar 14, 2016

I have reverse proxy the request in IIS by adding rewrite rules to my application web.config. Just to add my application is 2 level deep from Default web site.

'

 Default Web Site
    Dir1
       Dir1.1
            MySite 

'
Here is how web.config looks like
`

     <configuration>
       <system.webServer>
         <handlers>
                   <add name="httpplatformhandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" />
         </handlers>
         <httpPlatform processPath="..\approot\web.cmd" arguments="web" stdoutLogEnabled="true"  stdoutLogFile="..\logs\stdout.log" startupTimeLimit="3600">
        <environmentVariables>
                     <environmentVariable name="VIRTUAL_PATH" value="/DIR1/DIR1.1/MySite" />
       </environmentVariables>
   </httpPlatform>
    <rewrite>
      <rules>
     <rule name="MySiteInboundRule" stopProcessing="true">
               <match url=".*" />
               <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
              <action type="Rewrite" url="http://localhost:9898/{R:0}" />
       </rule>
     </rules>
   </rewrite>
   </system.webServer>
  </configuration>`

I have tested above rewrite by running web.cmd and I can see the request coming to http://localhost:9898. Here is command section of project.json
`

    "commands": {
        "web": "Microsoft.AspNet.Server.WebListener --server.urls http://localhost:9898",
         "ef": "EntityFramework.Commands"
      },'

Now I wanted to make it work without running web.cmd. When I tried to access the url I have this error
image

Does the rewrite rule requires any changes? I feel I'm close but something is missing.

I appreciate your response.

@Tratcher
Copy link
Member

web.config does not apply to selfhost, and there is no url-rewrite there. I recommend removing the url-rewrite. HttpPlatformHandler takes care of it's own redirection to a dynamic port.

You also can't use WebListener with IIS/Express, you need to use Kestrel.

@Mady007
Copy link
Author

Mady007 commented Mar 14, 2016

Sorry, I'm not using WebListener its a typo. I'm using Kestrel and want to host application in IIS. I'm trying to achieve your suggestion in earlier response "Kestrel cannot share ports with IIS, you have to give IIS the port and have it reverse proxy the request to Kestrel on a random port."

How do I give IIS the port when it already have one(443)?
How do I reverse proxy the request to Kestrel, if not by rewrite?

In startup.cs class I have configured to use IISPlatformHandler

app.UseIISPlatformHandler(options => { options.AuthenticationDescriptions.Clear(); });

@Tratcher
Copy link
Member

You configure IIS as normal to use whatever public ports you like, usually 80 and 443. HttpPlatformHandler implements the reverse proxy functionality, you don't need additional url-rewrite. HttpPlatformHandler will run web.cmd and specify the port to use via environment variable. Do not configure any addresses for kestrel, Hosting will take care of it (in RC1).

@Mady007
Copy link
Author

Mady007 commented Mar 14, 2016

I did everything but no luck so far. Please guide me.

Since my app is two levels deep from Default website do I have to add environment variable as below?
`

    <environmentVariables>
             <environmentVariable name="HTTP_PLATFORM_APPL_PATH" value="dir1/dir1.1/mysite" />
    </environmentVariables>`

Also, where does web.config of my application reside? at parent level?

@muratg muratg added this to the Discussion milestone Mar 14, 2016
@Tratcher
Copy link
Member

@Mady007 That workaround only applies to RC2 packages. For RC1 use this one instead: aspnet/IISIntegration#14 (comment)

@Mady007
Copy link
Author

Mady007 commented Mar 23, 2016

I redid all the steps from my initial comment except using Kestrel instead of WebListner and everything is working like charm. The main issue i faced was with copying the build over to server via ftp. Some of the dlls and nuspec files from packages directory were not copied over. I used a different client which copied everything then it worked fine.

I never had this issue with vs2013 MsDeploy which has ftp option. And for 2015, i know this option is missing, but I tried to setup as suggested here Publishing Directly with FTP in VS. I'm getting an exception
AspnetPublishHandler with name “FTP” was not found

Thank you @Tratcher and all the participants.

@Mady007
Copy link
Author

Mady007 commented Mar 25, 2016

Before I close I have one issue with copying files to server. If a user is using the application then I cannot copy the files to the virtual path on server. It says Files are being used by another program.

@Tratcher
Copy link
Member

@Mady007 coming soon... aspnet/IISIntegration#81

@muratg
Copy link

muratg commented May 12, 2017

We are closing this issue because no further action is planned for this issue. If you still have any issues or questions, please log a new issue with any additional details that you have.

@muratg muratg closed this as completed May 12, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants