Redirect user to from a SEO like url to a controller action in ASP.NET MVC 2 - 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
);

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.)

How to handle ASP MVC Url Parameter containing forward slash

I am working on a ASP.Net MVC project. I have a particular controller action that accepts a date value in the form yyyy/mm/dd. So the URL becomes
http://localhost/MyProject/PublicReview/GetReviews/2012/10/29.
where GetReviews is an action and 2012/10/29 the parameter.
My RouteConfig is as follows:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(name: "Default",url: "{controller}/{action}/{id}",defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}
How should I change the routevalues ? What should be the order of MapRoute values?
I've not tested this, but I'm guessing this will work in your scenario:
routes.MapRoute(
"Reviews", "PublicReview/GetReviews/{year}/{month}/{day}"
{ controller = "PublicReview", action = "GetReviews" };
Note that this will need your GetReviews method to have three properties of "year", "month" and "day". You'll then have to parse them into a DateTime.
Taken from http://www.asp.net/mvc/tutorials/controllers-and-routing/creating-custom-routes-cs which uses "-" for date separators.

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

ASP.NET MVC 2.0: How to read querystring value

I am trying to build a small ASP.NET MVC 2 application.I have a controller class with the below method in it
public ActionResult Index()
{
TestMvc.Models.PersonalInformation objPerson = new TestMvc.Models.PersonalInformation();
objPerson.FirstName = "Shyju";
objPerson.LastName = "K";
objPerson.EmailId="shyju#company.com";
return View(objPerson);
}
And when the page (View) being called, i can see this data there as my view has these data's displaying. Now i want to know how can i pass a query string in the url and use that id to build the PersonalInformation object.Hoe can i read the querystring value ? Where to read ?
I want the quesrtstring to be like
http://www.sitename/user/4234 where 4234 is the user id
http://www.sitename/user/4234 is not a querystring. The querystring is the part of the URL that comes after the ?, as in http://www.sitename/user?userId=42
However, the default routes that come with the MVC project template should allow you to simply change the signature of your action method to
public ActionResult Index(int id)
and you should get the desired result. You should look into how routing works in MVC if you want full control of your URLs.
Also, note that the index action is usually used for showing a list of all objects, so you probably want the Details action for showing 1 user object.
What you want is to modify your action to accept an id like so:
public ActionResult Index(string id)
{
TestMvc.Models.PersonalInformation objPerson = new TestMvc.Models.PersonalInformation();
if (!string.isNullOrEmpty(id))
{
objPerson = getPerson(id);
}
return View(objPerson);
}
Then add a route to your global.asax:
routes.MapRoute(
"MyRoute", // Route name
"user/{id}", // URL with parameters
new { controller = "mycontroller", action = "index", id = ""} // Parameter defaults
);

Action not found in Route table?

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.