Routing doesn't find controller with the same name as area - c#

I followed article about Areas in ASP:NET MVC 4 (section How to Avoid Name Conflict). I'm using MVC 5, but I suppose all the features from version 4 are available and should work in version 5.
My directory structure:
File EpicAreaRegistration.cs content:
namespace App1.Web.UI.Areas.Epic
{
public class EpicAreaRegistration : AreaRegistration
{
public override string AreaName
{
get{ return "Epic"; }
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRouteLocalized(
name: "Epic_default",
url: "Epic/{controller}/{action}/{id}",
defaults: new { controller = "Pm", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "App1.Web.UI.Areas.Epic.Controllers" }
);
}
}
}
My project's App_Start -> RouteConfig.cs file content: UPDATE corrected namespace
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 = "Default", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "App1.Web.UI.Controllers" } // according to article namespace must be added here, so ASP.NET router distinguishes between request: e
);
}
}
And finally I have EpicController.cs file in project's directory Controllers:
namespace App1.Web.UI.Controllers
{
public class EpicController : Controller
{
public ActionResult Browse()
{
return View();
}
}
}
When I navigate to: http://localhost:7300/Epic/Pm it works (finds it), but http://localhost:7300/Epic/Browse doesn't work (404 - not found). What have I missed?
My assumption is that request goes through some kind of routing table. If it doesn't find Epic/Browse in Areas, it should move to project's root Controller folder. It's the same analogy as with Views (folder, if not in folder look in Shared, ...)
Additionally I registered all areas in Application_Start
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
RouteConfig.RegisterRoutes(RouteTable.Routes);
....

Make sure your Area controller uses the correct namespace.
Namespace for EpicController is currently:
namespace App1.Web.UI.Controllers
Change it to:
namespace App1.Web.UI.Areas.Epic.Controllers

Your controller is also Epic. So your URL would look like
http://localhost:7300/Epic/Epic/Browse

This may help you to access,
http://localhost:7300/Areas/Epic/Epic/Browse
As It's contained in sub folder.

Related

Controller namespace not routing correctly

So I am using MVC 5, and is getting this error. This is because I have two areas and they both have a controller with the same name and same method name.
Multiple types were found that match the controller named 'controller1'.
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.
So I understand that I need to add name spaces to my routing. So in Route.config.cs I added this
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "webApp.Controllers" }
);
Then in the application_start() function in global.asax I added ControllerBuilder.Current.DefaultNamespaces.Add("webApp.Controllers");
Then in my areas, where my error is coming from. I have 2 areas, admin and myportal. Both have a AreaRegistration.cs file. In AdminAreaRegistration.cs I have this added
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Admin_default",
"Admin/{controller}/{action}/{id}",
defaults: new { action = "Index", id = UrlParameter.Optional },
new[] { "webApp.Areas.Admin.Controllers" }
);
}
In MyPortalAreaRegistration.cs I have this added
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"MyPortal_default",
"MyPortal/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional },
new[] { "webApp.Areas.MyPortal.Controllers" }
);
}
From the client side I am making a post call
const otherParams = {
headers: {
"content-type": "application/json; charset=UTF-8"
},
body: JSON.stringify(product),
method: 'POST'
};
console.log(otherParams);
const response = await fetch('/Item/GetDetailPageURL', otherParams)
.then(response => {
response.json();
console.log(response);
window.open(response.url, "_blank");
})
.then(data => console.log(data));
From what I understand this is all I needed to get it work, but it is still complaining about the namespace. Am I misunderstanding/ missing something?
You shouldn't need to change your RouteConfig.cs
All you need to do is to register your area (inside the area folder):
In this example, the area name is admin. You need to write your area registration code inside adminAreaRegistration.cs file which is inside admin folder:
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 }
);
}
}
And then add AreaRegistration.RegisterAllAreas(); to your Global.asax.cs
Besides area registration like Hooman Bahreini said, try to setup your default name spaces as well in the application start.
Try this
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
// in you application start register your default or whatever makes sense Portal Controllers
ControllerBuilder.Current.DefaultNamespaces.Add("webApp.Areas.MyPortal.Controllers");
}
TRUST ME ON THIS -- go to your bin folder and blow away any old dll's "bin" folder completely manually. Sometimes there are stale dll's and don't get cleaned
your routes seem fine, but double check your routes with this answer on routes...
Use Attribute Routing in ASP.NET MVC 5:
[RoutePrefix(“reviews”)]
public class ReviewsController : Controller
{
Somewhere else:
[RoutePrefix(“otherreviews”)]
public class ReviewsController : Controller
{

Adding Web API to MVC 5 project (API takes over)

I've gone over all stack over flow QAs and online tutorials, to add a Web API to my current MVC project.
The Web API works, the MVC works only if I put the routing path into the url.
I want the MVC routing to come up as default, but for some reason it always tries to do the API logic.
I'm hoping its something simple I've missed
What I have done so far.
Web API Config class
Default, not really changed anything
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
MVC config class
Default, not really changed anything
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 }
);
}
}
Global Config class
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
API Controller class
Default, not really changed anything
public class RegistrationController : ApiController
{
// GET: api/Registration
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET: api/Registration/5
public string Get(int id)
{
return "value";
}
MVC home Controller class
Default, not really changed anything
namespace MVCPortal.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
}}
This is the error I'm getting

