Action not found in Route table? - asp.net-mvc-2

Just started my first MVC 2.0 .net application. And I set up some default pages like:
/Loa/Register
/Loa/About
But when I request for /Loa/sdfqsdf (random string) I get the "The resource cannot be found." error, how can I redirect this non-existing action to a default action?
Like an "action not found" default action?
thx!

Using routes
You can define more than one route (which is also quite common in real-life MVC applications), because some routes have particular settings that differ from the default one. And especially if you want to do decent SEO.
routes.MapRoute(
"DefaultRoute",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = string.Empty },
new { action = "Register|Index|About" } // route constraint that limits the actions that can be used with this route
);
routes.MapRoute(
"InvalidRoutes"
"{*dummy}",
new { controller = "Home", action = "Nonexisting" }
);
If you'll add additional routes to our route table, just make sure the InvalidRoutes is defined as the last one.

Related

MVC ignores route defaults and renders full “/Home/Index” URLs instead of root

My ASP.NET MVC project seems to ignore route defaults when composing URLs. For instance, Url.Action("Index", "Home") returns /Home/Index/, while it should return just / (which I have seen in all my other MVC websites). It does not have any problem with using URLs, e.g. by visiting http://myserver/, the default controller and action are found correctly.
How can I fix the behavior? (Note that I have found questions asking how to achieve this behavior, but nobody seems to suffer from this opposite problem.)
The project is nothing spectacular, no custom routing handlers etc., and the routing configuration is quite simple:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("LoginHandler");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{*id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
(The * is there because some actions use arbitrary strings as identifiers which might contain embedded slashes, and without the asterisk, the route does not match for such URLs.)
The problem lies indeed in the small asterisk. These catch-all parameters apparently do not match against UrlParameter.Optional defaults, and result in the URL always containing the whole path.
If you want to keep the default behavior, while also allowing arbitrary parameters using the catch-all parameter syntax, you need to use the catch-all parameter in a secondary route:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("LoginHandler");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "CatchAll",
url: "{controller}/{action}/{*id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
With this definition, simple parameters not containing slashes are handled using the first route (as is the URL generation when not specifying the exact route to be used), while complex parameters with slashes fall back to the second route, and are handled correctly there.
(Note that this might be just a bug in the MVC implementation: For catch-all parameters, MVC’s ParsedRoute.IsParameterRequired returns null as the default parameter value, which is then tested against the supplied UrlParameter.Optional from the route’s defaults, and is found to be different. Therefore, you might change the route definition to use id = null default instead of id = UrlParameter.Optional, instead of adding the secondary route, and it also seems to be working, but it might have unwanted side effects, I guess. I am also not sure if this behavior is deliberate, or just a bug.)

Redirect user to from a SEO like url to a controller action in ASP.NET MVC 2

is it possible to redirect a static seo "friendly" url address to a controller/action without loosing the original address?
For example:
if you navigate to http://localhost/find-the-best-employees
under the hood MVC takes you to http://localhost/Search/Employees (SearchEmployee controller, Index action). But the idea is to keep the address http://localhost/find-the-best-employees.
How can I make this work on ASP.NET MVC 2.0?
I was having a look at here and here with no luck during tests.
In Global.asax define a route like:
routes.MapRoute(
"findEmployess", // Route name
"find-the-best-employees", // URL with parameters
new { controller = "SearchEmployee", action = "Index" } // Parameter defaults
);
For this to work you need to use the route-name when generating the url, using this html helper
<%: Html.RouteLink("Search Employees","findEmployess")%>
Also you need to define this route before the default route:
//Your custom routes goes HERE before the default route
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);

Return PartialView in MVC3 Area is not searching in area

