MVC routing error - asp.net-mvc-4

I have a custom route defined:
routes.MapRoute(
"FabricDetails", // Route name
"fabric/details/{designerUrlFriendlyName}/{collectionUrlFriendlyName}/{fabricUrlFriendlyName}", // URL with parameters
new { controller = "Fabric", action = "Details", designerUrlFriendlyName = UrlParameter.Optional, collectionUrlFriendlyName = UrlParameter.Optional, fabricUrlFriendlyName = UrlParameter.Optional }, // Parameter defaults
new[] { "StashFabrics.Web.Controllers" }
);
I have two nearly identical actionlinks and one is working while the other is not
#Html.ActionLink(fabric.FabricName, "Details", "Fabric", new RouteValueDictionary(new { designerUrlFriendlyName = fabric.DesignerUrlFriendlyName, collectionUrlFriendlyName = fabric.CollectionUrlFriendlyName, fabricUrlFriendlyName = fabric.FabricUrlFriendlyName }), null)
#Html.ActionLink(fabric.FabricName, "Details", "Fabric", new RouteValueDictionary(new { designerUrlFriendlyName = fabric.DesignerUrlFriendlyName, collectionUrlFriendlyName = "grand_hotel", fabricUrlFriendlyName = fabric.FabricUrlFriendlyName }), null)
For whatever reason, as soon as I replace the hard coded value for collectionUrlFriendlyName the link doesn't get built correctly
http://localhost:55089/Fabric/Details?designerUrlFriendlyName=jenean_morrison&collectionUrlFriendlyName=grand_hotel&fabricUrlFriendlyName=ballroom_in_azure
http://localhost:55089/fabric/details/jenean_morrison/grand_hotel/ballroom_in_azure
This has me stumped. Any advice would be appreciated.

Well I figured it out.
In the model of the view I have collectionUrlFriendlyName defined at two different levels; first on the model itself and then again on the class to which the model has a list.
I wasn't defining a value for collectionUrlFriendlyName at the list level, where the URL was being formed. But I guess when constructing the URL it would later find the value at the upper level and use it to form the ugly url (thus hiding the problem that it wasn't populated on the lower level)
If that make sense.

Related

Optional middle parameter in MVC4 Route

I am trying to create a controller action that receives several parameters for filtering a scope and then the final parameter is a required paging parameter for paging the results.
//Example Action
public ActionResult Details(string time, string regionscope, string localscope = null, int page = 1) {
}
//RouteConfig.cs
routes.MapRoute(
name: "LocationWithLocalScopeRoute",
url: "/Details/{time}/{regionscope}/{localscope}/{page}",
defaults: new
{
controller = "Location",
action = "Details",
localscope = UrlParameter.Optional
}
);
Is there anyway I can exclude the localscope parameter but still have the page parameter be interpreted as the page number by the controller (while still maintaining pretty URLs)?
// Test URLs
/Details/May-17/Mid/1
/Details/May-17/Mid/Bumville/1
I know I could add a route before the existing route:
//RouteConfig.cs
routes.MapRoute(
name: "LocationWithNoLocalScopeRoute",
url: "/Details/{time}/{regionscope}/{page}",
defaults: new
{
controller = "Location",
action = "Details"
}
);
I also realize I could put page before any of the other parameters.
routes.MapRoute(
name: "LocationWithLocalScopeRoute",
url: "/Details/{page}/{time}/{regionscope}/{localscope}",
defaults: new
{
controller = "Location",
action = "Details",
localscope = UrlParameter.Optional
}
);
Was just wondering if there was a way to make it work all in one route definition while still having the Test URLs work.
No, not without creating another specific route or making localscope the last parameter.
When using routing, only the last parameter can be marked as UrlParameter.Optional. If more that one is optional, then the routing engine has no way to know which route segment applies to which method parameter.
In your case when the url is ../Details/May-17/Mid/1, is the last segment with the value of 1 the value for localscope or the value for page? There is no way to determine that, so if you were to generate the url using #Url.Action() (or one of the other methods that generate url's), then the url will be generated with query string values, not route values.

Html.ActionLink not filling up the href attribute

Route definition:
context.MapRoute(
name: "VeranderingsTraject",
url: "Detail/{action}/{id}/{viewDate}/{toekomstBeeldId}",
defaults: new { controller = MVC.Detail.Name, action = MVC.Detail.ActionNames.VeranderingsTraject, viewDate = UrlParameter.Optional, toekomstBeeldId = UrlParameter.Optional },
namespaces: new[] { typeof(DetailController).Namespace }
);
DetailController:
public virtual ActionResult VeranderingsTraject(int id, DateTime? viewDate = null, int? toekomstBeeldId = null)
{ ... }
ActionLink in view:
The current view is actually also from the DetailController so I thought that I didn't need the controller name. Since it wasn't working, I added it, but to no avail.
#Html.ActionLink(linkText:"TEST LINK", actionName: "VeranderingsTraject", controllerName: "Detail", routeValues: new {id= 1, viewDate = Model.VersieDatum}, htmlAttributes: null)
Result in browser:
<a href="">
TEST LINK
</a>
Expected result:
<a href="/Detail/VeranderingsTraject/1/{date, i need to encode the url i know)/">
TEST LINK
</a>
So after some reading left and right (thank you google)
Seems that my routing was done completely wrong. So I cleaned up my whole routing table and now I'm getting a lot better results, it's still not perfect, but it can be fixed thanks to the answers given on other ActionLink related questions here on stackoverflow
I have about 10 actions on the detail controller giving the same view (shared info amongst different objects) I used to have a route for each of these so the correct route could not be determined.
Now all 10 routes are brougth to this one:
context.MapRoute(
name: "Detail",
url: "Detail/{action}/{id}/{viewDate}/{toekomstBeeldId}",
defaults: new { controller = MVC.Detail.Name, action = MVC.Detail.ActionNames.Persoon, viewDate = UrlParameter.Optional, toekomstBeeldId = UrlParameter.Optional },
namespaces: new[] { typeof(DetailController).Namespace }
)
The generated link is now the following:
So I just need to format that date a bit better and then read up to change the /persoon?id=... to /persoon/14/01-22-2014/ but I've seen some questions and answers on stackoverflow to remedy that problem.
Thanks for reading and thinking, hope this helps somebody