MVC5 Area not working

I have two Areas in my MVC 5 app that are not working properly.
When I use the following Link http://localhost:45970/Admin/Admin the app loads the proper index.cshtml whicxh is located at /Areas/Admin/Views/Admin/Index.cshtml however when I try to load http://localhost:45970/Admin it tries to load the Index.cshtml file from /Views/Admin/Index.cshtml.
All the search results say I am doing the correct thing. I have even loaded a sample API project to look at the help area in it to make sure I was doing things correctly.
Here is my RouteConfig.cs file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace BlocqueStore_Web
{
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 },
namespaces: new[] { "BlocqueStore_Web.Controllers" }
);
}
}
}
Here is the Application_Start() section of my Global.asax.cs file
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
And finally my AdminAreaRegistration.cs file
using System.Web.Mvc;
namespace BlocqueStore_Web.Areas.Admin
{
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 },
namespaces: new[] { "BlocqueStore_Web.Areas.Admin.Controllers" }
);
}
}
}
So, what am I missing?
You didn't set the default controller when registering Admin area. Set the controller to Admin and action to Index in the defaults parameter of context.MapRoute method
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Admin_default",
"Admin/{controller}/{action}/{id}",
defaults: new { action = "Index", controller = "Admin", id = UrlParameter.Optional },
namespaces: new[] { "BlocqueStore_Web.Areas.Admin.Controllers" }
);
}

HTTP 404 Server Error in '/' Application. in ASP.NET MVC 4

