2

I'd like to setup a custom route constraint that would allow me to decorate a controller with an attribute so that I don't have to pass in string to the route and remember to update it with new controller names.

I thought I could setup use the IRouteConstraint but I can't seem to get the attribute. Perhaps I'm just missing something obvious here.

routes.MapRoute("test", 
    "foo/{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional },
    new { controller = new TestConstraint()}
);

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



public class TestConstraint : IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, 
        RouteValueDictionary values,
        RouteDirection routeDirection)
    {
        return false;
    }
}

[AttributeUsage(AttributeTargets.Class)]
public class CustomConstraintControllerAttribute : Attribute
{

}

[CustomConstraintController]
public class TestController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}

Edit:

Current Method:

routes.MapSubdomainRoute("Store",
    "{store}/{controller}/{action}/{id}",
    new {controller = "Home", action = "Index", id = UrlParameter.Optional},
    new {controller = "StoreHome|Contacts|..." }
    );

This route configuration ensures that a url must match subdomain.test.com/GiggleInc/Contacts or subdomain.test.com/GiggleInc/StoreHome.

subdomain.test.com/GiggleInc/StoreHome
MapSubdomainRoute /{store}  /{controller}/{action}/{id}

This method requires that each controller that should be used this way must be added to the controller constraint.

As I mentioned in the comments, I want to replace the hard coded strings for an attribute or something similar.

9
  • Routing is completely finished before the controller is selected. Exactly what is it you hope to achieve with your constraint? Commented Jan 22, 2016 at 18:44
  • Do note that you can completely setup routing (including constraints) in MVC 5 using Attribute Routes, which simply put your route config along with your controller. Commented Jan 22, 2016 at 18:45
  • that's what I was afraid. From my research that's what I figured the answer was. We're using subdomains in our project and certain controllers require a subdomain to be present. Currently, we stuff the constraint with the controller class names as a string. I was hoping to decorate the class instead Commented Jan 22, 2016 at 18:47
  • although if I put a break point on the return false it is hit at the start of the request. I thought I might be able to use something like ControllerDescriptor like in an AuthorizeAttribute Commented Jan 22, 2016 at 18:49
  • Please update your question with details about what you are trying to achieve. It is unclear what case you have here that AuthorizeAttribute doesn't cover already. What exactly do you expect the application to do if a user tries to access a controller that they are "not allowed" to? Commented Jan 22, 2016 at 18:55

2 Answers 2

1

First, thank you for this sweet line of code I didn't know was possible:

constraints: new { controller = "StoreHome|Contacts" }

I didn't know I could filter my MapRoute to a list of Controllers so easily.
Second, you don't need to implement a custom IRouteConstraint for this.
MVC offers the Attribute-Routing you are looking for.

You may even include Default/Optional Values, just like in your MapRoute.
Decorate your Controller Class like so:

[RoutePrefix("{store}/Test")]
[Route("{action=Index}/{id?}")]//Without this, you need to define "[Route]" above every Action-Method.
public class TestController : Controller
{
    public ActionResult Index(string store)//Adding "string store" is optional.
    {
        return View();
    }
}

That's it.
Remember to add the "store" Parameter in all your Actions under each Controller (but it is not Required).

Note:
If you use Attributes instead of MapRoute, then you will not be able to hit the Controller without the "store" Prefix.
With the Custom and Default MapRoutes, you could have accessed your controller either way.
By decorating your Controller with these Attributes, you now force it to only use this exact path.
This may be what you want, but if you start IIS Express from Visual Studio on one of your Views, it will not find it, because Visual Studio doesn't know to add the RoutePrefix for you.

See this link for more information about Attribute-Routing:
https://blogs.msdn.microsoft.com/webdev/2013/10/17/attribute-routing-in-asp-net-mvc-5/

Sign up to request clarification or add additional context in comments.

3 Comments

where did you use constraints: new { controller = "StoreHome|Contacts" }
@Seabizkit I used it in the routes.MapRoute() function. Please see my other answer for a better example: stackoverflow.com/a/52033013/555798
thank you, hard to find information around how you could/should structure your project/projects when your using more advance context relative routing and have areas already, i have gotten it to work, but would be nice to find info examples on how to structure. trying to ask got me no where softwareengineering.stackexchange.com/questions/398700/…
0

Try this...

public class TestRouteAttribute : RouteFactoryAttribute
{      
    public TestRouteAttribute(string template) : base(template) { }

    public override RouteValueDictionary Constraints
    {
        get
        {
            var constraints = new RouteValueDictionary();
            constraints.Add("TestConstraint", new TestConstraint());
            return constraints;
        }
    }
}

Then you should be able to decorate your action methods using [TestRoute]

By the way, would love to know how to accomplish this in asp.net core if anyone knows.

1 Comment

Should I use [TestRoute("{template}")] instead of [Route("{template}")] or in addition to?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.