I am creating MVC application where I have several domains and depending on the domain it will go to a specific area.
when the application starts the application calls the AreaRegistration.RegisterAllAreas();
is there a way to register one specific area rather than all??
Thanks in Advance.
read about the area registration class I hope it will help to accomplish this task.
see the example:
public class BlogAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Blog";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Blog_default",
"Blog/{controller}/{action}/{id}",
new { action = "Index", id = "" }
);
}
}
Related
I'm using MVC4 without WebAPI, just plain on MVC. I have an admin area (called "Admin", as usual) which is properly registered:
public class AdminAreaRegistration : AreaRegistration
{
public override string AreaName { get { return "Admin"; } }
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute("EditGroupRoute", "admin/groups/{action}/{id}", new { controller = "EditGroup", action = "Index", id = UrlParameter.Optional });
//...
//No default handler at the end, all routes are predetermined
}
Global.asax:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
//...
}
}
My regular, non-area RouteConfig.RegisterRoutes works as it should and contains normal routes with no default catch-all handler at the end.
Whenever I try some admin area route I get a 404 error. I'm using Haack's RouteDebugger and it shows a full match (and only one match) below the 404 error text, with the correct area, controller and action.
I've checked similar questions on SO, but no joy. Any ideas what could be wrong?
Area controllers were in the wrong namespace. Originally they were in /Controllers when I moved them to area controllers I didn't update the namespaces.
Hi everyone I have a problem with MVC3 routing and areas:
My route matches but the controller is never called, instead i get a 404 error.
I have set an MVC3 solution with 2 project:
One is the main MVC Project: CityServices
One for an area: CityServices.Demo
In my area I register the following route:
public class TestAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Test";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Test_default",
"Test/{controller}/{action}",
new { controller = "Stuff", action = "ListAll" }
);
}
}
Content of StuffController.cs:
public class StuffController : Controller
{
public ActionResult ListAll()
{
List<Stuff> lstStuff = new List<Stuff>
{
new Stuff()
{
Id = 0,
Name = "HEeey",
Value = 10.456f
},
new Stuff()
{
Id = 1,
Name = "Beeee",
Value = 456789.47879999f
},
new Stuff()
{
Id = 2,
Name = "HooAAaoo",
Value = 0f
}
};
return Json(lstStuff);
}
}
I register area in the main project:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
//RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);
}
My route is matched: http://host/Test
But i always get a 404 error.
Any ideas?
Thanks,
- Jeremy
Edit: Here is a proof that the route matches:
Found Solution
So to sum it up.
My AreaRegistration inherited class was not in the same namespace as my controllers.
Since i did not have any views (it's just a restful websvc) i did not have to use MvcContribs which seems to be useful when you have views&controllers in a differents project than the main site.
Hope this helps if you arrive on this question ;)
You have your area in another project which won't work per default unless you are using MvcContribs portable areas or another custom implementation
I think you need to set the allow get for json:
return Json(data, JsonRequestBehavior.AllowGet)
I have a small MVC 3 app - bit of a demo ground.
I have one area and thats been working fine.
I have just added another area expecting to just spin up the app and it work - but no, 404 - The resource cannot be found.
The map route in the AreaRegistration is the default (as is the first area i created).
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Postcard_default",
"Postcard/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
I have tried adding in a specific controller into this, but nothing.
So I downloaded Phil Haack's RouteDebugger and my route is found when typing in http://server/Postcard/Create (which is where I am trying to get too)
Structure of the Area
My controller
public class CreateController : Controller
{
private ILogger Logger { get; set; }
private ICardSender Emailer { get; set; }
private IOCCardRepository CardRepository { get; set; }
public CreateController(ILogger logger, ICardSender cardSender, IOCCardRepository repository)
{
this.Logger = logger;
this.Emailer = cardSender;
this.CardRepository = repository;
}
//
// GET: /Postcard/Create/
public ActionResult Index()
{
var model = new OCPostcardModel().Create();
return View(model);
}
NOW: I have since deleted the entire area, tried again it didn't work. So I added in the specific controller in the route (Inside AreaRegistration file)
context.MapRoute(
"Postcard_default",
"Postcard/{controller}/{action}/{id}",
new { controller = "Create", action = "Index", id = UrlParameter.Optional }
);
And its working...I don't know why it didn't work when I did this before, but it is now.
Still curious though as I've not seen anyone add in this controller into route in any of the demo's i've looked at - and I haven't got it in my other area?
I ran into this when I moved a controller into an Area but forgot to update the namespace. The controller name is scoped to the Area's namespace. So "Some" in "Area" will map to App.Areas.Area.Controllers.SomeController, which didn't exist.
You were missing the controller part in your maproute
Try to add a class PostCardAreaRegistration under PostCard Area
using System.Web.Mvc;
namespace Areas.PostCard
{
public class PostCardAreaRegistration: AreaRegistration
{
public override string AreaName
{
get
{
return "PostCard";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"PostCard_default",
"PostCard/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
}
}
Some body tried Spark View Engine with asp.net mvc 2 preview 2?
I have a problem with AREAS.
It looks likes spark engine looks **.spark* files inside of Views folders only instead of Areas folder in additionally.
My question is:
Somebody has information how to add it?
Spark will not automatically check the area views location in the current version. If you're willing to change the source (which i assume you are if you're doing mvc 2 stuff), here's the fix:
You have to modify the file src\Spark.Web.Mvc2\Descriptors\AreaDescriptorFilter.cs so that it reads as below (changes highlighted by **):
Note: I don't have the machine i did this on with me, so the slashes in the format string MIGHT need to be forward slashes.
Also, it is possible to create this class in your own code and pass it in when you register the view engine, but I don't remember the configuraiton code off the top of my head.
That's the approach I did since I wanted to modify the spark source as little as possible.
public class AreaDescriptorFilter : DescriptorFilterBase
{
**private const string areaPathFormatString = "~\\Areas\\{0}\\Views";**
public override void ExtraParameters(ControllerContext context, IDictionary<string, object> extra)
{
object value;
if (context.RouteData.Values.TryGetValue("area", out value))
extra["area"] = value;
}
public override IEnumerable<string> PotentialLocations(IEnumerable<string> locations, IDictionary<string, object> extra)
{
string areaName;
return TryGetString(extra, "area", out areaName)
**? locations.Select(x => Path.Combine(string.Format(areaPathFormatString,areaName), x)).Concat(locations)**
: locations;
}
}
Spark looks for a constraint or default value key "area" in a route to determine the view location. MVC 2 area support does not add this by default, you have to do it when declaring your area:
public class AdminRoutes : AreaRegistration
{
public override string AreaName
{
get { return "admin"; }
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"admin_default",
"Admin/{controller}/{action}/{id}",
new { controller = "Dashboard", action = "Index", id = "", area = "admin" },
new [] { "MyProject.Areas.Admin.Controllers" });
}
}
Note the area = "admin" inside the defaults object.
I noticed that in MVC 2 Preview 2, AreaRegistration is loading the routes for each area in an arbitrary order. Is there a good way to get one before the other?
For example, I have two areas - "Site" and "Admin". Both have a "Blog" controller.
I would like the following:
/admin/ --> go to Admin's Blog controller
/ --> go to Site's Blog controller.
The problem is that it is loading the site's route first, so it is matching {controller}/{action}/{id} instead of admin/{controller}/{action}/{id} when I go to the url "/admin/". I then get a 404, because there is no Admin controller in the "Site" area.
Both areas default to the "Blog" controller. I realize I could simply put site/{controller}/... as the url, but I would rather have it at the root if possible. I also tried keeping the default route in the global RegisterRoutes function, however, it is then not sent to the "Sites" area.
Thanks in advance!
Aside from what Haacked said, it is very much possible to order area registrations (and thus their routes). All you have to do is register each area manually, in whatever order you want. It's not as sleek as calling RegisterAllAreas() but it's definitely doable.
protected void Application_Start() {
var area1reg = new Area1AreaRegistration();
var area1context = new AreaRegistrationContext(area1reg.AreaName, RouteTable.Routes);
area1reg.RegisterArea(area1context);
var area2reg = new Area2AreaRegistration();
var area2context = new AreaRegistrationContext(area2reg.AreaName, RouteTable.Routes);
area2reg.RegisterArea(area2context);
var area3reg = new Area3AreaRegistration();
var area3context = new AreaRegistrationContext(area3reg.AreaName, RouteTable.Routes);
area3reg.RegisterArea(area3context);
}
Another option is to take the code for RegisterAllAreas(), copy it into your own app, and build your own mechanism for determining the order. It is quite a bit of code to copy if you want all the fancy caching logic that the built-in method does, but your app might not even need that.
Currently it's not possible to order areas. However, I think it makes sense to try and make each area as independent from other areas as possible so the order doesn't matter.
For example, instead of having the default {controller}/{action}/{id} route, maybe replace that with specific routes for each controller. Or add a constraint to that default route.
We are mulling over options to allow ordering, but we don't want to overcomplicate the feature.
I make this solution:
AreaUtils.cs
using System;
using System.Web.Mvc;
using System.Web.Routing;
namespace SledgeHammer.Mvc.Site
{
public static class Utils
{
public static void RegisterArea<T>(RouteCollection routes,
object state) where T : AreaRegistration
{
AreaRegistration registration =
(AreaRegistration)Activator.CreateInstance(typeof(T));
AreaRegistrationContext context =
new AreaRegistrationContext(registration.AreaName, routes, state);
string tNamespace = registration.GetType().Namespace;
if (tNamespace != null)
{
context.Namespaces.Add(tNamespace + ".*");
}
registration.RegisterArea(context);
}
}
}
In global.asax:
Utils.RegisterArea<SystemAreaRegistration>(RouteTable.Routes, null);
Utils.RegisterArea<ClientSitesAreaRegistration>(RouteTable.Routes, null);
//AreaRegistration.RegisterAllAreas(); do not dublicate register areas
No requred changes to generated area registration code.
I also use custom constrant in routes to filter routes by type of domain in request (system domain or user site).
This is my area registrations as example:
namespace SledgeHammer.MVC.Site.Areas.System
{
public class SystemAreaRegistration : AreaRegistration
{
public override string AreaName
{
get { return "System"; }
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"System_Feedback",
"Feedback",
new { controller = "Feedback", action = "Index" }
);
context.MapRoute(
"System_Information",
"Information/{action}/{id}",
new { controller = "Information", action = "Index", id = UrlParameter.Optional }
);
}
}
}
namespace SledgeHammer.MVC.Site.Areas.ClientSites
{
public class ClientSitesAreaRegistration : AreaRegistration
{
public override string AreaName
{
get { return "ClientSites"; }
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"ClientSites_default",
"{controller}/{action}/{id}",
new { controller = "Site", action = "Index", id = UrlParameter.Optional },
new { Host = new SiteInGroups("clients") }
);
}
}
}
For reference,
In MVC3 (don't know about MVC2) when you just want to map root to a specific area/controller you could simply use a global route.
Just remember to specify the namespace/area.
routes.MapRoute(
"CatchRoot", "",
new { controller = "SITEBLOG-CONTROLLER-NAME", action = "Index"}
).DataTokens.Add("area", "SITE-AREA-NAME");