1
votes

I'm having problems with routing. I have News controller and I can read the details of a news from url http://localhost/News/Details/1/news-title(slug). Here is no problem for now. But I created a controller called Services with Index action. Route config:

routes.MapRoute(
    "Services",
    "Services/{id}",
    new { controller = "Services", action = "Index" }
); 

When my Index Action is

public ActionResult Index(string title)
{
    return View(title);
}

I write localhost:5454/Services/sometext by hand in browser it works.

But when change my index action to

public ActionResult Index(string title)
{
    Service service = _myService.Find(title);
    ServiceViewModel = Mapper.Map<Service , ServiceViewModel >(service );
    if (service == null)
    {
        return HttpNotFound();
    }
    return View(serviceViewModel);
}

I get Http Error 404 Not Found for Url localhost/Services/ITServices.

I can add this services from admin page with it's title (ITServices for example). Then I do foreach in my Home Page for the services links

@foreach (var service Model.Services)
{
    <div class="btn btn-success btn-sm btn-block">
     @Html.ActionLink(service.Title, "Index", new { controller = "Services", id = service.Title }) 
    </div>
}

But I can't show the page in localhost/Services/ITServices.

When I click on the link I want to go to page localhost/Services/ITServices and it has to show the content(which can be added from admin page) like in the news. But I don't want to use it with action name and ids like in the news. How can I achieve this?

EDIT

Ok. I add FindByTitle(string title) in repository. I changed the id to title in RouteConfig and in the link in Home Page View. Then in my domain model deleted Id and updated Title as [Key]. Now it works. Only have to check with remote validation for possible duplicates of Title when adding new from admin page.

2

2 Answers

3
votes

The parameter name in the URL template does not match the argument on the Action (Index).

So you can do one of two things.

Change the template parameter to match the argument of the Action

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

Where Action Index is

public ActionResult Index(string title) { ... }

or you change the argument of the Action Index to match the paramater in the url template

public ActionResult Index(string id) { ... }

Where the route mapping is

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

But either way the route is not finding route because it cannot match the parameters.

In fact if the intention is to use the title as a slug you could go so far as to use a catch all route for services like

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

Take a look at the answers provided here

how to route using slugs?

Dynamic routing action name in ASP.NET MVC

1
votes

Try this:

public ActionResult Index(string id)