ASPNET MVC3: how to transform an anchor to Html.ActionLink? - asp.net-mvc

I have the following a href link:
title
That i use for showing SEO-friendly urls; i would like, instead of the anchor tag, to use the Html.ActionLink.
How can i transform the anchor in ActionLink considering that i have not the Action name on the url?

You can use Html.ActionLink even when the action is not present in the URL; you just need an appropriate route. Routes are used for both inbound URL matching and outbound URL generation.
First things first, you'll need a route in the Routes collection to be used as a template for the URLs that you want to generate
routes.MapRoute(
null, // name
"News/{id}/{title}", // URL pattern
new { controller = "News", action = "Index" }, // defaults
new { id = "\d+", title = #"[\w\-]*" }); // constraints
This route will only match if id is a number and title contains only word characters and/or hyphens. The route needs to be registered before any more "general" routes as the order of routes is important; the framework stops on the first matching route, it does not try to find a "best" match.
Now you can use Html.ActionLink to generate routes.
#Html.ActionLink("title", "Index", "News", new { id = item.id, title = item.NewsSeoTitle })
You may also want to look at T4MVC (available as a NuGet package) too as it adds some overloads that removes the need for magic strings all over the place
Assuming your controller action looks like
public class NewsController
{
public ActionResult Index(int id, string title)
{
return View();
}
}
T4MVC adds an overload that allows you to use Html.ActionLink like
#Html.ActionLink("title", MVC.News.Index(item.id, item.NewsSeoTitle))
much neater :)

If you are using the custom links which is not corresponding to the controller/action structure, maybe it's better to use your own html extension
public static string SeoLink(this HtmlHelper helper, string itemId, string title, string seoTitle)
{
return String.Format("{1}",
VirtualPathUtility.ToAbsolute(String.Format("~/News/{0}/{1}", itemId, seoTitle)),
title);
}
As for Html.ActionLink: from the name of extension you can find the it work with actions. Of course you can provide such action and controller names to fit your requirements, but it's not a good idea, especially if your code will be supported by any other developer - he will never find such action in controller which is specified in ActionLink as actionName param.

Related

how to create hierarchy of pages in asp.net MVC

I am working on a classified website that will have links like "electronics/mobiles/samsung/samsungS3/adTitle". How to create hierarchy of views like that in asp.net. If the answer is HMVC then please refer some link that contains complete guide how to implement HMVC.
You don't need hierarchy of Views, you should use Route Config that will allow you to get View that you need base on URL.
From 4 Version of MVC also have areas not only controlles and View by default. So check this tutorial to know how to customise your Routing.
You don't need to create views in this hierarchy but you need to create URLs in this fashion and that is called friendly URLs.
Look at following stack overflow question
How can I create a friendly URL in ASP.NET MVC? and Friendly URL
You will be defining another route which will end up on your single action method. So You will add a route in routeConfig.cs as follows
routes.MapRoute(
name: "custom",
url: "{category}/{type}/{manufacturer}/{version}/{Title}",
defaults: new { controller = "Home", action = "customRoute"}
);
and your custom action will have all values passed in as param be as follows
public string customRoute(string category, string type, string manufacturer, string version, string Title)
{
return category + type + manufacturer + version + Title;
}
You can achieve the same using action based routing as well
// eg: electronics/mobiles/samsung/samsungS3/adTitle
[Route("{category}/{type}/{manufacturer}/{Title}")]
public ActionResult Index(string cateogry, string type,string manfacture, string Title) { ... }

How do I do Short URLs in MVC?

Suppose I want to publish (like in paper catalogs) some "short URLs" that are easy to type/remember, but I want them to redirect to a verbose, SEO-friendly URL. How do I accomplish that with MVC routes?
Example:
http://mysite.com/disney
becomes
http://mysite.com/travel/planning-your-disney-vacation (with "travel" as the Controller)
The things I've tried:
Just setup a route for it. Problem: the URL doesn't change in the browser (it stays "/disney".
Use NuGet package RouteMagic (see Haacked's article). Problem: I get an error: The RouteData must contain an item named 'controller' with a non-empty string value. I think this is because I don't have a static word before my controller ("travel") like he did (with "foo" and "bar")???
Use a redirect module (like Ian Mercer's). Problem: the route matches on my HTML.ActionLinks when creating URLs which I don't want (Haacked mentions this in his article and says that's why he has GetVirtualPath return NULL ...?)
I'm out of ideas, so any would be appreciated!
Thanks!
You could set up a catch-all type route, to direct all /something requests to a specific action and controller, something like:
routes.MapRoute(
"ShortUrls",
"{name}",
new {controller = "ShortUrl", action = "Index", name = UrlParameter.Optional}
);
(depending on how the rest of your routing is set up, you probably don't want to do it exactly like this as it will likely cause you some serious routing headaches - but this works here for the sake of simplicity)
Then just have your action redirect to the desired URL, based on the specified value:
public class ShortUrlController : Controller
{
//
// GET: /ShortUrl/
public ActionResult Index(string name)
{
var urls = new Dictionary<string, string>();
urls.Add("disney", "http://mysite.com/travel/planning-your-disney-vacation");
urls.Add("scuba", "http://mysite.com/travel/planning-your-scuba-vacation");
return Redirect(urls[name]);
}
}
I just faced the same problem.
In my Global:
routes.MapRoute(
"ShortUrls",
"{name}",
new { controller = "Home", action = "Index", name = UrlParameter.Optional }
);
In my Home Controller:
public ActionResult Index(string name)
{
return View(name);
}
This way is dynamic, didn't want to have to recompile every time I needed to add a new page.
To shorten a URL you should use URL rewriting technique.
Some tutorials on subject:
url-rewriting-with-urlrewriternet
url-routing-with-asp-net-4
URL rewriting in .Net

MVC Route parameters

If I have this route:
routes.MapRoute(
"BlogRoute", // Route name
"blog/{action}", // URL with parameters
new { controller = "Blog", action = "Index", id="abc" } // Parameter defaults
);
... and have this Index method in the controller:
public ActionResult Index(string id)
{
return View((object)id);
}
Is it possible for someone to change that id parameter from "abc" to something else? For example, by appending ?id=somethingElse to the URL? I tried that but it didn't change it. So is it guaranteed that I'll always get "abc" in the Index method?
Basically I need to send a hardcoded string when one route is chosen and I don't want the user to be able to change this string via the URL or any other mechanism. It's like "abc" is a password (it's not but just assume it is). Only the developer is allowed to set this string by editing Global.asax.cs.
Is it possible?
You can add a constraint for the id parameter using the regular expression /abc/

Customizing the url-from-parameters lookup in asp.net mvc

I have a route added by the code
routes.MapRoute("MyRoute", "TheUrl", new { controller = "MyController", action = "MyAction" });
I can then do a reverse lookup with the arguments like UrlHelper.Action("MyAction", "MyController"), and it will return a nice url like ~/TheUrl
However, for this route I want the generated URL to be ~/TheUrl?p=2354, with the parameter being some versioning parameter. Is there a way of doing this by mapping the route with some customized route handler or something? The versioning parameter will be non-standard and require some custom code to execute every time the Url is looked up.
I think a UrlHelper extension method would be most ideal and simple here specially.
public string MyRoute(this UrlHelper url)
{
string versionNumber = GetVersionNumber(); // or w/e is required to get it
return Url.Action("MyAction", "MyController") + "?p=" + versionNumber;
}
This would make calling that route much easier in html
<%= Url.MyRoute() %>

Areas And Routes

I'm using areas everywhere and I'm wanting something like the following:
http://localhost/MyArea/MySection/MySubSection/Delete/20
Usually I access things by doing the following:
http://localhost/MyArea/MySection/MySubSection/20
But if I want to delete then I have to say
http://localhost/MyArea/MySection/DeleteEntryFromMySubSection/20
With routes, how do you do this? (the routes aren't realistic by the way, they're much more concise than this in my system)
EDIT: This is specifically related to the use of Areas, an ASP.NET MVC 2 Preview 2 feature.
It would depend on how your routes & controllers are currently structured.
Here's an example route you might want to use.
If you want to be able to call the following route to delete:
http://localhost/MyArea/MySection/MySubSection/Delete/20
And let's assume you have a controller called "MyAreaController", with an action of "Delete", and for the sake of simplicity let's assume section and subsection are just strings e.g.:
public class MyAreaController : Controller
{
public ActionResult Delete(string section, string subsection, long id)
{
Then you could create a route in the following way (in your Global.asax.cs, or wherever you define your routes):
var defaultParameters = new {controller = "Home", action = "Index", id = ""};
routes.MapRoute("DeleteEntryFromMySubSection", // Route name - but you may want to change this if it's used for edit etc.
"{controller}/{section}/{subsection}/{action}/{id}", // URL with parameters
defaultParameters // Parameter defaults
);
Note: I'd normally define enums for all the possible parameter values. Then the params can be of the appropriate enum type, and you can still use strings in your path. E.g. You could have a "Section" enum that has a "MySection" value.

Resources