0

I am new to ASP.Net MVC. May be this question looks simple, but i couldn't fix it. Here the scenario. I have an application listing data based on city. So the url will be looking like this

        www.xxxxxx.in/chennai
        www.xxxxxx.in/mumbai
        www.xxxxxx.in/delhi

In normal routing the first part (chennai/mumbai) is controller in the above url, But here i dont want this to be a controller. instead i want to map the single controller (LocationController) to these URl's. Because later time i can add any number of city.

I am struck here, can someone help me out.

4 Answers 4

2

Try this:

  routes.MapRoute(
            "CityRoute",                                              // Route name
            "{city}",                           // URL with parameters
            new { controller = "Location", action = "Index", city = "" }  // Parameter defaults
        );
Sign up to request clarification or add additional context in comments.

3 Comments

@Ramesh: What do you mean it's not working? Are you still using the original route definition? Do you have a controller action with string parameter named city? This definitely works. You must be doing something wrong.
@Robert Koritnik, yes i was using the original definition along with this... I am looking into your answer. I ll change if thats the problem...
@Ramesh: Yes read my answer because I think that's exactly what you're after.
1

I am not sure there won't be easier option than this, but you can try this - using route constraint. Basically, you need to know the list of cities you have and then constrain the route to match only entries in that list.

The route constraint can be implemented as follows

public class CityConstraint : IRouteConstraint
{
    public static IList<string> CityNames = (Container.ResolveShared<ICityService>()).GetCities();

    bool _IsCity;
    public CityConstraint(bool IsCity)
    {
        _IsCity = IsCity;            
    }

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        if (_IsCity)
            return CityNames.Contains(values[parameterName].ToString().ToLower());
        else
            return !CityNames.Contains(values[parameterName].ToString().ToLower());
    }
}

And then put the route as follows:

routes.MapRoute("Location", "{cityName}", new { controller = "LocationController", action = "Index" }, new { cityName = new CityConstraint(true) });

Also make sure the above route is listed before the default route

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

Also note that, no controller name can be a city name.

Try this and see.

4 Comments

It's probably better to reverse route ordering and put a controller name constraint on default route because there is a finite number of defined controllers, and cities are most probably dynamic defined in the database. So default route with constraint first and then location route.
Reversing would also mean that there's no need for a custom constraint class. You can easily use built-in constraint functionality.
@Robert: Thanks for that, I have something like this playing on my head while I was writing the answer, but because my answer was coming after two others that tried using only route mapping. Your response below seems that 'other ways' I believe it could be achieved.
Yes true. @Ramesh seems a bit lost (or inexperienced in MVC routing) and needed a very exact answer hence I've provided one that's as close to what he needs as it can be.
1

If all your routing is related to these cities than remove default route and replace it with this route definition:

routes.MapRoute(
    "Default",
    "{city}",
    new { controller = "Location", action = "Index", city = "Mumbai" }
);

Then create a LocationController class:

public class LocationController : Controller
{
    public ActionResult Index(string city)
    {
        // do whatever needed; "city" param has the city specified in URL route
    }
}

If you still need your default route (controller/action/id) for other pages not just cities then it's probably better to put a constraint on your default route and define them like this:

routes.MapRoute(
    "Default",
    "{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional },
    new { controller = "Home|...|..." } // put all controllers here except "Location"
);
routes.MapRoute(
    "Location",
    "{city}",
    new { controller = "Location", action = "Index", city = "Mumbai" }
);

This will make other controllers still working and location will work just as well. The problem is of course if there's a city name that's the same as a name of one of your regular controllers. :) But you can control/avoid that as well.

Comments

0

You can do that by adding a route that hardcodes the controller name:

routes.MapRoute(
  "location", // Route name
  "{cityName}", // URL with parameters
  new { controller = "location", action = "index" } // Parameter defaults
);

routes.MapRoute(
  "Location", // Route name
  "{controller}/{action}/{cityName}", // URL with parameters
   new { controller = "Location", action = "index"} // Parameter defaults
)

This will route all requests of the form "/mumbai" to LocationController action method Index with parameter cityName set to "mumbai". It will also be able to route full controller/action spec using the second route.

4 Comments

This is of course not the correct route because it will work as: www.xxxxxx.in/location/index/mumbai and that's not what he wants.
@Robert Koritnik It will work if it is the only route defined. The framework will substitute the default values when they are not supplied AND will allow explicit controller/action/parameter URL.
I don't know how much you've worked with Asp.net MVC but this will never work as www.xxxx.in/cityname even though you define defaults for controller and action. cityname in this case will always be understood as controller name. So whenever you'd like to define a city URL will have to be www.xxxxx.in/location/index/somecity. How should framework know then what somecity means here? Is this a non-default controller? Or is it a non-default action? No. This is the city name. And both segments in front of it must be specified. Doesn't matter if they have default values...
Hmm, you're right, i've updated the code in the way that I would do it.

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.