I am working on an ASP.Net MVC 3 RC project. I have one area named Drivers. I have a LoadPartial() action in a controller in the Drivers area that returns a PartialView(string, object); When this is returned I get an error on my webpage that says "The partial view 'PublicAttendanceCode' was not found." It searched the following locations:
~/Views/AttendanceEvent/PublicAttendanceCode.aspx
~/Views/AttendanceEvent/PublicAttendanceCode.ascx
~/Views/Shared/PublicAttendanceCode.aspx
~/Views/Shared/PublicAttendanceCode.ascx
~/Views/AttendanceEvent/PublicAttendanceCode.cshtml
~/Views/AttendanceEvent/PublicAttendanceCode.vbhtml
~/Views/Shared/PublicAttendanceCode.cshtml
~/Views/Shared/PublicAttendanceCode.vbhtml
Why is it not searching in the Drivers Area?
I have the following pretty basic routes in Global.asax.cs:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home",
action = "Index",
id = UrlParameter.Optional // Parameter defaults
}
);
}
And in DriversAreaRegistration.cs
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Drivers_default",
"Drivers/{controller}/{action}/{id}",
new { action = "RequestLeave", id = UrlParameter.Optional }
);
}
What am I missing that will make it look in the drivers area for the partial?
How are you providing area name to PartialView() method? I think you should be passing it in new { area = "Drivers" } as routeValues parameter.
The way that the MVC view engines know the area that they should look in is based on the route that was used to process the request.
In the case of the controller action that you have, are you certain that the request was processed by the area's route definition, or is it possible that the request was processed by the more general route that you defined in global.asax?
There are only four overloads of the method PartialView and it seems like neither of them accept routeValues as a parameter.
I solved this problem like this:
return PartialView(
VirtualPathUtility.ToAbsolute("~/Areas/MyArea/Views/Shared/MyView.cshtml"));
It works, but looks ugly.
This works too:
return PartialView("~/Areas/Admin/Views/Shared/MyView.cshtml", model);

Inconsistent Routing Results in MVC

Seems I'm still missing something to the MVC routing concept. I have a route that follows nearly the same pattern as another route in an area but for what ever reason I get a 404 every time I attempt to run it. I've tried to use Phil Haack's Route Tester DLL and according to that it hits the correct route (matched route comes out to common/itemhistory/{contentid}). When I try to run it for real, it blows up.
I'm trying to map a call to a JsonResult by passing a Guid. I've had success with other routes working fine (common is an area in my site).
What could I be doing wrong?
context.MapRoute(
"ItemHistory",
"common/itemhistory/{contentid}",
new { controller = "common", action = "GetItemHistory" },
new { contentid = #"^(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}$" }
);
context.MapRoute(
"Common_default",
"common/{action}",
new { controller="common", action = "Index" }
);
You are assigning action attribute to "GetItemHistory" and have defined itemhistory in the regular Route Pattern. Looks like you don't have a method in your controller by name "GetItemHistory"

actionlink not resolving urls related to route

I have the following route ( it's the first in my global.asax )
routes.MapRoute(
"AdminCompany", // Route name
"{controller}.aspx/{action}/{companyId}/{id}", // URL with parameters
new { controller = "Home", action = "Index", companyId = "", id = "" } // Parameter defaults
);
if i navigation to
"Order/DisplayAdmin/2/79000180" it resolves correctly
However if i do the following
Html.ActionLink("View", "DisplayAdmin", new {companyId = Model.CompanyId, id = order.OrderNumber }, new { #class = "button add" })
it displays
/Order.aspx/DisplayAdmin/39068760?companyId=0
which also works, but isn't so pretty :)
Here is my Controller Method
public ActionResult DisplayAdmin(int companyId, [DefaultValue(0)]int id, [DefaultValue(0)] int orderItemStatusId)
{
var viewModel = DisplayAdminViewModel(companyId, id, _statusResponses);
return View(viewModel);
}
Am i calling ActionLink the wrong way? how do i get the nice Urls?
only thing I can think of that is happening is that its falling back to the Default route, I did a copy paste of both your route and the html.ActionLink and it works perfectly for me displaying it like "/Order.aspx/DisplayAdmin/39068760/45456", i did replicate the same fault like you get if the naming isn't the same in the route and action link.
Use the overload of ActionLink that has a RouteValueDictionary argument.
It appears that you are currently using the overload with the "object" argument and it's going to a workable, but not as clean, url.