0

I am looking for some advice on how to achieve the following.

I have an MVC5 .NET web application. In this application I have created a base controller, this controller is the parent for many child controllers. Each child controller has its own set of views, which have their own set of sass and JavaScript file. What I need to do is load the correct controller based on the host URL and not show the controller name within the URL, e.g. www.host1.co.uk would load controller1 and www.host2.co.uk would load controller2, when the site is running the URL needs to look like this www.host1.co.uk/Index NOT www.host1.co.uk/controller1/Index
Another thing I am doing is using Ninject to inject all our business logic services into the controllers, I would like to continue to do this.

Any help would be appreciated

Below is an example of the controller structure for reference

public abstract class BaseController : Controller
    {
        private readonly IService1 _service1;
        private readonly IService2 _service2;

        protected BaseController(IService1 service1, IService2 service2)
        {
            _service1 = service1;
            _service2 = service2;
        }

        // GET: Base
        public virtual ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public virtual ActionResult Index(IndexViewModel model)
        {
            //DoSomething
            return View();

        }
    }


    public class HostController1 : BaseController
    {
        public HostController1(IService1 service1, IService2 service2)
            : base(service1, service2)
        {

        }
    }
Mike Ross
  • 155
  • 1
  • 1
  • 9

1 Answers1

1

You can implement a custom route constraint that verifies the host name

namespace Infrastructure.CustomRouteConstraint
{
    public class HostNameConstraint : IRouteConstraint
    {
        private string requiredHostName;

        public HostNameConstraint(string hostName)
        {
            requiredHostName = hostName;
        }

        public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
        {
            // get the host name from Url.Authority property and compares it with the one obtained from the route
            return httpContext.Request.Url.Authority.Contains(requiredHostName);
        }
    }
}

Then, in the top of your RouteConfig.cs you can create two new routes specifying these host names:

public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute("Host1Route", "{action}",
                new { controller = "One", action = "Index" },
                new { customConstraint = new HostNameConstraint("www.host1.co.uk") });

            routes.MapRoute("Host2Route", "{action}",
                new { controller = "Two", action = "Index" },
                new { customConstraint = new HostNameConstraint("www.host2.co.uk") });

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
        }

Now, every request from host "www.host1.co.uk" will be treated with the action methods of "OneController" and every request from "www.host2.co.uk" will be treated by the action methods of "TwoController" (and without the controller name in the URL, as in "www.host2.co.uk/Test")

Rafael Companhoni
  • 1,780
  • 1
  • 15
  • 31