sakuntala
sakuntala

Reputation: 37

MVC 4 - routes turn into a query string

I downloaded the Chinook sample database and I'm trying to build a simple application to teach myself MVC 4 and EF. Chinook is basically a bunch of artists, their albums and tracks in each album. I wanted to create a REST-like URL structure for displaying each artist, their albums and tracks. This is what I was envisioning:

Chinook/Artist                              <- List of artists
Chinook/Artist/{id}                         <- Artist details
Chinook/Artist/{id}/Album                   <- List of albums for artist
Chinook/Artist/{id}/Album/{id}              <- Details for an album
Chinook/Artist/{id}/Album/{id}/Track        <- Track listing for album
Chinook/Artist/{id}/Album/{id}/Track/{id}   <- Track details

This is what my Route.config looks like:

 routes.MapRoute(
    name: "chinook_artist",
    url: "Chinook/Artist/{id}/{action}",
    defaults: new { controller = "Artist", action = "Index", id = UrlParameter.Optional }
);

routes.MapRoute(
    name: "chinook_album",
    url: "Chinook/Artist/{ArtistId}/Album/{id}/{action}",
    defaults: new { controller = "Album", action = "Index", id = UrlParameter.Optional, ArtistId = UrlParameter.Optional }
);

routes.MapRoute(
    name: "chinook_track",
    url: "Chinook/Artist/{ArtistId}/Album/{AlbumId}/Track/{id}/{action}",
    defaults: new { controller = "Track", action = "Index", id = UrlParameter.Optional, ArtistId = UrlParameter.Optional, AlbumId = UrlParameter.Optional }
);

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

My idea was to have Edit, Delete and Add actions as well for all three types of objects, and Index would serve as listing.

This works well enough, however this is what my URLs look like:

http://localhost:57264/Album/?ArtistId=8&AlbumId=10&TrackId=70

In all cases I'm using Html.ActionLink with controller, action, etc. To generate links in views. But I can't get my URLs to start with "Chinook" and be "clean" rather than use a query string, like this:

http://localhost:57264/Chinook/Artist/8/Album/10/Track/70

So I'm not sure what I'm doing wrong here. Am I going against the grain of how MVC is supposed to work? Are my routes defined incorrectly?

Upvotes: 0

Views: 797

Answers (1)

user3559349
user3559349

Reputation:

Looking at the last 2 routes

Chinook/Artist/{id}/Album/{id}/Track
Chinook/Artist/{id}/Album/{id}/Track/{id}

Your route definitions would need to be

//Chinook/Artist/{artistid}/Album/{albumid}/Track
routes.MapRoute(
  name: "chinook_track",
  url: "Chinook/Artist/{ArtistId}/Album/{AlbumId}/Track",
  defaults: new { controller = "Track", action = "Index" }
);

//Chinook/Artist/{artistid}/Album/{albumid}/Track/{id}
routes.MapRoute(
  name: "chinook_trackdetails",
  url: "Chinook/Artist/{ArtistId}/Album/{AlbumId}/Track/{id}",
  defaults: new { controller = "Track", action = "Details", id = UrlParameter.Optional }
);

and your controller

public class TrackController : Controller
{
  public ActionResult Index(int ArtistId, int AlbumId)
  {
    ....
  }
  public ActionResult Details(int ArtistId, int AlbumId, int id)
  {
    ....
  }
}

and in the view, generate the links as

@Html.ActionLink("Index", "Index", "Track", new { ArtistId = 5, AlbumId  = 3 }, null)
@Html.ActionLink("Details", "Details", "Track", new { ArtistId = 5, AlbumId = 3, id = 7 }, null)

Then if you wanted a route to edit a track in a similar format

//Chinook/Artist/{artistid}/Album/{albumid}/Track/{id}/Edit
routes.MapRoute(
  name: "chinook_trackedit",
  url: "Chinook/Artist/{ArtistId}/Album/{AlbumId}/Track/{id}/Edit",
  defaults: new { controller = "Track", action = "Edit"}
);

public ActionResult Edit(int ArtistId, int AlbumId, int id)
{
  ....
}

@Html.ActionLink("Edit", "Edit", "Track", new { ArtistId = 5, AlbumId = 3, id = 7 }, null)

Upvotes: 1

Related Questions