0

I have an area named adpan in my mvc site with following route config:

context.MapRoute(
     "adpan_clinics",
     "adpan/DoctorClinics/{doctorObj}/{controller}/{action}/{clinicObj}",
     new { action = "Index", Controller = "Clinics", clinicObj = UrlParameter.Optional }
     );

context.MapRoute(
    "adpan_default",
    "adpan/{controller}/{action}/{obj}",
    new { action = "Index", Controller = "Dashboard", obj = UrlParameter.Optional }
    );

I use T4MVC for routing. Everything works fine until I want to route back from adpan_clinics to adpan_default using action link.

Scenario) I have following urls:

1st url) http://localhost/adpan/Doctors/Index

2nd url) http://localhost/adpan/DoctorClinics/doctor1/Clinics/index

I can redirect to 2nd url with an action link on 1st url's view like this:

 @Html.ActionLink("Manage Clinics", MVC.adpan.Clinics.Index().AddRouteValues(new { doctorObj = item.Url }))

But, when redirecting back to 1st url using following action link, I face url appending problem:

 @Html.ActionLink("Back to Doctors", MVC.adpan.Doctors.Index())

This action link gives me the following bad url instead of 1st url(Although the page loads correctly!):

bad url) http://localhost/adpan/DoctorClinics/doctor1/Doctors

NOTE: I've also tried this without T4MVC and specifying null values in action link parameters as follow, but still getting the bad url:

@Html.ActionLink("Back to Doctors", "Index", "Doctors", null, null)

I'm just working in adpan area with 2 routes.

I would appreciate any solution and if possible, the reason for getting the correct view from that bad url.

Efe
  • 800
  • 10
  • 32

2 Answers2

1

Route values are supplied not just from the parameters of ActionLink, but will also bleed over from the current request. While many people don't find this intuitive, it makes it really easy to do things like stay within the current culture or area of the site.

Route values are not for meta data. They are the values that will be used when matching a URL pattern or to determine which route to use to build the outgoing URL. I suspect that is what you are grappling with, because it is very unusual to set a route value to a URL.

If you need to pass meta-data along with route information, there is a DataTokens property that is meant for that purpose. While both are passed through the request, only route values are used to determine whether the route matches.

It is also possible to override the route values from the current request by specifying them explicitly.

@Html.RouteLink("foobar", new { controller = "Home", action = "Index", doctorObj = "" })

But since you would need to do that on every affected link, it is much more practical to keep the invalid data out of the route values in the first place.

NightOwl888
  • 55,572
  • 24
  • 139
  • 212
  • good reason for staying within current culture and area. but can you tell me what you mean exactly by meta-data? – Efe Oct 20 '17 at 16:25
  • Meta data means data that does not actually control how the URL is built, but is for some other application purpose. For example, [MvcCodeRouting](https://github.com/maxtoroq/MvcCodeRouting) uses `DataTokens` to determine what depth the current controller is from the root of the site based on its namespace, which determines how many segments to put into the URL. But that info is not used for matching the route with the incoming request. – NightOwl888 Oct 20 '17 at 16:31
  • I feel confused. what i try to do is to generate the 1st url when I am in adpan_clinics route. I also want to avoid url parameters like ?doctorObj=doctor1, because of that, I've used model binding to get neat urls. Your suggested solution gives me this url: http://localhost/adpan/Doctors?doctorObj=doctor1 . omiting doctorObj="" gives me the bad url again. I can't undestand it – Efe Oct 20 '17 at 17:02
0

Based on @NightOwl888 answer and difference between RouteLink and ActionLink, I found the solution for both hard-coded approach and T4MVC approach.

1) Hard-Coded approach: route name must be specified:

//signiture: RouteLink(this HtmlHelper htmlHelper, string linkText, string routeName, object routeValues);
@Html.RouteLink("Back to Doctors","adpan_default", new { controller = "Doctors", action = "Index"})

resulting url: http://localhost/adpan/Doctors

2) T4MVC approach: route name must be specified:

//signiture: RouteLink(this HtmlHelper htmlHelper, string linkText, string routeName, ActionResult result, IDictionary<string, object> htmlAttributes)
@Html.RouteLink("Back to Doctors","adpan_default", MVC.adpan.Doctors.Index().AddRouteValues(new {Area=""}), null)

resulting url: http://localhost/adpan/Doctors

Why AddRouteValues(new {Area=""}) ?

Due to the discussion here, it seems like a bug in T4MVC. Below route link adds ?Area=adpan as a futile parameter to the url:

@Html.RouteLink("Back to Doctors", "adpan_default", MVC.adpan.Doctors.Index(), null)

resulting url: http://localhost/adpan/Doctors?Area=adpan

However, this can be a trick to cheat over unwanted url parameters in T4MVC.

Efe
  • 800
  • 10
  • 32