views:

839

answers:

3

Our company is developing an API for our products and we are thinking about using ASP.NET MVC. While designing our API, we decided to use calls like the one below for the user to request information from the API in XML format:

http://ws.audioscrobbler.com/2.0/?method=artist.getimages&artist=cher&api_key=b25b959554ed76058ac220b7b2e0a026

As you can see, multiple parameters are passed (i.e. artist and api_key). In ASP.NET MVC, artist would be the controller, getImages the action, but how would I pass multiple parameters to the action?

Is this even possible using the format above?

+5  A: 

Parameters are directly supported in MVC by simply adding parameters onto your action methods. Given an action like the following:

public ActionResult GetImages(string artistName, string apiKey)

MVC will auto-populate the parameters when given a URL like:

/Artist/GetImages/?artistName=cher&apiKey=XXX

One additional special case is parameters named "id". Any parameter named ID can be put into the path rather than the querystring, so something like:

public ActionResult GetImages(string id, string apiKey)

would be populated correctly with a URL like the following:

/Artist/GetImages/cher?apiKey=XXX

In addition, if you have more complicated scenarios, you can customize the routing rules that MVC uses to locate an action. Your global.asax file contains routing rules that can be customized. By default the rule looks like this:

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

If you wanted to support a url like

/Artist/GetImages/cher/api-key

you could add a route like:

routes.MapRoute(
            "ArtistImages",                                              // Route name
            "{controller}/{action}/{artistName}/{apikey}",                           // URL with parameters
            new { controller = "Home", action = "Index", artistName = "", apikey = "" }  // Parameter defaults
        );

and a method like the first example above.

Ryan Brunner
+1 Good answer. Too bad this question wasn't asked two weeks ago ;) Would have saved me some google time.
magnus
The MapRoute syntax is incorrect on the second maproute.
George Stocker
Really? I'm having trouble seeing the syntax error. I'll correct if you let me know where it is.
Ryan Brunner
Your route specifies `{controller}/{action}/{artistName}/{apikey}`, but you don't use `{artistName}` in the object you create. You should change `artist = "",` to `artistName = "",`
George Stocker
Thanks, I fixed the error.
Ryan Brunner
+accepted. Great info. Thanks.
CodingWithoutComments
+2  A: 

You can pass arbitrary parameters through the query string, but you can also set up custom routes to handle it in a RESTful way:

http://ws.audioscrobbler.com/2.0/?method=artist.getimages&artist=cher&
                                  api_key=b25b959554ed76058ac220b7b2e0a026

That could be:

routes.MapRoute(
    "ArtistsImages",
    "{ws}/artists/{artist}/{action}/{*apikey}",
    new { ws = "2.0", controller="artists" artist = "", action="", apikey="" }
    );

So if someone used the following route:

ws.audioscrobbler.com/2.0/artists/cher/images/b25b959554ed76058ac220b7b2e0a026/

It would take them to the same place your example querystring did.

The above is just an example, and doesn't apply the business rules and constraints you'd have to set up to make sure people didn't 'hack' the URL.

George Stocker
A: 

I wish I had an answer, but I only have a question. The foregoing sounds simple enough, but I can't seem to code the ActionLink call right. I'm really stumped.

I've worked through the NerdDinner tutorial, but my app needs to go one level deeper. So as an example they have a list of Dinner events, including a "Details" hyperlink as follows:

<%: Html.ActionLink(dinner.Title, "Details", new { id=dinner.DinnerID }) %>

This invokes the Details action method in the Dinners controller, which is expecting a single parameter straightforwardly supplied by the code "new {id=dinner.DinnerID}":

    //
    // GET: /Dinners/Details/5

    public ActionResult Details(int? id) {
        if (id == null) {
            return new FileNotFoundResult { Message = "No Dinner found due to invalid dinner id" };
        }

        Dinner dinner = dinnerRepository.GetDinner(id.Value);

        if (dinner == null) {
            return new FileNotFoundResult { Message = "No Dinner found for that id" };
        }

        return View(dinner);
    }

Well and good! But I have an application that looks at collections of documents. Using somewhat similar logic, I can list an index page of the collections and click on a hyperlink that leads to another index page showing the documents that belong to that collection. Now how do I create a hyperlink in the second index page that will lead to information about that one document? An example would be an abstract for the document, or a word-count analysis. What do I need in global.asax.cs, and how do I code the ActionLink() call to make it work? I know I can make the action method itself work by manually setting the parameter values in the debugger, but I can't figure out how to send the proper arguments to the parameters.