If you reverse the order like so:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "AccRef",
url: "{controller}/{action}/{acc_ref}",
defaults: new { controller = "Company", action = "Index", acc_ref = "" },
constraints: new { acc_ref = @"^\d{1,4}$" }
);
Your current scenario will work with above change but the url "/Home/Index/5" or "/Company/Index/0015" still matches both the routes. This is because the routes are generic (as correctly pointed out by Bigfellahull).
In your case since both the parameter is of type int, both the routes are matched.
Option 1:
You can add a extra string say "Acc" in the route url to make it more specific.
routes.MapRoute(
name: "AccRef",
url: "{controller}/{action}/{acc}/{acc_ref}",
defaults: new { controller = "Company", action = "Index", acc_ref = "" },
constraints: new { acc_ref = @"^\d{1,4}$" }
);
In this case the url will change to ".Company/Index/acc/0015".
Option 2:
If you can change the parameter type in action method like so:
public class HomeController : Controller
{
public ActionResult Index(string id)
{
}
}
The url will match only one route.
Option 1 and 2 are for example only to explain how you can make routes more specific.