Dryadwoods
Dryadwoods

Reputation: 2929

Proxy - ASP.NET with or without MVC

I'm working on one multi-tenancy application, where each tenant will have access to 1 or more "sub applications" (different ASP.NET MVC websites).

Later in time, I'll have new versions for each sub application and I will end with:

Some tenants will want to have access to the latest versions, and some will still be using old ones. This is what I've done.

Now I would like to keep "the subdomain versions" hidden for them. They will only access the domain: app1.domain.com This "internal smart proxy" will have the core to know which version this tenant has access.

Anyone knows how I can do this? In a way that all my internal urls (links, images, JS, css, etc...), AJAX,etc, will work correcly? Or point me to some tutorials/blog/forums where i can find that can help me?

Thank you very much.

Upvotes: 2

Views: 2178

Answers (2)

David James
David James

Reputation: 525

Application Request Routing (ARR) could be a workable solution if you are using IIS 7 or 7.5.

You would have an additional web site defined in IIS acting as the proxy, which would be separate to the web site(s) your application uses.

The rules about which tenant is on which version would have to be written to a web.config for ARR to read. Is this acceptable? If you have a small number of tenants changing infrequently, you may be happy to edit this file by hand. If you need more automation, you could programatically generate this web.config file. Because this web.config is only for your ARR proxy site, editing it will not cause your application sites to restart.

A sample configuration might use the following IIS Sites:

  • proxy - binding for your public IP address. *.domain.com resolves to this address
  • v1app - binding for 127.0.0.101
  • v2app - binding for 127.0.0.102

IIS server-level settings: ARR cache -> Server Proxy Settings -> enable proxy. (Set the timeout here if your app needs long timeouts.)

And in your "proxy" site's web.config, the following rewrite rules:

    <rewrite>
        <rules>
            <rule name="V1 tenants" stopProcessing="true">
                <match url="(.*)" />
                <action type="Rewrite" url="http://127.0.0.101/{R:1}" />
                <conditions logicalGrouping="MatchAny">
                    <add input="{HTTP_HOST}" pattern="app1.domain.com" />
                    <add input="{HTTP_HOST}" pattern="app3.domain.com" />
                </conditions>
            </rule>
            <rule name="V2 tenants" stopProcessing="true">
                <match url="(.*)" />
                <action type="Rewrite" url="http://127.0.0.102/{R:1}" />
                <conditions logicalGrouping="MatchAny">
                    <add input="{HTTP_HOST}" pattern="app2.domain.com" />
                </conditions>
            </rule>
        </rules>
    </rewrite>

When a request comes in, it will hit your proxy site, then those rules will look at the hostname and redirect to the appropriate internal site.

If your ARR site is running on the same server as your content sites, you may want to remove the line

<add name="ApplicationRequestRouting" />

from C:\windows\system32\inetsrv\config\applicationHost.config, and add it as a module in your proxy site's web.config. This will apply ARR only to your proxy site, instead of the whole server.

Upvotes: 2

Adrian Grigore
Adrian Grigore

Reputation: 33318

What you are trying to build is in essence an HTTP proxy. The difference to most other proxies is just that the actual URL is built on the server side.

There many different ways to do this. I'd choose one of the following:

  • Create an HTTP handler, in which case you could use this code project article as a starting point.
  • Use ASP.NET MVC. Create a "catch all" route and pipe that through one single action method.

Either way, you will have to

  • Analyze the HttpContext.Current.Request object and build a suitable outgoing URL
  • Use a HttpWebRequest to fetch the data from the actual website. Remember to mimic the original request header plus request content (usually POST parameters) if applicable.
  • Output the Response Header from the server and then output the data you just fetched.

Upvotes: 2

Related Questions