0

I am facing an issue having 2 default asp.net mvc routes (applied through custom constraints). What I am trying to do is, load different views based on if the parameters are supplied in the routedictionary or not. Below are my two routes in RouteConfig.cs

        routes.MapRoute(
            name: "DefaultWatch",
            url: "{controller}/{action}/{title}",
            defaults: new { controller = "Watch", action = "Index", title = ""},
            constraints: new { title = new VideoTypeRouteConstraint() }
        );

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

I want to open /watch/Index/{title} if the title string is supplied or just open my default route /Main/Index. Below is the implementation for my route constraint.

In VideoTypeRouteConstraint.cs

public class VideoTypeRouteConstraint : IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        if (values.ContainsKey(parameterName))
        {
            string value = values[parameterName].ToString();
            return !String.IsNullOrEmpty(value) ? true : false;
        }
        return false;
    }
}

What I am trying to do check if RouteValueDictionary contains the title variable and if so, returns true so my /Watch/Index/{title} is executed.

Now it works when I hit the below urls

http://localhost:53923/    //returns /Main/Index correctly
http://localhost:53923/?title=routing-optional-parameters-in-asp-net-mvc-5  //Also returns /Main/Index because the value in RouteValueDictionary is null but I can see the value in httpContext.Request[parameterName]

http://localhost:53923/routing-optional-parameters-in-asp-net-mvc-5  //this DOES NOT WORK - Returns 404

RouteValueDictionary contains the key (title) but its value is always null. This is where the issue is I believe but I'm not being able to identify it.

The whole idea of this was to clean my urls for SEO which were way longer when I used a separate controller.

Abdul
  • 2,002
  • 7
  • 31
  • 65
Ali Baig
  • 3,819
  • 4
  • 34
  • 47
  • You 3rd example has only one segment so it will never match the `DefaultWatch` route which has 3 segments, so it will try and find the `Index()` method in `routing-optional-parameters-in-asp-net-mvc-5Controller` which does not exist. –  Jun 23 '16 at 04:50
  • Yes this is exactly what's happening. Is there a way to make third url work without using other controller? Currently it works but url takes the form example.com/controller/some-long-title, I wanted to remove that controller thing from url. – Ali Baig Jun 23 '16 at 05:03
  • Not unless you give the `DefaultWatch` route a prefix to distinguish it - e.g. it would need to be say `url: "Watch/{title}",` so that it generates `http://localhost:53923/Watch/routing-optional-parameters-in-asp-net-mvc-5` –  Jun 23 '16 at 05:08
  • 1
    The only other alternative would be `url: "{title}",` but then you would need a very complex route constraint to ensure the value you passed did not match another route or controller name - just testing `.IsNullOrEmpty()` would not be enough –  Jun 23 '16 at 05:10
  • Great okay! I guess going forward with {title} can give me what I want given a good route constraint covering all possible cases for the match. Thank you @StephenMuecke – Ali Baig Jun 23 '16 at 05:20

0 Answers0