I am stuck in simple problem and i am not sure how to solve this.
The view Category or its master was not found or no view engine supports the searched locations. The following locations were
searched:
~/Views/ShoppingCart/Category.aspx
~/Views/ShoppingCart/Category.ascx
~/Views/Shared/Category.aspx
~/Views/Shared/Category.ascx
~/Views/ShoppingCart/Category.cshtml
~/Views/ShoppingCart/Category.vbhtml
~/Views/Shared/Category.cshtml
~/Views/Shared/Category.vbhtml
I have a area called ShoppingCartArea and i have view (Category.cshtml) and controller inside it. But i am not sure how it is referencing to main view folder.
Global.asax
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "ShoppingCart", action = "Category", id = UrlParameter.Optional }, // Parameter defaults
);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
and my area registration.cs
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"ShoppingCartArea_default",
"ShoppingCartArea/{controller}/{action}/{id}",
new { controller = "ShoppingCart", action = "Category", id = UrlParameter.Optional },
new[] { ShoppingCartAppMVC.Areas.ShoppingCartArea.Controllers}
);
}
Lemme know if am doing something wrong
Probably, you ran into this because you have added your areas manually. Recently I have been rebuilding old WebForms applications and slowly transforming it into MVC. I have not added MVC type to a project and just added needed folders etc. Unfortunatelly, I`ve faced the same issue as you.
The answer was to add correct project type (see this answer) and add areas from the
context menu of the project. After that I`ve moved everything to a newly created area - and it worked.
So the answer is that MVC not only creates all the folders, but also updates its routes.
Related
This post is directly related to: MVC5 Area not working
That post fixed the index.cshtml issue, however it did not resolve each view for that controller. For example:
http://localhost:45970/Setup/Start gives the error that the resource cannot be found (basically a 404).
However http://localhost:45970/Setup/Setup/Start brings up the correct page.
So what needs to be reconfigured so that ALL views for that controller in the Setup Area will open properly?
Edit 1
Code from SetupAreaRegistration.cs
using System.Web.Mvc;
namespace BlocqueStore_Web.Areas.Setup
{
public class SetupAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Setup";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
name: "Setup_default",
url: "Setup/{controller}/{action}/{id}",
defaults: new { action = "Index", controller = "Setup", id = UrlParameter.Optional },
namespaces: new[] { "BlocqueStore_Web.Areas.Setup.Controllers" }
);
}
}
}
Since you have an Area named Setup with the above route configuration, opening http://localhost:45970/Setup/Start will execute StartController under Setup Area. You got 404 error because you don't have StartController under Setup Area, but you can open http://localhost:45970/Setup/Setup/Start successfully because you have SetupController and Start action method under Setup Area.
Based on your comment, you want the following url patterns
http://{host}/Setup/{view}
http://{host}/Admin/{view}
You can accomplish that without using any Area. You only need AdminController and SetupController using the default route.
When I try to make a new view in an area in MVC 6 it only displays a white page. The Home/Index action works fine, and this one will hit the controller but never displays the view. I can return content and get a display, but when I try to return the view it breaks. Any advice?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc;
using PmData.Models;
// For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
namespace PlantManagement.Areas.Cms.Controllers
{
[Area("Cms")]
public class AssetsController : Controller
{
// GET: /<controller>/
public IActionResult Index()
{
return View();
}
}
}
that is coupled with a blank view that calls to the main layout page.
I found the issue. Sadly, it's because I'm so new to MVC 6 / vNext so I feel silly. It was a matter of their being an issue with an item on the page, but without app.UseDeveloperExceptionPage(); being added in the configure of startup.cs it would never show me the actual error, just give me the generic 500 error and white page. Once I added that it started producing errors I could work with and gave me what I needed.
I had a similar issue, and resolved it by,
a) Create a _ViewStart.cshtml file in each area you have. i.e. Areas/Cms/Views/_ViewStart.cshtml
b) In this _ViewStart.cshtml file add
#{
Layout = "~/Areas/Cms/Views/Shared/_LayoutCms.cshtml
}
c) Add a _LayoutCms.cshtml to Areas/Cms/Views/Shared
d) In this file add the reference to the overall site layout
#{
Layout = "~/Views/Shared/_Layout.cshtml
}
and any other area specific layout code.
That fixed my blank page issue. Hopefully yours too
In addition to my last answer, try these steps
e) Make sure you have an area registration setup within your Cms area folder i.e Areas/Cms/CmsAreaRegistration.cs
public class CmsAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Cms";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Cms_default",
"Cms/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
}
f) In your App_Start/RouteConfig.cs make sure you are registering all areas by adding AreaRegistration.RegisterAllAreas() something like the following.
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
AreaRegistration.RegisterAllAreas(); //Add this//
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
My MVC application is set up with controllers at the root/global level. These have no explicit Area. I also have a single "Admin" area. URLs that begin with /admin/ are routed to the matching controller in the Admin area. Other URLs are routed to the matching global controller. This is working fine for the most part.
The issue I'm having is that in the case when a URL matches a controller in the Admin area when one of the same name doesn't exist on the global area, the request is incorrectly routed to the controller in Admin area. I know this is happening because I put a breakpoint on the matching action in the relevant controller.
For example, I have a controller called CalendarController in the Admin area. When I visit /admin/calendar, it works because it finds the action and the corresponding view in Areas/Admin/Views/Calendar/Index.cshtml. The problem occurs when I visit /calendar. I do not have a controller named Calendar at the root level, but for some reason it routes the request to the Admin area's CalendarController, which I don't want. I want it to return a 404 because no CalendarController exists at the root level. Instead, I get an error because it's searching for the view at the root level (at /Views/Calendar/Index.cshtml) even though the matching controller was in the Admin area.
How can I prevent the Admin area from being searched for matching controllers except when the URL has /admin in it?
Here's the relevant route code, which is basically stock except for the namespaces addition. The issue still happens without the namespace. There are more routes in the actual application, but I'm getting the same behavior in a brand new MVC project.
public class AdminAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Admin";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Admin_default",
"Admin/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional },
new[] { "AreaProblem.Areas.Admin.Controllers" }
);
}
}
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
What I mean by a controller at the "root level" is Controllers/HomeController in this screenshot. I want URLs that don't start with /admin to only look at those controllers. The problem is that it's also searching in Areas/Admin/Controllers.
So the MVC routing engine will look in different namespaces to try and find a matching controller. You can solve this by specifying a namespace (like you did for the admin area). You can also specify that a route not search other namespaces using DataTokens.
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new [] { "AreaProblem.Controllers" }
).DataTokens["UseNamespaceFallback"] = false;
I'm having difficulties with my controllers that are in an Area answering requests on routes that aren't for the area. So I have a setup like this (Extra stuff cut):
/Areas/Security/Controllers/MembersController.cs
/Areas/Security/SecurityAreaRegistration.cs
/Controllers/HomeController.cs
I have my area for security defined:
namespace MyApp.Web.Areas.Security
{
public class SecurityAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Security";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Security_default",
"Security/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
}
}
And my global routing rules:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{*robotstxt}", new { robotstxt = #"(.*/)?robots.txt(/.*)?" });
routes.IgnoreRoute("{*favicon}", new { favicon = #"(.*/)?favicon.ico(/.*)?" });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new string[] { "MyApp.Web.Controllers" }
);
In my global asax I'm doing quite a few things but the relevant part is that I call AreaRegistration.RegisterAllAreas(); then I call the routing function that does the above.
But my problem is that requests for "/Members/" are hitting my Members controller using my "Default" route... even though the controller's not in the namespace I specified. Then when it tries to run it can't find it's Views cause they're defined in the Area and it's trying to find them in the overall Views folders. I tried making the route namespace "Weird.Namespace.With.No.Content" and it STILL hits the Members controller - I can't find any way to make it not use that controller. How do I make it not answer requests that aren't in it's area?
Ended up finding a solution by changing the Route to:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new string[] { "MyApp.Web.Controllers" }
).DataTokens["UseNamespaceFallback"] = false;
For some reason with that unset it seemed to always find my Controllers no matter where they were and totally disregard my namespaces - even from other referenced assemblies. Looking through the ILSpy of DefaultControllerFactory it looks like GetControllerType eventually falls back to searching absolutely every controller if it doesn't find the controller in the namespaces you asked for...
This flag seems to be set automatically on the Routes I made in a specific area, but not on the ones I made globally. When I set it on the global ones they began behaving how I had originally expected. I have no idea why you'd ever want to turn this on...
You should register the namespace on your area as well.
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Security_default",
"Security/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional },
new []{ "MyApp.Web.Areas.Security.Controllers"},
);
}
And then make sure all your controllers are in their appropriate namespaces.
Are you calling register all areas after registering your main route?
This is the default snippet from the MVC template (note how area regisration goes first)
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
Is it possible to define routes in various parts of a website.
Example, if I wanted to break functionality of my website out into modules, and each module would define the routes it needs.
Is this possible? How?
Consider using ASP.NET MVC's built-in Areas.
An "Area" is essentially your module, and Areas allow you to register routes for each specific area.
If you've not used them before there is an MSDN walkthrough here:
http://msdn.microsoft.com/en-us/library/ee671793.aspx
Essentially, you have a directory for each area, which contains all your area-specific controllers and views, and in the route of that directory you place a file that registers the routes for that particular area like so:
public class MyAreaRegistration : AreaRegistration
{
public override string AreaName
{
get { return "My Area"; }
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"news-articles",
"my-area/articles/after/{date}",
new {controller = "MyAreaArticles", action = "After"}
);
// And so on ...
}
}
In global.asax.cs you need to register all these extra areas, along with your other primary routes:
public static void RegisterRoutes(RouteCollection routes)
{
AreaRegistration.RegisterAllAreas();
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Products",
"products/show/{name}",
new {controller = "Products", action = "Show", name = UrlParameter.Optional}
);
...
}
You can put a DefineRoutes(RouteCollection routes) method in each module, then call them all in Global.asax.cs.