I have created a controller and I don't want my default Action or View to be named Index. I created Action in TopicsController as below
[ActionName("Index")]
public ActionResult Topics()
{
var topic = new Topic();
return View("Topics", topic.GetTopics());
}
and it mached to URL xyz.com/Topics.
I tried to apply same philosophy to another controller, named, ModulesController but now I have got parameter.
[ActionName("Index")]
public ActionResult Modules(string id)
{
var topic = new Topic();
return View("Modules", topic.GetTopics());
}
but now it is saying
The resource cannot be found.
what I can do so that this action matches URL like xyz.com/Modules/aaaa?
To access the Url xyz.com/Modules/aaaa change the Action name for the Modules action to aaaa like this:
[ActionName("aaaa")]
public ActionResult Modules(string id)
{
var topic = new Topic();
return View("Modules", topic.GetTopics());
}
FYI - It would be better to avoid naming each action with the ActionName filter. At some point it would become difficult to manage. Instead manage the routes in the RouteConfig like this:
routes.MapRoute(
name: "Modules",
url: "{controller}/{action}/{id}",
defaults: new { controller="Modules", action="Modules", id=UrlParameter.Optional }
);
The following Urls will work for the above route:
xyz.com/Modules/aaaa
xyz.com/Modules/aaaa/123
xyz.com/Modules/aaaa?id=123
Update:
If you want 'aaaa' to be the parameter and want to access the action with xyz.com/Modules/aaaa (where 'aaaa' will be bound as the value to the Id variable) then add the following Route to the route table:
routes.MapRoute(
name: "Modules",
url: "Modules/{id}",
defaults: new { controller="Modules", action="Modules", id=UrlParameter.Optional }
);
Note the value of the Url above.
Related
Fairly new to MVC, I would like the URLs of my article pages to be like this:-
http://www.example.com/article1
http://www.example.com/article2
http://www.example.com/article3
How can I set up the routing such that whenever someone types in the above it calls an action called article in the controller and passes the path to it?
I tried something like this but to no avail: -
routes.MapRoute(
name: "article",
url: "{article}",
defaults: new { controller = "Home", action = "article" }
);
One solution is to add multiple routes.
routes.MapRoute(
name: "article1",
url: "article1",
defaults: new { controller = "<YourControllerName>", action = "article1" }
);
routes.MapRoute(
name: "article2",
url: "article2",
defaults: new { controller = "<YourControllerName>", action = "article2" }
);
Edit:
From OP's comment, it is understood that there would be 'n' number of articles(urls). To deal with that, we can create a custom route handler.
Step 1: Create a new custom route handler inheriting from MvcRouteHandler
public class CustomRouteHandler : MvcRouteHandler
{
protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
{
var controller = requestContext.RouteData.Values["controller"].ToString();
requestContext.RouteData.Values["controller"] = "Home";
requestContext.RouteData.Values["action"] = "Index";
requestContext.RouteData.Values["articleId"] = controller;
return base.GetHttpHandler(requestContext);
}
}
Step 2: Register the new route. Make sure to add this route before default route.
routes.Add("Article", new Route("{controller}", new CustomRouteHandler()));
In the given CustomRouteHandler class, the Controller and Action is hard coded with "Home" and "Index" respectively. You can change that to your own controller and action name. Also you would see a "articleId" setting to RouteData.Values. With that setting, you would get the articleId as a parameter in your Action method.
public ActionResult Index(string articleId)
{
return View();
}
After all the changes, for the url http://www.example.com/article1, the Index() method of HomeController gets invoked with articleId set to 'article1'.
Similarly for http://www.example.com/article2, the Index() method gets invoked with parameter articleId set to 'article2'.
I have a controller named Blog.
I have an action like this:
[Route("{code:int}/{title?}")]
public virtual ActionResult Index(int code, string title)
{
var postModel = _blogService.Get(code.ToUrlDecription());
return View(postModel);
}
I entered these urls, but all of them returned not found:
localhost:7708/Blog/index/12/post-title;
localhost:7708/Blog/index/12;
localhost:7708/Blog/12/post-title.
I tried to write a route like below, but the result was the same:
routes.MapRoute(
name: "showblogpost", url: "{controller}/{action}/{code}/{title}",
defaults: new {
controller = "Blog",
action = "Index",
title = UrlParameter.Optional
},
namespaces:new string[] { "Web.Controllers" }
);
One thing, you don't need to use both attribute [Route] on action and mapping route.
In your attribute [Route] you have specified only parameters, so route according to it should be localhost:7708/12
by route, specified in MapRoute it should be localhost:7708/showblogpost/12
What I suggest is - remove your attribute, name your route in MapRoute as you want to see in URL, and also you can remove "string title" parameter from action, as it's not used.
I faced with the following problem. I have an url and I would like to check whether the url could be mapped to any route defined in my RouteConfig or not. In other words I need a right way to determine whether the url is correct for my application or not.
Maybe anyone knows how to do it?
For Example : Student is my contoller and having action method StudentList then I need to write following code in RouteConfig.cs file.
StudentContoller.cs
public List<Student> StudentList (StudentModel model)
{
/* Logic for Student List */
return View(model);
}
RouteConfig.cs
routes.MapRoute(
name: "StudentList",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Student", action ="StudentList", id = UrlParameter.Optional }
);
I have an action in controller like:
public ActionResult Index(string ssn)
{
}
and default route values: {controller}/{action}/{id}
I don't want use url like /Home/Index?ssn=1234. I want use like /Home/Index/1234.
But I also don't want to add new route values for ssn parameter (or custom model binder).
Is there some complete attribute, like [ActionName] but for parameters?
Something like this:
public ActionResult Index([ParameterBinding("id")] string ssn)
{
}
As Darin & Rumi mentioned - there are no built-in attributes, however you can achieve the same affect (across multiple controllers/actions) with a single new Route using the RouteCollection.MapRoute constraints parameter on a single route.
The following route config will apply the "SSN" route to the Foo or Bar controller, any other controller will go through the Default route.
routes.MapRoute(
name: "SSN",
url: "{controller}/{action}/{ssn}",
defaults: new { controller = "Foo", action = "Index" },
constraints: new { controller = "(Foo|Bar)", action = "Index" }
);
// default route
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Edit: Alternatively you could use the ActionParameterAlias library which seems to support what you initially requested.
ASP.NET MVC routes have names when mapped:
routes.MapRoute(
"Debug", // Route name -- how can I use this later????
"debug/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = string.Empty } );
Is there a way to get the route name, e.g. "Debug" in the above example? I'd like to access it in the controller's OnActionExecuting so that I can set up stuff in the ViewData when debugging, for example, by prefixing a URL with /debug/...
The route name is not stored in the route unfortunately. It is just used internally in MVC as a key in a collection. I think this is something you can still use when creating links with HtmlHelper.RouteLink for example (maybe somewhere else too, no idea).
Anyway, I needed that too and here is what I did:
public static class RouteCollectionExtensions
{
public static Route MapRouteWithName(this RouteCollection routes,
string name, string url, object defaults, object constraints)
{
Route route = routes.MapRoute(name, url, defaults, constraints);
route.DataTokens = new RouteValueDictionary();
route.DataTokens.Add("RouteName", name);
return route;
}
}
So I could register a route like this:
routes.MapRouteWithName(
"myRouteName",
"{controller}/{action}/{username}",
new { controller = "Home", action = "List" }
);
In my Controller action, I can access the route name with:
RouteData.DataTokens["RouteName"]
If using the standard MapRoute setting like below:
routes.MapRoute( name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
...this will work in the view...
var routeName = Url.RequestContext.RouteData.Values["action"].ToString();
You could pass route name through route values using default value of additional parameter:
routes.MapRoute(
name: "MyRoute",
url: "{controller}/{action}/{id}",
defaults: new { routeName = "MyRoute", controller = "Home", action = "Index", id=UrlParameter.Optional }
);
Then, it is possible to get passed value from controller context:
string routeName = ControllerContext.RouteData.Values["routeName"].ToString();
This does not directly answer the question (if you want to be pedantic); however, the real objective seems to be to get a route's base URL, given a route name. So, this is how I did it:
My route was defined in RouteConfig.cs as:
routes.MapRoute(
name: "MyRoute",
url: "Cont/Act/{blabla}",
defaults: new { controller = "Cont", action = "Act"}
);
And to get the route's base URL:
var myRoute = Url.RouteUrl("MyRoute", new { blabla = "blabla" }).Replace("blabla", "");
It gave me the route's base URL that I wanted:
/Cont/Act/
Hope this helps.
An alternative solution could be to use solution configurations:
protected override OnActionExecuting()
{
#if DEBUG
// set up stuff in the ViewData
#endif
// continue
}
There shouldn't really ever be a need to reference the route name like this - which I suppose is why MVC makes it so difficult to do this sort of thing.
another option - use MapRoute with string[] namespaces argument, then you can see your namespaces as RouteData.DataTokens["Namespaces"]