I am trying to build my ASP.NET MVC 4.5 project to use search engine friendly URLs. I am using the following route mapping.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}/{title}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional, title = UrlParameter.Optional }
);
The intention is so that I can create URLs like this:
Mysite.com/Home/Page/1/this-title-bit-is-just-for-show
but it fails and I have to use URLs like this:
Mysite.com/Home/Page?page=1
In case it matters, the Controller Action that this link points to is below:
public ActionResult Page(int page)
{
PostModel pm = new PostModel(page);
return View(pm);
}
And I am generating URLs like this:
1
Can someone tell me where I am going wrong?
Instead of
1
Use
1 //instead of page use id here
and change action method as shown :-
public ActionResult Page(int id) //instead of page use id here
{
PostModel pm = new PostModel(id);
return View(pm);
}
Related
I am learning asp.net MVC and I was trying Redirect to action and I tried the following code and I keep getting Redirect Loop Error.
This is the Controller class in which I am getting an error
public class CuisineController : Controller
{
// GET: Cuisine
public ActionResult Search(string name)
{
return RedirectToAction("About","Cuisine");
}
public ActionResult Index()
{
return Content("This is Index");
}
public ActionResult About()
{
return Content("this is About");
}
}
I have also created a route of my own other than the Default route
routes.MapRoute(name: "Cuisine",
url: "cuisine/{name}",
defaults: new { controller = "Cuisine", action = "Search", name = UrlParameter.Optional });
When I try to access the Cuisine controller it gives me a redirect loop error.
Thank you
In your routeConfig, you have a route defined for "cuisine/{name}" and it will be sent to the Search action method.
In your Search action method, You are redirecting to the About, Which is cuisine/About. This is matching with the route you defined cuisine/{name} so it will send the request to Search action again. The same process will keep running. That is why you are getting the redirect loop
You should either delete this specific route you defined or rename the url pattern for cusine search to prevent the redirect loop.
routes.MapRoute(name: "Cuisine",
url: "searchcuisine/{name}",
defaults: new { controller = "Cuisine", action = "Search",
name = UrlParameter.Optional });
This should be pretty obvious:
routes.MapRoute(name: "Cuisine",
url: "cuisine/{name}",
defaults: new { controller = "Cuisine", action = "Search", name = UrlParameter.Optional })
Says all urls that start with cuisine/ use the Search method on the CuisineController.
/Cuisine/About starts with that url, so it willl always use the Search method.
It looks like you want to make {name} part of URL. You can use attribute routing instead of changing default routing, it does not have such global "destructive" effects (explained in other answers) at least, and looks it's what you are actually after :)
[Route("Search/{name}")]
public ActionResult Search(string name)
{
return RedirectToAction("About", "Home");
}
See more about attribute routing here (for this to work, don't forget to add routes.MapMvcAttributeRoutes() if it is not there yet).
You need to restore controller action pattern. Just change url: "cuisine/{name}" to url: "cuisine/{action}/{name}"
I am trying to pass 3 parameters, one int, and 2 datetime to a controller with no luck. I have created custom Routes, but no matter what I do it never connects.
In My View I have
#Html.ActionLink("Check Availability", "Check", new { id = item.RoomID, AD = ArrivalDate.Date.ToString("dd-MM-yyyy"), DD = DepartureDate.Date.ToString("dd-MM-yyyy") }, null)
In my Controller I have
[RoutePrefix("RoomInfoes")]
[Route("Check/{ID},{AD},{DD}")]
[HttpPost]
public ActionResult Check(int? id, string AD, string DD) {
I have tried numerous arrangements of routes and views, but never can connect.
The code above returns a 404 with
Requested URL: /RoomInfoes/Check/1,06-11-2014,06-11-2014
Thanks
Before you use attribute routing make sure you have it enabled:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes(); // add this line in your route config
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
then decorate your action like this:
[Route("RoomInfoes/Check/{ID},{AD},{DD}")]
public ActionResult Test(int? id, string AD, string DD)
The RoutePrefix has been removed because it can be used only on class declaration (the code will even doesn't compile). I removed the HttpPost attribute because I assumed that you want make a GET instead of POST.
then to generate a link pointing to this action you can simply write:
#Html.ActionLink("test", "Test", "Home", new { id = 5, AD="58", DD = "58" }, null)
the result will be:
test (the commas in your url will be url encoded)
Do also have the Check Action method for serving HttpGet requests? If not, you will get 404 error.
Have you also done the routes.MapRoute in the RouteConfig.cs? This is required to render the correct URL with #Html.ActionLink helper method.
Try adding below code in RouteConfig.cs, if not already exists.
routes.MapRoute(
name: "RoomInfoes",
url: "Check/{ID},{AD},{DD}",
defaults: new
{
controller = "RoomInfoes",
action = "Check",
ID = UrlParameter.Optional,
AD = UrlParameter.Optional,
DD = UrlParameter.Optional
}
);
You don't Need Route and the RoutePrefix attribute on the Action method.
I want to create a URLs shortener website. URLs that I offer are like example.com/XXX where
XXX is the value of the short URL.
I want to have website on example.com and URLs are example.com/xxx. I want to get xxx from URL and redirect users to equivalent URLs in database.
How can implement this?
Create a new route in your RouteConfig for example:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("empty",
"{id}",
new {controller = "Home", action = "Index", id = UrlParameter.Optional}
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
And the simply go to your database with the id passed in the index
public ActionResult Index(int id)
{
//Do Stuff with db
return View();
}
asp.net mvc documentation here.
One way you be doing the needed redirection in the default controller action. By default in asp.net mvc it is home/index.
So in the index action you should be having such code
public ActionResult Index(string id)
{
var url = Db.GetNeededUrl(id);
return Redirect(url);
}
So now if the user enters such an address site.com/NewYear you'll get redirected to the equivalent url that is in you database.
I am creating a blog engine, and I need a custom route, like this:
localhost/blogname/posts/1
Where blogname should be handled by a BlogsController, and posts will be an action.
How would I define such a route?
I don't think you need to define {controller} in your Url if you define it as a constraint. I think this should work:
routes.MapRoute("Default",
"{action}/{id}",
new { controller = "Blogs", action = "Posts" },
new { controller = "Blogs"});
It might cause problems with other routes though, I'm not sure. If it doesn't work, David's answer of http://site.com/blogs/posts/id is the best way to go.
This feels like a weird approach. If you use the default routing in ASP.NET MVC, you would need one controller class per blog--not something you can easily create on the fly.
If you use the classname BlogsController, then the default routing would work for URLs of the form:
/Blogs/SomeAction/123
Maybe this is what you're looking for:
public class BlogsController : Controller
{
public ActionResult List()
{
return View(GetPostsOrSomething());
}
public ActionResult Posts(int id)
{
return View(new BlogViewModel(id));
}
[HttpPost]
public ActionResult Comment(int id, string comment)
{
// do comment
}
}
And your routing would need to look like this:
routes.MapRoute(
"Blogs", // Route name
"{blog}/{action}/{id}", // URL with parameters
new { controller = "Blogs", action = "List", id = UrlParameter.Optional }
);
Note
Bear in mind, this would match default style URLs, and everything might be routed to your BlogsController. Maybe you could consider a regular expression for the {blog} part of the pattern:
routes.MapRoute(
"Blogs", // Route name
"{blog}/{action}/{id}", // URL with parameters
new { controller = "Blogs", action = "List", id = UrlParameter.Optional },
new { blog = "(blogname1|blogname2|blogname3|etc)" }
);
But, this isn't very flexible either. Any time you added a blog to your site, this regular expression would require an update. I would probably reconsider your URL structure--something similar to the default style.
Something like this
routes.MapRoute(
"Blogs", // Route name
"{blogname}/{action}/{id}", // URL with parameters
new { controller = "Blog", action = "Posts", id = UrlParameter.Optional } // Parameter defaults
);
would work, meaning you could have your blog controller like this:
public class BlogController : Controller
{
public ActionResult Posts(string blogname, int id)
{
... get posts based on blog name and id and return view...
}
}
but then if you want a url like localhost/admin/dostuff/1 to go to an admin controller, how will MVC know that you don't just mean a 'blogname' called 'admin'?
You would need to do something like the regex matching that David suggests, or else specifically add a route for any other controllers you have before you add the Blog route
e.g.
routes.MapRoute(
"Admin Controller Routes", // Route name
"admin/{action}/{id}", // URL with parameters
new { controller = "Admin", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Account Controller Routes", // Route name
"account/{action}/{id}", // URL with parameters
new { controller = "Account", id = UrlParameter.Optional } // Parameter defaults
);
... etc - one for each controller ...
I found this approach to be best for my needs. Very simple, goal is to have the title of the blog as the parameter but also the URL (I didn't want a ? to set a parameter value, I have been told it is not helping SEO. Goal is MYURL.com/blog/my-blog-title
ASP.NET MVC
add to your RouteConfig.cs file
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "Blog",
url: "blog/{title}",
defaults: new { controller = "Blog", action = "GetBlog" },
constraints: new { title = #"[\w\-]*" }
);
Add a Controller and call it Blog and then add the following Action to that Controller
[Route("blog/{title}")]
public ActionResult GetBlog(string title)
{
// do what ever code you need to do here to get the blog from the title and pass a model to the view using return View(MyBlogObject)
return View();
}
I have this routes:
routes.MapRoute(
"Default",
"user/{userId}/{controller}/{action}",
new {controller = "Home", action = "Index" }
);
routes.MapRoute(
"Short",
"{controller}/{action}",
new { controller = "Home", action = "Index"}
);
My current location in browser:
http://my_site/user/197/UserEvents
On this page there are links:
#Html.ActionLink("Friends", "Index", "Friends")
#Html.ActionLink("Information", "Index", "UserInfo", new { userId = (string)null },null)
MVC re-use query parameters , so the first generated link:
my_site/user/197/Friends
The second link is generated:
my_site/UserInfo?userId=197
Why userId in the second link has a value of 197? Why not have a link:
my_site/UserInfo
I cannot pinpoint the exact location where MVC decides to reuse whatever route values it has at hand, but here's what I use in my projects:
//
// This fixes "ambient values" problem:
// http://stackoverflow.com/questions/2651675/asp-net-mvc-html-actionlink-maintains-route-values
// http://stackoverflow.com/questions/780643/asp-net-mvc-html-actionlink-keeping-route-value-i-dont-want
return new UrlHelper(
new RequestContext(
HttpContext.Current,
new RouteData {
Route = urlHelper.RequestContext.RouteData.Route,
RouteHandler = urlHelper.RequestContext.RouteData.RouteHandler
}), urlHelper.RouteCollection)
.Action(actionName, controllerName, routeValuesWithArea);
The key here is that neither RouteData.DataTokens nor RouteData.Values aren't set, so there's nothing MVC can possibly reuse.
I would probably do something like
http://foo.com/user/events/197
http://foo.com/user/events?userId=197
I find that the more I try to jive with ASP.NET routing conventions the more time I can send developing my app.
public class UserController : Controller
{
public ActionResult Events(long userId)
{
//Do Something...
}
}
public class FriendsController : Controller
{
public ActionResult Index(long userId)
{
//Do Something...
}
}