I have an angular application, which i have split into 2, because of functionality. For here, we will call the apps Default and Admin.
In my ASP.NET MVC Website, i have this route defined, which will catch all URLs and load the Home/Index.cshtml view.
// Mvc routes
app.UseMvc(builder =>
{
// default goes to Home, and angular will deal with client side routing
builder.MapRoute(
name: "default",
template: "{*url}",
defaults: new { controller = "home", action = "index" });
});
Now if the user goes to a URL that contains the word admin (eg. www.mysite.com/admin or www.mysite.com/admin/something) then i would like to return my Admin/Index.cshtml view.
To accompolish this, i have added my AdminController as so
[Authorize]
public class AdminController : Controller
{
[Route("~/Admin/{id?}")]
public IActionResult Index()
{
return View();
}
}
But if i try and load a url with more than 2 parameters, such as www.mysite.com/admin/page/12 my Home/Index.cshtml is being returned.
How can i get my Admin view to be returned if the word Admin is after the domain name, no matter how many parameters are in the URL??
Change your code like below:
routes.MapRoute(
name: "spa-fallback-admin",
template: "admin/{*url}",
defaults: new { controller = "Admin", action = "Index" });
routes.MapRoute(
name: "spa-fallback",
template: "{*url}",
defaults: new { controller = "Home", action = "Index" });
[Route("~/Admin/{id?}")] just can't catch www.mysite.com/admin/page/12, so it moves on to default route. You should either pass your parameters via query string, or add different actions for each parameter combination.
[Route("~/Admin/")]
public IActionResult Index(int? id, int page){}
So you can use www.mysite.com/admin/?id=1&page=12
Related
In asp.net MVC the "homepage" (ie the route that displays when hitting www.foo.com) is set to Home/Index .
Where is this value stored?
How can I change the "homepage"?
Is there anything more elegant than using RedirectToRoute() in the Index action of the home controller?
I tried grepping for Home/Index in my project and couldn't find a reference, nor could I see anything in IIS (6). I looked at the default.aspx page in the root, but that didn't seem to do anything relevent.
Thanks
Look at the Default.aspx/Default.aspx.cs and the Global.asax.cs
You can set up a default route:
routes.MapRoute(
"Default", // Route name
"", // URL with parameters
new { controller = "Home", action = "Index"} // Parameter defaults
);
Just change the Controller/Action names to your desired default. That should be the last route in the Routing Table.
ASP.NET Core
Routing is configured in the Configure method of the Startup class. To set the "homepage" simply add the following. This will cause users to be routed to the controller and action defined in the MapRoute method when/if they navigate to your site’s base URL, i.e., yoursite.com will route users to yoursite.com/foo/index:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=FooController}/{action=Index}/{id?}");
});
Pre-ASP.NET Core
Use the RegisterRoutes method located in either App_Start/RouteConfig.cs (MVC 3 and 4) or Global.asax.cs (MVC 1 and 2) as shown below. This will cause users to be routed to the controller and action defined in the MapRoute method if they navigate to your site’s base URL, i.e., yoursite.com will route the user to yoursite.com/foo/index:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// Here I have created a custom "Default" route that will route users to the "YourAction" method within the "FooController" controller.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "FooController", action = "Index", id = UrlParameter.Optional }
);
}
Step 1: Click on Global.asax File in your Solution.
Step 2: Then Go to Definition of
RouteConfig.RegisterRoutes(RouteTable.Routes);
Step 3: Change Controller Name and View Name
public class RouteConfig
{
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 }
);
}
}
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Your Controller", action = "Your Action", id = UrlParameter.Optional }
);
}
}
Attribute Routing in MVC 5
Before MVC 5 you could map URLs to specific actions and controllers by calling routes.MapRoute(...) in the RouteConfig.cs file. This is where the url for the homepage is stored (Home/Index). However if you modify the default route as shown below,
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
keep in mind that this will affect the URLs of other actions and controllers. For example, if you had a controller class named ExampleController and an action method inside of it called DoSomething, then the expected default url ExampleController/DoSomething will no longer work because the default route was changed.
A workaround for this is to not mess with the default route and create new routes in the RouteConfig.cs file for other actions and controllers like so,
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Example",
url: "hey/now",
defaults: new { controller = "Example", action = "DoSomething", id = UrlParameter.Optional }
);
Now the DoSomething action of the ExampleController class will be mapped to the url hey/now. But this can get tedious to do for every time you want to define routes for different actions. So in MVC 5 you can now add attributes to match urls to actions like so,
public class HomeController : Controller
{
// url is now 'index/' instead of 'home/index'
[Route("index")]
public ActionResult Index()
{
return View();
}
// url is now 'create/new' instead of 'home/create'
[Route("create/new")]
public ActionResult Create()
{
return View();
}
}
check RegisterRoutes method in global.asax.cs - it's the default place for route configuration...
I tried the answer but it didn't worked for me. This is what i ended up doing:
Create a new controller DefaultController. In index action, i wrote one line redirect:
return Redirect("~/Default.aspx")
In RouteConfig.cs, change controller="Default" for the route.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Default", action = "Index", id = UrlParameter.Optional }
);
If you don't want to change the router, just go to the HomeController
and change MyNewViewHere in the index like this:
public ActionResult Index()
{
return View("MyNewViewHere");
}
I have a bunch of mostly-static pages (about 40),
like: order-form01.html, order-form02.html, orderform03.html etc..
Should each of them have its own Controller/Action, or is that possible to have one dynamic Controller/Action for all of them?
My Url should look like this: http://MyProject/GlobalController/IndividualView and for the above example: http://MyProject/OrderForm/order-form01, http://MyProject/OrderForm/order-form02 etc..
Thanks in advance.
Yes it's very easy AND you don't need a switch statement or any other redundant logic.
public class MyController
{
public ActionResult Page(string file)
{
return View(file);
}
}
The magic is in the Route Map:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// New MapRoute for your 40+ files..
routes.MapRoute(
"OrdeForm",
"OrderForm/{file}",
new { controller = "MyController", action = "Page", {file} = "" }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
}
Additionally:
I pass the View name in the query string.
Is not required, but is supported. The following urls will work:
// Url Parameters
http://MyProject/OrderForm/order-form01
http://MyProject/OrderForm/order-form02
// Querystring Parameters
http://MyProject/OrderForm?file=order-form01
http://MyProject/OrderForm?file=order-form02
The only catch is that you need to rename your html files to cshtml and place them in the correct directory for the ViewEngine to find.
#Erik, I also bit of new to mvc . Could you please explain your route map as of how is it possible with default raute again and again
Routes are broken down into 3 values:
Controller
Action
Parameter(s)
At a bare minimum, the controller and action are required. Where the values come from is not dependent on the Url. For example, in the following Url and Map Route...
// Url
http://MyProject/
// MapRoute
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = "" }
);
// Controller named "Home" matches the default in the above route
// Method named "Index" matches the default in the above route
public class HomeController {
public ActionResult Index() {
return new EmptyResult();
}
}
... everything still works because we provided a default value for the controller and action.
Ok let's break down the URL you want:
http://MyProject/OrderForm/order-form01
http://MyProject/OrderForm/order-form02
http://MyProject/<identifier>/{parameter}
You have one identifier that tells me route (OrderForm) and one changing value that because it changes and you want one value, should be a parameter.
http://MyProject/<identifier>/{file}
The name of the parameter makes no difference as long as it matches the signature of the controller method:
http://MyProject/{Controller}/{file}
public class HomeController {
public ActionResult Index(string file) {
return new EmptyResult();
}
}
or
http://MyProject/{Controller}/{einstein}
public class HomeController {
public ActionResult Index(string einstein) {
return new EmptyResult();
}
}
I named the parameter file, because it tells me it's the parameter is a name of a file, whereas the name einstein has no inherent description so is a terrible name for a variable.
http://MyProject/{Controller}/{file}
// MapRoute
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = "" }
);
// Controller named "Home" matches the default in the above route
// Method named "Index" matches the default in the above route
public class HomeController {
public ActionResult Index() {
return new EmptyResult();
}
}
Now we only want this route to run when the identifier is OrderForm so we don't allow that to be a value, we hard code it.
url: "OrderForm/...
Next we have a value that keeps changing, so we to add url parameter:
url: "OrderForm/{file}"
Now we have an issue because we aren't allowing MVC to parse values from the url to populate Controller nor Action so we must supply them.
routes.MapRoute(
name: "",
url: "OrderForm/{file}",
defaults: new { controller = "Home", action = "Index", file = "" }
);
Here we've mapped the url http://MyProject/OrderForm/{file} to:
public class HomeController {
public ActionResult Index(string file) {
return new EmptyResult();
}
}
Now I would choose to to update the defaults to something more specific and descriptive:
routes.MapRoute(
name: "",
url: "OrderForm/{file}",
defaults: new { controller = "OrderForm", action = "Index", file = "" }
);
public class OrderFormController {
public ActionResult Index(string file) {
return new EmptyResult();
}
}
Hope that all makes sense.
After the question edited :my solution is, you can have one controller/action and it should call view (cshtml). Your querystring data should be pass to view as of viewbag variable and partial views should be called acording to the viewbag variable. noo need of editing routing table even(if you are willing to pass it as a query string).
//your routeconfig will be
routes.MapRoute(
name: "default",
url: "{controller}/{file}",
defaults: new { controller = "OrderForm", action = "Index", file = "" }
);
//here no need to have 40 routing table one is enough
//your controller/action will be
public class OrderForm
{
public ActionResult Index(string file)
{
ViewBag.Orderform=file
return View(file);
}
}
//view bag variable is accessible in view as well as in javascript
But I would say as best practice, you can modify default routing to access all urls and navigate it to same controller/action and let that action to return the view. After that use angular / knockout js to handle client side routing and based on it the partial views should be loaded.(still your url will be different for your 40 pages but noo need to pass it as query string)
//your route table will be
routes.MapRoute(
name: "default",
url: "{controller}/{file}",
defaults: new { controller = "OrderForm", action = "Index"}
);
//your controller will be
public class OrderForm
{
public ActionResult Index()
{
return View(file);
}
Navigation should be handled by client side routing
I was referencing this question to try and get this done, but it only works for my index method and I am not sure why.
My project has one area in it (if that is relevent) and I have about 5 different views that I want to hide /home/ in the url.
Code:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"JobResults", // Route name
"JobSearch/{title}-{id}", // URL with parameters
new { controller = "JobSearch", action = "Job" }, // Parameter defaults
new[] { "inkScroll.Web.Controllers" }
);
routes.MapRoute("home", "{action}",
new { controller = "Home", action = "index" });
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new
{
controller = "^(account|common|base|jobsearch)$", //every controller goes in here
action = "Index",
id = UrlParameter.Optional
},
new[] { "inkScroll.Web.Controllers" }
);
I am solving the same problem with the help of Attribute based Routing feature of ASP.NET MVC 5. Say, I have an action named ContactUs in my Home Controller as follows:
public ActionResult ContactUs()
{
return View();
}
I used to get Url for ContactUs as /Home/ContactUs. But, I wanted it to be simply /ContactUs. So, I am decorting the ContactUs action with Route Attribute as follows:
[Route("ContactUs")]
public ActionResult ContactUs()
{
}
So, this is working perfectly for me. Therefore, if you are using ASP.NET MVC 5, I would say, utilize this excellent feature of MVC5. It will not only save you from separating Route Logic and Actions, but also, it solves many problems very easily.
If ASP.NET MVC5 is not an option for you, or if you dont want to use Route Attribute on Action Methods, then, perhaps the following route can work: ( I did not test it though)
routes.MapRoute("Default", "",
new { controller = "Home", action = "index" });
This page contains helpful resource about Attribute Routing: http://blogs.msdn.com/b/webdev/archive/2013/10/17/attribute-routing-in-asp-net-mvc-5.aspx
Catch all wildcard route as the last one would work
routes.MapRoute("home2", "{*path}",
new { controller = "Home", action = "index" });
In my MVC application, when user goes to www.MyDomain.com/Home, this request is processed in HomeController class Index method due to following routing entry in Global.asax
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
Let's say if user goes to www.MyDomain.com/SomeParameters, I want this request to be processed in MyController class Index method. An example for the parameters will be www.MyDomain.com/John. For this I have created following entry in Global.asax but it does not seem to get hit. Can anyone point out what I am doing wrong here?
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "MyController", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
The routing handles John as the controller, not the action. So in your example John is the controller and because you don't provide an action, it takes Index as the default action.
If you want www.MyDomain.com/John to be routed to controller MyController, action Index and a parameter that contains John, a solution could be to add the following route (before the default route):
routes.MapRoute(
name: "MyController",
url: "{myparameter}",
defaults: new { Controller = "MyController", Action = "Index" });
And the controller:
public ActionResult Index(string myparameter)
{
return View("whatever");
}
This will lead www.MyDomain.com/John to the Index action with myparameter = "John".
ps. In the example myparameter is mandatory.
In order to have www.MyDomain.com/SomeParameters you simply need to create a route where the Controller and the Action method are defaulted since they will not be provided in the URL.
Make sure the route definition only includes the someparameters and does not have anything else. This way you can just treat anything in the URL after / as a parameter.
routes.MapRoute(
name: "MyController",
url: "{someparameters}",
defaults: new { Controller = "MyController", Action = "Index" });
public ActionResult Index(string someparameters)
{
...
return View();
}
I am working with ASP.NET MVC 4 and am attempting to write a really basic route, but it's not working and getting very frustrated with it!
I want the URL http://www.mywebsite.com/my-page to trigger the controller called Page and the action method Index.
I have no other route setup apart from this:
RouteTable.Routes.MapRoute(
name: "Default",
url: "my-page",
defaults: new { controller = "Page", action = "Index" }
);
Is there something incorrect with my setup or where am I going wrong?
The error I get is:
The controller for path '/my-page' was not found or does not implement IController.
Main problem is you are trying to override the default route. In MVC4, the routes are defined in App_Start/RouteConfig.cs. The "Default" route should be the LAST route:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Then, for your specific route, use the following BEFORE the default route:
routes.MapRoute(
name: "MyPage",
url: "my-page",
defaults: new { controller = "Page", action = "Index" }
);
Fianlly, ensure you have a controller PageController.cs with an action Index and a View Views/Page/Index.cshtml:
public class PageController : Controller
{
public ActionResult Index()
{
return View();
}
}