November Happy Hour will be moved to Thursday December 5th.

Custom routing with extra parameters in Action method.

Vote:
 

I have the following controller

public async Task Index(MyPage currentPage, int myId) 
{
        //Other code here, not important
	return View();		
}


I've then created a page and named it "MyExamplePage"
The following url works

http://example.com/MyExamplePage?myId=1337

But I want it to work like this:

http://example.com/MyExamplePage/1337

I've added the following route to make it work

routes.MapContentRoute(
	"MyCustomRoute", "{language}/{node}/{action}/{myId}",
		new {
				controller = "MyExamplePage",
				action = "Index"
		});


This mapping makes the following url work: http://example.com/MyExamplePage/Index/1337

My question: How can I make it work WITHOUT the ACTION parameter in the url? I want it to default to "Index".

#176559
Mar 21, 2017 14:47
Vote:
 

The reason you get a 404 is that there is no route that consumes the "1337" part of your url. An alternative to defining a custom route as in your example is to register a partial router for your type MyPage. In your partial router you should then consume the "1337" segement and add it to segmentContext.RouteData.Values, then it will be model binded to your parameter. Something like this:

 public class ParameterPartialRouter : IPartialRouter<MyPage, MyPage>
    {
        public PartialRouteData GetPartialVirtualPath(MyPage content, string language, RouteValueDictionary routeValues, RequestContext requestContext)
        {
            return null;
        }

        public object RoutePartial(MyPage content, SegmentContext segmentContext)
        {
            var nextValue = segmentContext.GetNextValue(segmentContext.RemainingPath);

            int myId;
            if (Int32.TryParse(nextValue.Next, out myId))
            {
                segmentContext.RouteData.Values["myId"] = myId;
                segmentContext.RemainingPath = nextValue.Remaining;
            }

            return content;
        }
    }

And then you could register your partial router with extension method to RouteCollection as:

routes.RegisterPartialRouter(new ParameterPartialRouter());
#176622
Mar 23, 2017 9:14
Vote:
 

Hello, thank you for your answer. I can't get it to work unfortunately, I still recieve a 404 when trying to access the url.

I put a breakpoint in the RoutePartial method and it gets hit and the correct values are set. It gets git twice though, is that correct? I've also placed a breakpoint in my controller but it never gets hit.

SO: Im hitting the breakpoint in RoutePartial, twice, but I never hit the breakpoint in my page controller. What am I missing?

#176626
Mar 23, 2017 9:43
Vote:
 

Your partial controller might get hit several times (there are multiple routes registered). It is crucial that you consume the segment, that is that you update segmentContext.RemainingPath. If you look in the debugger is there anything left in segmentContext.RemainingPath after you have consumed your segment?

#176627
Mar 23, 2017 9:53
Vote:
 

Nope the remaining path is empty(empty string). 

Is it weird that I recieve a 404 error from the StaticFileHandler? 

#176628
Mar 23, 2017 9:58
Vote:
 

And you return the same page as you get in from your PartialController?

I guess the StaticFileHandler is registered as a wildcard handler as last handler in the list and then if nothing else (like a route) handles the request i ends up in the staticfilehandler.

#176632
Mar 23, 2017 10:11
Vote:
 

My Controller looks like this

public class MyPageController : PageController<MyPage> 
{
    public async Task<ActionResult> Index(MyPage currentPage, int myId) 
    {
    //Other non important code here
        return View("~/Views/MyPage/Index.cshtml",
            new MyPageViewModel
            {
                   //some stuff here
            });
    }
}

And my PartialRouter looks like this, do you see anything weird?

public class ParameterPartialRouter : IPartialRouter<MyPage, MyPage> 
{
    public object RoutePartial(MyPage content, SegmentContext segmentContext) 
    {
        var nextValue = segmentContext.GetNextValue(segmentContext.RemainingPath);

        int myId;
        if(Int32.TryParse(nextValue.Next, out myId)) 
        {
            segmentContext.RouteData.Values["myId"] = myId;
            segmentContext.RemainingPath = nextValue.Remaining;
        }

        return content;
    }

    public PartialRouteData GetPartialVirtualPath(MyPage content, string language, RouteValueDictionary routeValues, RequestContext requestContext) 
    {
        return null;
    }
}

I then register it like this in Global.asax.cs:

protected override void RegisterRoutes(RouteCollection routes) 
{
    base.RegisterRoutes(routes);
    new RouteConfig().RegisterRoutes(routes);
}
public void RegisterRoutes(RouteCollection routes) 
{
    routes.RegisterPartialRouter(new ParameterPartialRouter());
}
#176633
Edited, Mar 23, 2017 10:24
Vote:
 

Aaah it's working now, the problem was the name of my action method. I had renamed it to Show instead of Index. When I changed back to Index it started working! Thank you man :)

#176640
Mar 23, 2017 10:54
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.