MVC Route parameters - asp.net-mvc

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/

Related

MVC4 Razor Appending ID to a url using route.config

I just cant achieve my goal of getting an id to appear in a URL. Here is an example of what I have done so far.
Here is my BlogController:
public ActionResult BlogPost(int hiddenBlogId)
{
TempData["id"] = hiddenBlogId;
return View(_repository);
}
Here is my route.config:
routes.MapRoute(
"MyBlog", // Route name
"blog/{action}/{id}", // URL with parameters
new { controller = "Blog", action = "blogpost", id = #"0|-?[1-9]\d*" } // Parameter defaults
);
I am completely missing the point somewhere. How can I pick up the parameter which went into my method/action BlogPost and then display it in the output URL.
http://www.mydomain/controller/id
It's so that in the end I should be able to display the title for each blog. I'm using an ID just for simplicity for now. Any help at all would be greatly appreciated.
Your route definition says that the third value is called id, but you are trying to bind hiddenBlogId in the method. The two names need to match. Change the hiddenBlogId action method parameter to id, or map a new route with the {hiddenBlogId} placeholder.

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

Can't get MVC Routing to work

I have a site and the url looks like this;
Home/LocationPage?locationId=f25a9ba4-54dc-4e6a-bdbf-094a5a6f7801
What I would like it to look like is;
Home/My Restaurant
I've tried mapping routes like this;
routes.MapRoute(
"Location",
"{Controller}/{LocationName}",
new { controller = "Home", action = "LocationPage", LocationName = "" }
But can't seem to get the URL to change at all.
Keep the route you just made, but you may need to add in a couple more things.
Add in a route constraint (or override the OnActionExecuting method on the controller or add a attribute to the action method) that looks up the the LocationName route parameter in the database and (if found) adds a locationId parameter to the route parameters. Then create an action called LocationPage that takes a locationId (location Name is optional).
That way you get nice urls coming in, but the action doesn't need to do the lookups.
If you receive a parameter called LocationId in your Action then you need to change your route:
routes.MapRoute(
"Location",
"{Controller}/{LocationId}",
new { controller = "Home", action = "LocationPage", LocationId = "" }
And don't forget that in this way you wouldn't get this parameter as Guid then you should make your logic to retrieve the Guid value by the provided name.

ASPNET MVC3: how to transform an anchor to Html.ActionLink?

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.

asp.net mvc routing: how to use default action but non-default parameter?

I'm rewriting the question, as the answers so far show me that I have not defined it good enough. I'll leave the original question for reference below.
When you set up your routing you can specify defaults for different url/route parts. Let's consider example that VS wizard generates:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "DefaultPage", action = "Index", id = UrlParameter.Optional } // Parameter defaults
In this example if controller is not specified, DefaultPageController will be used and if action is not specified "Index" action will be used.
The urls will generally look like: http://mysite/MyController/MyAction.
If there is no action in Url like this: http://mysite/MyController then the index action will be used.
Now let's assume I have two actions in my controller Index and AnotherAction. The urls that correspond to them are http://mysite/MyController and http://mysite/MyController/AnotherAction respectively. My "Index" action accepts a parameter, id. So If I need to pass a parameter to my Index action, I can do this: http://mysite/MyController/Index/123. Note, that unlike in URL http://mysite/MyController, I have to specify the Index action explicitly. What I want to do is to be able to pass http://mysite/MyController/123 instead of http://mysite/MyController/Index/123. I do not need "Index" in this URL I want the mvc engine to recognize, that when I ask for http://mysite/MyController/123, that 123 is not an action (because I have not defined an action with this name), but a parameter to my default action "Index". How do I set up routing to achieve this?
Below is the original wording of the question.
I have a controller with two methods definded like this
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(SomeFormData data)
{
return View();
}
This allows me to process Url like http://website/Page both when the user navigates to this url (GET) and when they subsequently post back the form (POST).
Now, when I process the post back, in some cases I want to redirect the browser to this url:
http://website/Page/123
Where 123 is some integer, and I need a method to process this url in my controller.
How do I set up the routing, so this works? Currently I have "default" routing generated by the wizard like this:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "DefaultPage", action = "Index", id = UrlParameter.Optional } // Parameter defaults
I tried adding another controller method like this:
public ActionResult Index(int id)
{
return View();
}
But this doesn't work as ambiguous action exception is thrown:
The current request for action 'Index'
on controller type 'PageController'
is ambiguous between the following
action methods:
System.Web.Mvc.ActionResult Index() on
type PageController
System.Web.Mvc.ActionResult
Index(Int32) on type PageController
I must add, that I also have other actions in this controller. This would have worked if I didn't.
Here is how this can be resolved:
You can create a route constraint, to indicate to the routing engine, that if you have something in url that looks like a number (123) then this is an action parameter for the default action and if you have something that does not look like a number (AnotherAction) then it's an action.
Consider This code:
routes.MapRoute(
"MyController", "MyController/{productId}",
new {controller="My", action="Index"},
new {productId = #"\d+" });
This route definition will only match numeric values after MyController in http://mysite/MyController/123 so it will not interfere with calling another action on the same controller.
Source: Creating a Route Constraint
If you keep the variable name to remain being ID, you don't need to change anything.
Rename the post one to "PostIndex" and add this attribute:
[ActionName("Index")]
Same question on SO here.
Ok, here's a cut/paste answer for you, if that helps.
public ActionResult Index() {
return View();
}
[AcceptVerbs(HttpVerbs.Post), ActionName("Index")]
public ActionResult PostIndex(SomeFormData data) {
return View();
}
Oh i got it now. I think It's not possible with default route, You need to map custom routes.
// /MyController/AnotherAction
routes.MapRoute(
null,
"MyController/AnotherAction",
new { controller = "DefaultPage", action = "AnotherAction" }
);
// /MyController
// /MyController/id
routes.MapRoute(
null,
"MyController/{id}",
new { controller = "DefaultPage", action = "Index", id = UrlParameter.Optional }
);
ps. Default routes like /MyController/id must mapped at last.
I think you want return the same view, but you need understand you are doing two differents things. One is receive post, and another is accessing by get, and another is accessing by get and parameter...
You should do 3 actionresult with different names, and return de same view as View("ThisIsTheResult")

Resources