0

I am getting the error

the current request is ambiguous between the following action methods: System.Web.Mvc.ActionResult Foo1(System.String) on type Project.Web.Controllers.PageController System.Web.Mvc.ActionResult Foo2(System.String) on type Project.Web.Controllers.PageController

The a href calling the ActionResults are

<a href="@Url.Action("Foo1", "Page", new { page = "Foo1" })">Foo1</a>
<a href="@Url.Action("Foo2", "Page", new { page = "Foo2" })">Foo2</a>

I am basically passing the string instead of a int id ( I realise this is not the best way to do this , but that is not the issue i want to address here )

This allows me to add a string parameter to the Routing for clean urls, so my ActionResult is now

[AllowAnonymous, Route("{page}")]
public ActionResult Foo1(string page)
{
   ...
}

and

[AllowAnonymous, Route("{page}")]
public ActionResult Foo2(string page)
{
   ...
}

Why is there ambiguity when the links are being passed to different ActionResults and the parameters are different?

  • Try using different route like `[AllowAnonymous, Route("{page/Foo2}")]` for your second ActionResult – Milen Dec 09 '14 at 10:31
  • Then i get the error here is an incomplete parameter in this path segment: '{page'. Check that each '{' character has a matching '}' character - i guess because that is not a correct parameter –  Dec 09 '14 at 10:46
  • @MilenPavlov. If i add a prefix Route("Foobar/{page}") then is works. I am still not sure why it works though –  Dec 09 '14 at 10:53
  • this might help: http://stackoverflow.com/questions/10668105/routing-the-current-request-for-action-is-ambiguous-between-the-following – Milen Dec 09 '14 at 11:00
  • or you can use completely different routes `[AllowAnonymous, Route("Foo1")] public ActionResult Foo1(string page) { ..... } [AllowAnonymous, Route("Foo2")] public ActionResult Foo2(string page) { ....... }` and then action `Foo1` – Milen Dec 09 '14 at 11:02
  • What is it that you are trying to accomplish with this approach? If the `Foo1` action is being accessed, what is the purpose of having `Foo1` passed in as the `page` parameter? – JLRishe Dec 09 '14 at 12:28
  • @JLRishe Foo1 is a dynamic property that can be changed by the administrator. It will not always be foo1. I have a entity type that controls static based pages , the page parameter defines what content to take from the database. Its just experimentation while i am learning asp mvc. –  Dec 10 '14 at 08:04
  • @gerdi I don't really understand what you are describing. Could you give a concrete example of what you are trying to do instead of using names like "Foo1" and "Foo2"? – JLRishe Dec 10 '14 at 12:15
  • @JLRishe Well Foo1 & Foo2 would just be a page like "about" or "overview" . Static type pages that do not change that often. However the content for the pages come from the database in a entity type of pages. So i want the admin to create the pages him/her self . This connects to one controller. and one entity framework class for all common pages of the site. This allows for one edit / update and delete class. –  Dec 11 '14 at 07:33

1 Answers1

2

You seem to be misunderstanding what the [Route] attribute does. Your example is definitely ambiguous.

This:

[AllowAnonymous, Route("{page}")]

means "map this action to any path that has one and only one segment, and treat that segment as the page parameter.

So all of these URLs:

http://example.com/Foo1
http://example.com/Foo2
http://example.com/SomethingElse

would be mapped to the action that has that attribute.

If you have two actions with that same route, then the MVC framework doesn't know which action to map the URL to. Both of them are valid candidates.

I think there is a simpler way to implement what you are trying to do.

In RouteConfig.cs, add a route map that doesn't include the controller name in the URL pattern:

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

Add an action parameter to your actions:

[AllowAnonymous]
public ActionResult Foo1(string action)
{
   // action has the value Foo1
   ...
}

and
[AllowAnonymous]
public ActionResult Foo2(string action)
{
   // action has the value Foo2
   ...
}

Remove the page stuff from your links:

<a href="@Url.Action("Foo1", "Page")">Foo1</a>
<a href="@Url.Action("Foo2", "Page")">Foo2</a>

And you should be all set.


Edit: If you just want to allow passing in a dynamic value for page, then you can get rid of the Foo1 and Foo2 actions, and just have one action:
[Route("{page=index}")]
public ActionResult Page(string page)
{
    // page is the value specified in the url
}

For links within the site, just use ordinary <a> elements:

<a href="/Foo1">To Foo1</a>
<a href="/Foo2">To Foo2</a>

and I think that should do it.

JLRishe
  • 99,490
  • 19
  • 131
  • 169