`First, this is my first MVC code & I tried to search for the solution to the problem in this site & I checked all the possible cases like routeconfig file, controller,action properties & I tried to put appropriate values in specified page of Web Tab of Project Property. But still it showing the same error. Some help please.
here my routeconfig file
namespace Deepak_MVC_2
{
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 = "Student", action = "GetStudents", id = UrlParameter.Optional }
);
}
}
}
specific page entry : Student/GetStudents
namespace Deepak_MVC_2.Controllers
{
public class StudentController : Controller
{
public ActionResult GetAllStudent()
{
StudentModelManager smm = new StudentModelManager();
List<StudentModel> lsm = smm.GetAllStudentInfo();
ActionResult ar = View("GetStudents",lsm);
return ar;
}
}
}
Update your controller's action to match the View you want. with that You can actually remove the name when returning the view as convention will match the ViewName to the action name.
namespace Deepak_MVC_2.Controllers
{
public class StudentController : Controller
{
public ActionResult GetStudents()
{
StudentModelManager smm = new StudentModelManager();
List<StudentModel> lsm = smm.GetAllStudentInfo();
ActionResult ar = View(lsm);
return ar;
}
}
}
this will allow
GET /Student/GetStudents
to be matched to the correct view as in your image

Asp.net MVC 2 Areas. Only one will work

This is my goal:
I need to two (or more) "Areas" for my MVC web app. They would be accessed like so:
/* Home */
http://example.com/
http://example.com/about
http://example.com/faq
http://example.com/contact
/* Admin */
http://example.com/admin
http://example.com/admin/login
http://example.com/admin/account
http://example.com/admin/ect
I would like to organize the project like the following:
MyExampleMVC2AreasProject/
Areas/
Admin/
Controllers/
Models/
Views/
Home/
Shared/
Site.Master
Web.Config
AdminAreaRegistration.cs
Web/
Controllers/
Models/
Views/
Home/
Shared/
Site.Master
Web.Config
WebAreaRegistration.cs
Global.asax
Web.Config
So, in Global.asax I have:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}
Here is WebAreaRegistration.cs
using System.Web.Mvc;
namespace MyExampleMVC2AreasProject.Areas.Web
{
public class WebAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Web";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"WebDefault",
"{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}
'AdminAreadRegistration.cs' is set up the same but the url param is Admin/{action}/{id}.
With the setup above the Web "Area" works great (example.com/about, example.com/contact, etc).
What do I need to do to get the Admin "Area" hooked up with the routes the way I want them? I just get 404ed now.
I've tried every combination of routes, routes w/namespaces, URL Parameters, parameter defaults, etc, I could think of. I have a feeling I'm missing something pretty basic.
I use this AreaRegistrationUtil class. It automatically registers anything which inherits AreaRegistration in any assembly you specify. As an added bonus, it's WAY faster than AreaRegistration.RegisterAllAreas because it only looks at the assembly you specify.
You probably need to set your namespaces on all your area registrations.
Example
context.MapRoute(
"Admin_default",
"admin/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new string[] { "MyExampleMVC2AreasProject.Areas.Admin.Controllers" } // This is area namespace
);
My current solution is here: http://notesforit.blogspot.com/2010/08/default-area-mvc-2.html
I don't like it and would love to get a better solution.
-- copied from URL above:
Implement your Areas as usually, register any routes that you need.
For example:
public class PublicAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Public";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Public_default",
"Public/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional, }
);
}
}
And:
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 {controller = "Overview", action = "Index", id = UrlParameter.Optional }
);
}
}
It's important, that URL should have any prefix, for example http://site.com/PREFIX/{controller}/{action}, because prefix of default Area will be cropped
Next in Global.asax.cs:
public class MvcApplication : System.Web.HttpApplication
{
public static string _defaultAreaKey = "DefaultArea";
public static void RegisterDefaultRoute(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//reading parameter DefaultArea from web.config
string defaultArea = ConfigurationManager.AppSettings[_defaultAreaKey];
//check for null
if (String.IsNullOrEmpty(defaultArea))
throw new Exception("Default area isn\'t set");
//select routes from registered,
//which have DataTokens["area"] == DefaultArea
//Note, each Area might have more than one route
var defRoutes = from Route route in routes
where
route.DataTokens != null &&
route.DataTokens["area"] != null &&
route.DataTokens["area"].ToString() == defaultArea
select route;
//cast to array, for LINQ query will be done,
//because we will change collection in cycle
foreach (var route in defRoutes.ToArray())
{
//Important! remove from routes' table
routes.Remove(route);
//crop url to first slash, ("Public/", "Admin/" etc.)
route.Url = route.Url.Substring(route.Url.IndexOf("/") + 1);
//Important! add to the End of the routes' table
routes.Add(route);
}
}
protected void Application_Start()
{
//register all routes
AreaRegistration.RegisterAllAreas();
//register default route and move it to end of table
RegisterDefaultRoute(RouteTable.Routes);
}
}
Do not forget add parameter to web.config:
<configuration>
<appSettings>
<add key="DefaultArea" value="Public"/>
</appSettings>
<!-- ALL OTHER-->
</configuration>

Categories

Resources