Let me define my setup here. I have some areas like 1. AreaA 2. AreaB 3. AreaC and 4. AreaGeneral. in AreaGeneral I have one controller as home and GetData(paras) and it returns some data either in partial or full page form to angularjs. If I am using these two controller inside the AreaGeneral then its ok. but I want to provide the same controllers inside other Areas like in A, B, and AreaC, but there area and route are different. and more importantly when a user navigates to particular area say AreaB to access GetData(paras) controller then the url should be like .../AreaB/GetData instead of .../AreaGeneral/GetData and the route should work in other areas as well. Can someone guide me how to do this, Thanks.
Givent that you've already had AreaGeneral routes defined as below:
public class AreaGeneralAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "AreaGeneral";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"AreaGeneral_default",
"AreaGeneral/{controller}/{action}/{id}",
new { controller = "Home", action = "GetData", id = UrlParameter.Optional }
);
}
}
You can register that route in AreaB:
public class AreaBAreaRegistration : AreaRegistration
{
public override string AreaName
{
get { return "AreaB"; }
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"AreaB_Getdata",
"AreaB/Home/Getdata",
new { controller = "Home", action = "GetData" },
new string[] { "areastest.Areas.AreaGeneral.Controllers" }).DataTokens["area"] = "AreaGeneral";
context.MapRoute(
"AreaB_default",
"AreaB/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional });
}
}
so that user can navigate to .../AreaB/Home/GetData and view the page actually handled within AreaGeneral.
I used angular services in different MVC areas for that I used following way
if your project structure should be like following
>ProjectName
>Areas
>AreaGeneral >controllername >GetData(function)
>AreaA
>AreaB
>AreaC
if your services like
app.service("yourService", ["$http",function ($http) {
this.GetData= function () {
var c = $http({
method: "post",
url:"../AreaGeneral/controllername/GetData",
data: "{}",
dataType: "json"
});
return c
} }])
if you are using inside AreaGeneral then
url "../AreaGeneral/controllername/GetData" ok for that
but when use different area like AreaA
"../AreaGeneral/controllername/GetData" its search inside the AreaA so that you donot get result
Solution work for me like called function adding extra ../ as per root directory structure
this way
"../../../AreaGeneral/controllername/GetData"
then every time call getdata function it checks from root directory so this way you can use Getdata function in any area
Hope this help you.
Related
I have developed a project in C# MVC with 'AdminLte' Template and I uses Areas for submodules.
when I access a link from home page (http://localhost:9760/Home/Index) the it works perfectly as follows http://localhost:9760/Manage/ChangePassword
but when I access the same link from Area ex: 'AirSurveillance' http://localhost:9760/AirSurveillance/Manage/ChangePassword it is not working and gives 404 error because it tried to find 'Manage' controller (which is not there) in 'AirSurveillance' area.
this is my auto-generated 'SecurityClearanceAreaRegistration.cs' file
namespace IIMS.Areas.SecurityClearance
{
public class SecurityClearanceAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "SecurityClearance";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"SecurityClearance_default",
"SecurityClearance/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
}
}
Please help me.
When using areas, your links will need to specify the area for the controller/action you're pointing to. If you want to use controllers outside of those areas you specify a blank Area. for example...
#Html.ActionLink("ChangePassword", "Manage", new { Area = ""})
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.
Hi I have problem with routes in plugin, in nopcommerce 3.6
I have in folder Controller TestPohodaController.cs contains method ImportProductInfo()
There is my RegisterRoutes:
namespace Nop.Plugin.Test.Pohoda
{
public partial class RouteProvider : IRouteProvider
{
public void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute("Plugin.Test.Pohoda.ImportProductInfo",
"Plugins/TestPohoda/ImportProductInfo",
new { controller = "TestPohoda", action = "ImportProductInfo" },
new[] { "Nop.Plugin.Test.Pohoda.Controllers" }
);
}
public int Priority
{
get
{
return 0;
}
}
}
}
Installation to nopCommerce is ok, but when I go to mypage/Plugins/TestPohoda/ImportProductInfo page return 404.
I need url of TestPohodaController to call this controller from economic system. Can You help me please? Thanks.
ASP.NET MVC Routing evaluates routes from top to bottom. So if two routes match, the first one it hits (the one closer to the 'top' of the RegisterRoutes method) will take precedence over the subsequent one.
With that in mind, you need to do two things to fix your problem:
Your default route should be at the bottom.
Your routes need to have constraints on them if they contain the same number of segments:
What's the difference between:
example.com/1
and
example.com/index
To the parser, they contain the same number of segments, and there's no differentiator, so it's going to hit the first route in the list that matches.
To fix that, you should make sure the routes that use ProductIds take constraints:
routes.MapRoute(
"TestRoute",
"{id}",
new { controller = "Product", action = "Index3", id = UrlParameter.Optional },
new { id = #"\d+" } //one or more digits only, no alphabetical characters
);
You don't need to start with Plugins for your route url. it is enough
to follow this pattern {controller}/{Action}/{parameter}
Make sure also namespace for the controller is correct as you define
in the routing. Nop.Plugin.Test.Pohoda.Controllers
You can define an optional productId parameter as well. so it will
work for mypage/TestPohoda/ImportProductInfo or
mypage/TestPohoda/ImportProductInfo/123
You can also set the priority higher than 0 which is priority of the
default routeprovider in the nop.web. this way you ensure that your
plugin reads it first. Indeed it is not necessary as you have
specific url. this is only required if you have similar route url
Try using this route
namespace Nop.Plugin.Test.Pohoda
{
public partial class RouteProvider : IRouteProvider
{
public void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute("Plugin.Test.Pohoda.ImportProductInfo",
"TestPohoda/ImportProductInfo/{productId}",
new { controller = "TestPohoda", action = "ImportProductInfo" , productId = = UrlParameter.Optional },
new[] { "Nop.Plugin.Test.Pohoda.Controllers" }
);
}
public int Priority
{
get
{
return 1;
}
}
}
}
We will have a look at how to register plugin routes. ASP.NET routing is responsible for mapping incoming browser requests to particular MVC controller actions. You can find more information about routing here. So follow the next steps:
If you need to add some custom route, then create RouteProvider.cs file. It informs the nopCommerce system about plugin routes. For example, the following RouteProvider class adds a new route which can be accessed by opening your web browser and navigating to http://www.yourStore.com/Plugins/PaymentPayPalStandard/PDTHandler URL (used by PayPal plugin):
public partial class RouteProvider : IRouteProvider
{
public void RegisterRoutes(IRouteBuilder routeBuilder)
{
routeBuilder.MapRoute("Plugin.Payments.PayPalStandard.PDTHandler", "Plugins/PaymentPayPalStandard/PDTHandler",
new { controller = "PaymentPayPalStandard", action = "PDTHandler" });
}
public int Priority
{
get
{
return -1;
}
}
}
It could be cache problem, try to restart IIS
actually you do nota have to register route by default you can call your method
/TestPohoda/ImportProductInfo
I have one area called user.
The area configuration looks like this
context.MapRouteLowercase(name: "User_Member", url: "User/Member", defaults: new { controller = "User", action = "Member", id = UrlParameter.Optional });
When I browse to this page without passing in a id, it returns the view my url looks like this /user/member
When I type the following into the browser /user/member/1
I've put a break point on
var userId
and it gets hit and I check the id parameter and its 1 which is correct.
[HttpGet]
[Authorize]
public ActionResult Member(Int64 id = 0)
{
var userId = id != 0 ? id : ReturnUserId();
var model = _userProfileBusinessLayer.GetProfile(userId);
return View(model);
}
Yet when I press F5 I get the following page
Server Error in '/' Application.
The view 'member' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/user/member.aspx
~/Views/user/member.ascx
~/Views/Shared/member.aspx
~/Views/Shared/member.ascx
~/Views/user/member.cshtml
~/Views/user/member.vbhtml
~/Views/Shared/member.cshtml
~/Views/Shared/member.vbhtml
I'm unsure why I'm seeing that because all I have done is added /1 to the url?
I should be seeing the profile of the user which matches then id of 1, yet I remove /1 and it returns the view ?!?!?!?! slightly baffled
In your project, the area user should have a class that inherits from AreaRegistration e.g.
public class UserAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "user";
}
}
}
In that class you can define routes sepcific for that area:
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"UserManagement",
"user/Admin",
new { controller = "UserAdmin", action = "Index" });
}
The file Global.asax.cs should have an Application_Start() method which calls:
AreaRegistration.RegisterAllAreas();
That will pick up the area routes you have configured. This is usually how area routes are configured. Do you have a similar setup for your project?
I have an api using web api 2 and I am trying to create help docs within an Area so that an incoming request like ...api/people.help will route to the people controller and people view and serve up the html. I am struggling with the route mapping for the area after refactoring the code. Previously, I had routes like this:
public override void RegisterArea(AreaRegistrationContext context) {
context.MapRoute(
name: "Help",
url: "{action}.help",
defaults: new { area = "help", controller = "default" }
);
All the methods were in the default controller and this worked. Now, I need a separate controller for each resource (eg people, schedules etc) but can't get the routes to work. I would appreciate help, I am very new to this. How do I get each help request to map to the controller with the same action name?
Wouldn't it simply be something similar to:
public override RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
name: "Help",
url: "api/{controller}.help",
defaults: new { area = "help" }
);
}
What you have in your post is a default for the name of the controller, in this case, it's name will always be default. Instead, what you're looking for is that when someone routes to your controller name suffixed with .help, it'll route to a path akin to api/help/people, which will end up calling a default action (in MVC) such as index.cshtml or the default action for a GET request to the controller (for WebAPI).
So, you want to set the default area to help as shown above. You also want to set the default action that should execute on the provided controller.
Update: To answer question in comment
For MVC, you can have an action method whose name matches what the controller name will be in the URL:
public class PeopleController : Controller
{
[HttpGet] // Not strictly necessary, but just want to stress this is GET
public ActionResult People()
{
// Do stuff in your action method
}
}
The only problem is, your action method will be different for each controller, and so unknowable for route registration purposes. Therefore, you should maybe have just a default Help action:
public class PeopleController : Controller
{
[HttpGet]
public ActionResult Help()
{
// Do stuff
}
}
Then you can have the following route:
public override RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
name: "Help",
url: "api/{controller}.help",
defaults: new { area = "help", action = "Help" }
}
You could take this one step further and provide a Help method in a custom base controller class:
public class MyBaseController : Controller
{
public virtual ActionResult Help()
{
// Do default behavior stuff, if appropriate
}
// If you don't have any "default" behavior, you could make the method abstract:
// public abstract ActionResult Help();
}
public class PeopleController : MyBaseController
{
public override ActionResult Help()
{
// Do stuff.
}
}
Update to further answer OP's question in comments
So, now the OP is saying: "but I want my view to have the same name as my controller." Ok, that should be no problem:
public class PeopleController : MyBaseController // if you're using a base class
{
public override ActionResult Help()
{
return ViewResult("People");
}
}
So, you can have a view with any name you want. But if the view's name differs from the name of the action method, then when returning (say) a ViewResult, you'll need to specify the name of the view to return.
Having said all that, the default folder structure for views in ASP.Net is Areas/{AreaName}/Views/{Controller}/{viewname}.{cs|vb}html. And here, {viewname} is by default assumed to be the action method name, but doesn't have to be when, as above, explicitly telling MVC which view to return (in the example above, People.cshtml).
HTH.