views:

384

answers:

5

I have two controller actions with the same name but with different method signatures. They look like this:

    //
    // GET: /Stationery/5?asHtml=true
    [AcceptVerbs(HttpVerbs.Get)]
    public ContentResult Show(int id, bool asHtml)
    {
        if (!asHtml)
            RedirectToAction("Show", id);

        var result = Stationery.Load(id);
        return Content(result.GetHtml());
    }

    //
    // GET: /Stationery/5
    [AcceptVerbs(HttpVerbs.Get)]
    public XmlResult Show(int id)
    {
        var result = Stationery.Load(id);
        return new XmlResult(result);
    }

My unit tests have no issue with calling one or the other controller action, but my test html page throws a System.Reflection.AmbiguousMatchException.

<a href="/Stationery/1?asHtml=true">Show the stationery Html</a>
<a href="/Stationery/1">Show the stationery</a>

What needs to change to make this work?

+3  A: 

Heres a link you may find userful. It talks about overloading the MVC Controllers.

Brandon
Gave this a +1 the link was useful in making my decision.
Sailing Judo
+1  A: 

There are two ways to address this:

1> Change the method name. 2> Provide different ActionName attributes to the two methods. You can define your own attribute.

J.W.
Gave this a +1 because it would work, it just didn't suit my needs.
Sailing Judo
A: 

There is the ActionName attribute. Take a look.

Daniel A. White
+3  A: 

Just have one method like this.

[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Show(int id, bool? asHtml)
{
    var result = Stationery.Load(id);

    if (asHtml.HasValue && asHtml.Value)
        return Content(result.GetHtml());
    else
        return new XmlResult(result);
}
Schotime
I originally had something like this, but I didn't want to change all my unit tests to cast the ActionResult to the appropriate type (as well as add the null to the signature). However, this is probably the best way as I don't care for the other options. Answer +1
Sailing Judo
A: 

To overcome this problem you can write an ActionMethodSelectorAttribute that examines the MethodInfo for each action and compares it to the posted Form values and then rejects any method for which the form values don't match (excluding the button name, of course).

Here's an example:- http://blog.abodit.com/2010/02/asp-net-mvc-ambiguous-match/

You could also make a simpler ActionMethodSelectorAttribute which looks only at the submit button name but that would tie your controller and view more closely.

Hightechrider