Generate wrong outgoing url because of segment variable reuse in MVC 4

Here is my RouteConfig.cs
routes.MapRoute(null,
"{controller}/Page{page}",
new {controller = "Product", action = "Index", category = (string) null},
new {page = #"\d+"}
);
routes.MapRoute(null,
"{controller}/{category}",
new {controller = "Product", action = "Index", page = 1}
);
routes.MapRoute(null,
"{controller}/{category}/Page{page}",
new {controller = "Product", action = "Index"},
new {page = #"\d+"}
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
And here is the code for generating url:
#Html.ActionLink("View Cart", "Index", "ShoppingCart", null, new { #class = "btn btn-orange" })
It works well when I navigate to, for example, Product/Page2, Product/Laptop, Product/Laptop/Page2. The problem is, whenever my current URL contains Page segment, it will try to reuse that segment for generating outgoing URL. So, if I'm at Product/Page2 the above generated URL would be ShoppingCart/Page2. I don't know how to avoid this.
Please help me. Thank you so much.
EDIT!!!
I've found a workaround way. Instead of using ActionLink, I use RouteLink like this:
#Html.RouteLink("View Cart", "Default", new { controller = "ShoppingCart", action = "Index" }, new { #class = "btn btn-orange" })
But I still want to use ActionLink, so please help me.
EDIT!!!
The workaround way doesn't work when I generate a link to ShoppingCart/Checkout. It still take me to Index action in ShoppingCart controller.
Create a new route pattern specific to ShoppingCart and make it the first route by placing it at the TOP.
routes.MapRoute(null,
"ShoppingCart/{action}",
new {controller = "Product"});
);
As a rule all the specific routes should come first.
This is because of the way the routing system tries to evaluate the value of segment variables when trying to match against a route.
So when the call to render the link occurs with the following arguments:
#Html.ActionLink("View Cart", "Index", "ShoppingCart", null, new { #class = "btn btn-orange" })
the framework when evaluating the route with template
{controller}/Page{page}
will resolve the controller segment variable to be ShoppingCart however when it cannot find a value for the page segment variable (via any of the arguments in the method call), it will then try and resolve that value from the RouteData object in the ViewContext. Since you have navigated to Product/Page2, the current value of page within the routes value dictionary is 2.
You can inspect this by looking at the value of ViewContext.RouteData.Values["page"] when rendering that view.

ASP.NET MVC 4 route crashes on one specific keyword: Ekstranett

I'm using routing in my ASP.NET MVC 4 application and I'm experiencing a very strange problem. I am attempting to establish a route to an area named Ekstranett, but if I use Ekstranett as the first URL parameter I get an Internal Server Error. I can use any word except for Ekstranett and I find that very strange. This is my setup:
context.MapRoute(
"Exception",
"Ekstranett/Exception/{action}/{*handle}",
new { controller = "Exception", action = "General", handle = UrlParameter.Optional },
new[] { "MyProject.Areas.Ekstranett.Controllers" }
);
context.MapRoute(
"Support",
"Ekstranett/Support/{action}/{*handle}",
new { controller = "Support", action = "Tickets", handle = UrlParameter.Optional },
new[] { "MyProject.Areas.Ekstranett.Controllers" }
);
context.MapRoute(
"Ekstranett_default",
"Ekstranett/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "MyProject.Areas.Ekstranett.Controllers" }
);
If I change Ekstranett to something like Ektranett, Testing, Foobar or anything else it works perfectly, but if I use Ekstranett it does not. Does anyone have any clue as to why I'm experiencing this behaviour?
Just a guess, but it could be because Ekstranett is the name of the Area? Could be causing a routing collision of some kind. Out of interest, if you use all lower case within the route, does that work? (e.g. "ekstranett/Support/{action}/{*handle}")
The problem has been solved! Ages ago I made a virtual directory called ekstranett, I deleted it and everything works wonderfully now!

Asp.net MVC custom routing with SEO

routes.MapRoute(
"Route",
"{id}/{*seostuff}",
new {controller = "Home", action="Index", seo = UrlParameter.Optional});
that will allow you to map urls such as http://www.somesite.com/11/whatever/goes-here/will-be-whatever-you/want
Here is the original post Asp.net MVC custom routing
Hi guys!
-what I want to know is how can this be code in controller? I have a static page like this Product/Phone/i-phone.aspx which is under the product it has a folder phone.. . any suggestion guys? thank you very much.. .
You can define the route you have described...
routes.MapRoute(
"Route", // ShopsToRent/0/B31 5EH/9/0/0/0/0/0
"{id}/{seo}", // URL with parameters
new
{
controller = "ControllerName",
action = "ActionName",
page = UrlParameter.Optional,
title = ""
} // Parameter defaults
);
I personally prefer to have a Keyword at the start of the url as this gives you an additional keyword (eg www.keywords.com/keywords )and allows future additions to the site...
routes.MapRoute(
"Route", // ShopsToRent/0/B31 5EH/9/0/0/0/0/0
"KEYWORD/{id}/{seo}", // URL with parameters
new
{
controller = "ControllerName",
action = "ActionName",
page = UrlParameter.Optional,
title = ""
} // Parameter defaults
);