HowTo: Linux, Nginx, Mono, Asp.Net Mvc

These are notes I made for getting an application written for Asp.Net Mvc (It was probably Mvc 3-ish) to run on a Centos server.

Note that some of the issues/solutions may vary across Linux variants. The interface Nginx-Mono is FastCGI, which they both support. The Mono webserver is xsp4.

Of course, running cross platform is all much easier these days if you use .Net Core and Kestrel 🙂 And een for Net Framework running on Mono, the work done since Microsoft bought Xamarin has been really helpful for e.g. Mvc compatibility.

The Reading List

The Checklist

Ensure nginx has read execute permissions on your application directory and all parent directories

nginx conf section for webapp

With the Asp.Net website listening on port 9001

#
server {
listen 8080;
server_name your-public-facing-nginx-server-name.com;

# use /smoketest/ to confirm that nginx is reading this config 
# and has read/execute access to the 
# /usr/share/nginx directories and files:

location /smoketest/ {
root /usr/share/nginx/smoketestredir;
index index.html;
}

# pass XSP to FastCGI server listening on 127.0.0.1:9001
# use a different port for each ASP.NET site you create
# (port 9000 is often taken by PHP on default webserver setups)

location / {

# replace fastcgi with this to confirm nginx read address
# to files in root /usr/share/nginx/mywebapplication;
fastcgi_pass  127.0.0.1:9001;
fastcgi_index index.html;

include /etc/nginx/fastcgi_params;
fastcgi_param  PATH_INFO          "";
fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;

fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
}
}

Systemd Startup Script

vim /etc/systemd/system/fastcgi-mono-hdmbreas.service

[Unit]
Description=FastCgi-mono-server4 for Application
After=syslog.target

[Service]
Type=simple
ExecStart=/bin/fastcgi-mono-server4 --applications /:/usr/share/nginx/hdmbreas/hdm-fe-web --socket=tcp:127.0.0.1:9001
Restart=always

systemctl daemon-reload
systemctl start fastcgi-mono-app.service
systemctl status fastcgi-mono-app.service
systemctl status fastcgi-mono-app.service

Error: [error] 7216#0: *119 upstream sent too big header while reading response header

  • Considering setting the buffer size
  • Considering setting the busy buffer size
  • e.g. nginx config: fastcgi_buffers 16 16k; fastcgi_buffer_size 32k;

Watching Errors

Watch errors with tail -F /var/log/nginx/error.log

IIS Express : Run a child web application in a virtual directory under a parent application

Like this: Edit your IIS Express config file at

"%userprofile%\My Documents\IISExpress\config\applicationhost.config"

Create a site which has two applications defined in it, e.g.

<site name="MyTopLevelAndChildWebAppsInOneSite" id="123" >
    <application path="/" applicationPool="Clr4IntegratedAppPool">
        <virtualDirectory path="/" physicalPath="C:\Users\me\Source\TopLevelWebApp" />
    </application>
    <application path="/Child" applicationPool="Clr4IntegratedAppPool">
        <virtualDirectory path="/" physicalPath="C:\Users\me\Source\ChildWebApp" />
    </application>
    <bindings>
        <binding protocol="http" bindingInformation="*:51234:localhost" />
    </bindings>
</site>

And then run the site, matching it on the siteid:

start "Woo!" "C:\Program Files (x86)\IIS Express\iisexpress.exe" /siteid:123

Browse to, and close, your web apps in the usual way from the IIS Express icon in the systray.

Optionally, experience the pain that is web.config inheritance. But try not to.

Mono MVC System.UnauthorizedAccessException Access to the path “/Library/Frameworks/Mono.framework/Versions/…/etc/mono/registry” is denied

Is an error you are likely to see if you run a Visual Studio MVC template in Mono. There are two options for fixing it.

  • Do this from the command line:
    sudo mkdir /Library/Frameworks/Mono.framework/Versions/3.2.5/etc/mono/registry
    sudo chmod g+rwx /Library/Frameworks/Mono.framework/Versions/3.2.5/etc/mono/registry

    (replacing 3.2.5 with your mono version, which you get at the command line with mono --version)

  • Or delete the reference to Microsoft.Web.Infrastructure.dll from the project and delete it from the bin directory too.

The important difference is that deleting Microsoft.Web.Infrastructure.dll will stop your project working on .Net, so the registry access is simpler for cross-platformers. Another option for cross-platform project files would be something like this in the .csproj file:

<Target Name="AfterBuild">
    <Delete Files="$(WebProjectOutputDir)\bin\Microsoft.Web.Infrastructure.dll" Condition=" '$(OS)' != 'Windows_NT'" />
  </Target>

I prefer the 'grant access to the registry approach' myself but it does mean having to re-run the 2 line script for every new version of mono.