Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple route with multiple parameters MVC4

I have a webpage doing a redirection with two URLs parameters: id and bidId and I also have an other webpage with a redirection with two other URLs parameters: id and templateId.

I want to create the route to get a well formed url like those: localhost/12/50 but I have a problem with my routes.

            routes.MapRoute(
        name: "SubmitBid",
        url: "{controller}/{action}/{id}/{bidId}/",
        defaults: new { controller = "Tender", action = "SubmitBid", id = UrlParameter.Optional, bidId = UrlParameter.Optional });

        routes.MapRoute(
        name: "Tender",
        url: "{controller}/{action}/{id}/{templateId}",
        defaults: new { controller = "Tender", action = "Create", id = UrlParameter.Optional, templateId = UrlParameter.Optional });

When I am to the SubmitBid page the URL work perfectly but if I go to template page I have a url like this: localhost/5/?templateId=0

I don't understand why it's doesn't work and I need your help to understand why it is doing that. Thank you for your help. Karine


Edit: The way I am navigating is like this:

@Html.ActionLink(this.LocalResources("Use"), VIA.Enums.ActionName.UseTemplate.GetStringValue(), new { Id = "0", templateId = item.Id })

@using (Html.BeginForm("SubmitBid", "Tender", new { id = Model.Id, bidId = "0" }, FormMethod.Get, null))
{
    <div style="text-align: center; margin: 20px 0 0 0">
        <button class="btn btn-large btn-primary" type="submit">@this.LocalResources("Bid.Text")</button>
    </div>
}
like image 789
Karine Avatar asked Jul 14 '26 01:07

Karine


2 Answers

You should add specific routes for both controller actions:

routes.MapRoute(
    name: "SubmitBid",
    url: "Tender/SubmitBid/{id}/{bidId}/",
    defaults: new 
                { 
                    controller = "Tender", 
                    action = "SubmitBid", 
                    id = UrlParameter.Optional, 
                    bidId = UrlParameter.Optional 
                });

routes.MapRoute(
    name: "Tender",
    url: "Tender/Create/{id}/{templateId}",
    defaults: new 
                { 
                    controller = "Tender", 
                    action = "Create", 
                    id = UrlParameter.Optional, 
                    templateId = UrlParameter.Optional 
                });

// Default route, keep this at last for fall-back.
routes.MapRoute(
    name: "Default", 
    url: "{controller}/{action}/{id}", 
    defaults: new 
                { 
                    controller = "Home", 
                    action = "Index", 
                    id = UrlParameter.Optional 
                });
like image 114
Henk Mollema Avatar answered Jul 15 '26 14:07

Henk Mollema


I think this is your problem:

1) First, your second route you have setup is irrelevant. It will never be hit nor used to base links off of.

2) Second, because of this, when you included templateId in your route values for the template action link,

 new { Id = "0", templateId = item.Id })

ASP.Net MVC looked at your routes, found the first one that satisfied the NUMBER of parameters, then tried to resolve the optional params with the route values on the link. Since ASP.Net MVC's requirements were satisfied with the first route, the SubmitBid one, it could not find an optional parameter for the route value with a name of templateId. It only has "Id" and "bidId" for that route. At this point ASP.Net MVC decided to stick it on the url as a query string. (This also explains why "ID", the 5 value in the url, looks correct. It is an optional param on that route.)

If you do a "view source" on your web page, you will see the link is built with that query string on there.

Here's how you might fix this:

Since your second route will never be used, delete it. Change your first route to use a more generic 2nd optional parameter:

    routes.MapRoute(
    name: "DefaultRoute",
    url: "{controller}/{action}/{id}/{allPurposePrettyId}/",
    defaults: new { controller = "Tender", action = "SubmitBid", id = UrlParameter.Optional, allPurposePrettyId = UrlParameter.Optional });

Then both your BeginForm declaration and your ActionLink definition will use allPurposePrettyId in their respective route values.

@Html.ActionLink(this.LocalResources("Use"), VIA.Enums.ActionName.UseTemplate.GetStringValue(), 
new { Id = "0", allPurposePrettyId = item.Id })

@using (Html.BeginForm("SubmitBid", "Tender", 
new { id = Model.Id, allPurposePrettyId = "0" }, FormMethod.Get, null))
{
<div style="text-align: center; margin: 20px 0 0 0">
    <button class="btn btn-large btn-primary" type="submit">@this.LocalResources("Bid.Text")</button>
</div>
}

Obviously, you should get a better name than allPurposePrettyId but you get the gist of it. Remember the names of the optional params set on the routes are also what is expected on the signatures of the action methods the form and links goto.

like image 30
TSmith Avatar answered Jul 15 '26 15:07

TSmith



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!