I'm building my first Asp.Net MVC2 Site, and i'm now trying to add an /Admin area to the site.
I don't want this area to be visibile to the main set of users so will only be accessible when you enter http://Intranet/Admin
What I have is a NewsController for my regular users but I also want an Admin NewsController and I'm not sure how to setup the Class hierarchy and folders so that when I add the Views they are in the correct location.
Inside my Global.Asax.cs I've added and the routes resolve correctly.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
new string[] { "Intranet.Controllers" }
);
routes.MapRoute(
"Admin", // Route name
"Admin/{controller}/{action}/{id}", // URL with parameters
new { controller = "Admin", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
new string[] { "Intranet.Controllers.Admin" }
);
And in the folder hierarchy I've setup
Views/
Admin/
News/
...I want the new view to go here...
In the Controllers
Controllers/
Admin/
AdminController.cs
NewsController.cs (this is the one i want for administration)
NewsController.cs (this is the regular one for viewing the list, specific item etc)
The problem I face is when I go into the admin/NewsController.cs on Index and Add View it tries to create it at the /News/Index.aspx rather than /Admin/News/Index.aspx.
This is the code for my admin news controller Controllers/Admin->Add->Controller
namespace Intranet.Controllers.Admin
{
public class NewsController : Controller
{
public ActionResult Index()
{
return View();
}
}
}
Is there something I'm doing incorrectly, or what should I change so that when I add the views they are being created in the /Admin/{area} directory.
Since you're using MVC2, the easiest way to solve this is the create an actual MVC "Area" for your Admin section. Right now you're doing everything in the default section and just using an Admin folder. If you create an Admin area (under the well-known location Areas) folder, then you'll have an AdminAreaRegistration - where is where you'll configure your Admin routes. Because you'll do this as part of the Area, then the first segment of the URL "/Admin" will be used for the "area" token. This will disambiguate which controller to use and correctly pick up the controller you want. So you're folder structure will be:
/Areas
/Admin
/Controllers
NewsController.cs
etc.
When you try to create a View for the existing Controller Action it always create on the root folder of the Views. The default route for the View is always pointing to the root of the Views folder.
For example:
Controllers
Admin
AdminController.cs
HomeController.cs
HomeController.cs
In that hierarchy, both of the HomeController inside Admin and root shares the same Views in the Views Folder.
Views
Home
Index.aspx
Unless you return a specified View() in all of the ActionResults in your HomeController inside the Admin Folder of your Controllers. It will map to a certain View.
Example, ActionResult inside the HomeController.cs of Admin folder in Controllers.
namespace Intranet.Controllers.Admin
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View("Home/Index");
}
}
}
This will be mapped in the Views folder like this
Views
Admin
Home
Index.aspx
But if you do not specify the View path when you return a View in your ActionResult it will map to the default location of the Views which is like this.
Views
Home
Index.aspx
The reason for this is that even though you specify the routes in the Global.asax, that is only to map to which controller the url should point, not the Views folder.
When you right click and Create View on ActionResult of any Sublevels of the Controllers, it always create on the root of the Views folder to its corresponding Controller.
Related
I am new to Area term in MVC and I want to use it. I have the following directories that points to the controller in Area.
Areas > Admin > Controllers > AdminController
When I want to visit the Index Action of AdminController, I need to visit http://localhost/Admin/Admin. I want to get rid of the second "Admin". I want to type http://localhost/Admin/ only. How can I do that?
AdminAreaRegistration.cs has the following MapRoute
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Admin_default",
"Admin/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
You have not specified a default value for the controller so unless you include it in the url, the routing engine has no way it identify which controller you want to navigate to. You can solve this by giving a default value for the controller name
context.MapRoute(
"Admin_default",
"Admin/{controller}/{action}/{id}",
new { controller = "Admin", action = "Index", id = UrlParameter.Optional }
);
While that means that ../Admin will navigate to the Index() method of AdminController, it still means that if you want to navigate to another method in AdminController, your url will need to be ../Admin/Admin/AnotherMethod which is probably not what you want.
The purpose of areas is to logically group your controllers and methods. For example a shopping cart app might have a ProductsController where users might navigate to ../Product to display a list of products or ../Product/Details/1 to display details of a product. But the app might need other methods for suppliers to create and edit their products so you would create a separate Suppliers area where ../Suppliers/Products would navigate to their list of products, and ../Suppliers/Products/Edit/1 would allow them to update details of their product.
Having a AdminController in a Admin area does not really make sense, and I suggest that it should be HomeController if it contains general methods associated with admin tasks (and the route definition would then be new { controller = "Home", .. }
I am trying to create seo friendly url.
current url:
http://www.example.com/Product/free-mobile-images/Mobile
expected ouput:
http://www.example.com/Product/free-mobile-images/
I am using id to fetch moblie data from database.
ActionMethod
public ActionResult Product(string seotext, string id)
{
return View();
}
Route.config
routes.MapRoute(
"Product",
"Product/{seotext}/{id}",
new { controller = "Home", action = "Product" });
I tried to remove moblie from the route value:
RouteData.Values.Remove("id");
RouteData.Values.Remove("Mobile");
But still I get /Mobile at the end of url.
May I know what wrong I am doing, any help would be great.
Why don't you just create a folder structure to mimic the path you want and then call your file Index.aspx, it will have the same effect but is much simpler.
Eg folder called Product, then inside that a folder called free-mobile-images and then your file called index.aspx
I am working on an app with ASP.NET MVC 5. I want my app to have a route that looks like the following:
http://www.myserver.com/my-category
Please notice how the route has a dash (-) in it. I currently have a controller named MyCategoryController. It is defined like this:
namespace MyApp.Controllers
{
[RoutePrefix("my-category")]
public class MyCategoryController : Controller
{
// GET: List
public ActionResult Index()
{
return View();
}
}
}
The view is located in /Views/My-Category/Index.cshtml. When I try to access http://www.myserver.com/my-category in the browser, I get an error that says:
The resource cannot be found.
I set a breakpoint and I noticed that the breakpoint is not hit. I then enter http://www.myserver.com/mycategory into the browser, and I get an error that says:
The view 'Index' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/mycategory/Index.cshtml
~/Views/mycategory/Index.vbhtml
~/Views/Shared/Index.cshtml
~/Views/Shared/Index.vbhtml
How do I setup my ASP.NET MVC so that
a) I can visit http://www.myserver.com/my-category and
b) Load the view from /Views/my-category/Index.cshtml
You need to name the views folder like the controller not like the route.
So /Views/MyCategory/Index.cshtml and not /Views/My-Category/Index.cshtml.
If you, for a reason I can't imagine why, want it to be /Views/My-Category/Index.cshtml you need to "fully quallify the view":
return View("~/Views/My-Category/Index.cshtml");
About the route with the dash: I am not using attribute based routing so I can only guess:
Did you add the routes.MapMvcAttributeRoutes(); in your RegisterRoutes method?
Because http://www.myserver.com/mycategory is routed by the default "{controller}/{action}/{id}" route...
I'd like to hide requests for several controllers 'create' action in a common url. The controllers all are in a sub-folder in the Controllers directory:
Controllers \ mydirectory \ controller1
\ controller2
I've tried it this way
routes.MapRoute(
name: "controller1Create",
url: "buy",
defaults: new { controller = "controller1", action = "Create" }
);
and have changed controller1 to
../mydirectory/controller1
/controller1
But anytime I go to the create action, the url remains the same .. .com/controller1/create
How to do that right? Thank you for your help!
First, creating a folder for these controllers won't actually do what you want. ASP.NET MVC doesn't care about where your controllers are, it will scan the assembly and all controllers will behave like they are in the root.
If you put a controller named Controller1 in Controllers/MyDirectory. It will still be reachable from /Controller1 URL and MyDirectory/Controller1 will fail.
What you need is an area. You have to create an area for these controllers put them inside its own Controllers folder.
Then you can use an area route like this in AreaRegistration class:
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"MyArea_default",
"MyDirectory/{controller}/{action}/{id}",
new { action = "Create", id = UrlParameter.Optional }
);
}
I have placed all my admin controllers inside an Admin folder in Controller folder. Since one of my admin controller matches the name of another controller in Controller folder, I am getting the following error.
Multiple types were found that match the controller named 'Product'. This can happen if the route that services this request ('{controller}/{action}/{id}') does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter.
I tried adding the following route, but still the problem is same
routes.MapRoute(
"", //Route name
"Admin/{controller}/{action}/{id}", // Url with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional });
How can i get rid of this error. Changing the name of controller is the last option on my mind. Right now, I am looking for a way to preserve the name and see if i can find another way around this.
I have placed all my admin controllers inside an Admin folder in Controller folder
Well, that's your problem. How do you expect the default controller factory to know which controller you want to be instantiated given the following request /admin/index (the one in the Controllers folder or the on in the Controllers/Admin folder)? Remember that the default controller factory searches for types in the loaded assemblies that derive from Controller. It doesn't really care in which folder they were declared. So when it finds that you have 2 controllers with the same name it doesn't know which one to pick.
One possibility is to use Areas. Then you could specify namespaces when registering the route:
routes.MapRoute(
"",
"Admin/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "AppName.Areas.Admin.Controllers" }
);
Also in your Global.asax make sure that you specify the namespace for the non-area controllers:
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "AppName.Controllers" }
);