简体   繁体   中英

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>
}

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 
                });

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM