MVC Route Mapping - c#

I have a website, xyz.com and users are setting up admin accounts where they then have other users that are registering under them. They call their account name wisconsinsponsor. Another user sets up another account called iowasponsor. So I want to be able to have the ability that a user could browse to xyz.com/wisconsinsponsor and xyz.com/iowasponsor and get funneled into the appropriate settings that these users have setup.
So then after I browse to xyz.com/wisconsinsponsor which will allow me to get the appropriate settings for wisconsinsponsor I can be dropped onto xyz.com/wisconsinsponsor/{controller}/{method}.
So I added the following code.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
List<Sponsor> sponsors = new SponsorContext().Sponsors.ToList();
foreach (Sponsor sponsor in sponsors)
{
// ALL THE PROPERTIES:
// rentalProperties/
routes.MapRoute(
name: sponsor.SponsorName,
url: sponsor.SponsorName + "{controller}/{action}/{id}",
defaults: new
{
controller = "Home",
action = "Index",
id = sponsor.SponsorId
}
);
}
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new {
controller = "Home",
action = "Index",
id = UrlParameter.Optional }
);
}
So the main goal is that without logging in, I can get information that pertains to each "sponsor" and then just generic information if a user goes to 'xyz.com' without specifying a sponsor. The below works to a point for landing on the home page, but then when I navigate to login or any other view, I get for example 'xyz.com/[my first sponsor entry in the database]/admin/login' instead of 'xyz.com/admin/login'. Why doesn't the navigation fall to the Default route?

Change your route to simply include the sponsor, don't create individual routes for every sponsor, this is where routing becomes so powerful
routes.MapRoute(
name: null, //routes names must be unique, but you can have multiple named null (go figure)
url: "{sponsor}/{controller}/{action}/{id}",
defaults: new
{
sponsor = "defaultSponsor", //or whatever you want the default to be
controller = "Home",
action = "Index",
id = UrlParameter.Optional
}
);
Then, decorate each of your action methods with the sponsor argument
public ActionResult Index(string sponsor, int id) { }
Rereading your question tho, this doesn't help in the instance of not having a sponsor, unless your "defaultSponsor" is not really a sponsor, but your generic information that is presented. So when no sponsor is passed in the address bar to the routing, you see 'defaultSponsor' or and empty string and could then handle appropriately
Another reason to handle it this way, is RegisterRoutes is only called upon application start up, so if they were dynamically added while the app is running, they would be invalid routes until the application is restarted. By making it an argument, they would work dynamically as well.

Related

mvcsitemapprovider - Navigating to the same ActionResult from different pages

Mvc 5, .Net 4.5
I implement MvcSiteMapNodeAttribute as follows:
[MvcSiteMapNode(Title="Running Events", ParentKey="Events", Key="RunningEvents")]
public ActionResult RunningEvents()
{
return View();
}
I need to access this page from multiple locations and keep the breadcrumbs in tack (i.e. from the correct calling method). However the ParentKey dictates where the call comes from and thus set the ParentNode based on it. This is not ideal as I want the calling ActionResult to be the parent and not "hard coded" as with the ParentKey solution. The ParentKey is also not editable at runtime nor the ParentNode. The only way around this at the moment is to duplicate the ActionResult with different signatures and give it the same Title which is also not ideal.
I've read up on mvc routing, DynamicNodeProvider, route mapping, etc but cannot find a way to make this work? I'm also not very familiar with mvc so would appreciate some guidance.
Thanks
See the Multiple Navigation Paths to a Single Page documentation.
You can use the same controller action in multiple places. However, you must always provide a unique set of route values (which usually means each URL should be unique).
The most natural way to do this is to design your URLs with the parent category.
routes.MapRoute(
name: "Category1RunningEvents",
url: "Category1/RunningEvents",
defaults: new { controller = "Events", action = "RunningEvents", category="Category1" }
);
routes.MapRoute(
name: "Category2RunningEvents",
url: "Category2/RunningEvents",
defaults: new { controller = "Events", action = "RunningEvents", category="Category2" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
And then differentiate the route matching by the category field. You can use multiple MvcSiteMapNode attributes on the same action, each with different parent key in the SiteMap.
[MvcSiteMapNode(Title="Category 1 Events", ParentKey="Events", Key="RunningEvents", Attributes = #"{ ""category"": ""Category1"" }")]
[MvcSiteMapNode(Title="Category 2 Events", ParentKey="Category2", Key="Category2RunningEvents", Attributes = #"{ ""category"": ""Category2"" }")]
public ActionResult RunningEvents()
{
return View();
}
Of course, this isn't the only way to configure the routing but it should clear up the concept. The only limitation is that you must use a unique set of route values for the match, each which corresponds to a node. However, there can be multiple nodes that represent the same controller action, each with a different parent node.
Also see this answer.

namespace rename issue in asp MVC4 [duplicate]

I am running into the following error with my ASP.NET MVC 3 project:
Multiple types were found that match
the controller named 'Home'. This can
happen if the route that services this
request ('Home/{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.
The request for 'Home' has found the
following matching controllers:
MyCompany.MyProject.WebMvc.Controllers.HomeController
MyCompany.MyProject.WebMvc.Areas.Company.Controllers.HomeController
I have a HomeController in my default controller folder, with a class name of MyCompany.MyProject.WebMvc.Controllers.HomeController.
My RegisterRoutes method, in my global.asax, looks like:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
I then have an area called Company, with a HomeController in the default controller folder for the area, with a class name of MyCompany.MyProject.WebMvc.Areas.Company.Controllers.HomeController.
The RegisterArea method in the CompanyAreaRegistration file looks like:
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Company_default",
"Company/{controller}/{action}/{id}",
new { area = "Company", action = "Index", id = UrlParameter.Optional }
);
}
This is all leading the error I highlighted at the beginning of this post. I am struggling trying to piece together a solution from various other posts, with NO LUCK.
Is it possible to have a HomeController in the default controllers folder and then one in EACH area? If so, do I need to make (assuming I do) changes to my configuration file to make this work?
Any help would be much appreciated!
The error message contains the recommended solution: "If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter."
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
new string[] { "MyCompany.MyProject.WebMvc.Controllers"}
);
This will make http://server/ go to your HomeController's Index action which is, I think, what you want. http://server/company/home will go to the Company area's HomeController's Index action, as defined in the area registration.
This is the asp.net mvc4 approach:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "RegisterNow", id = UrlParameter.Optional },
namespaces: new[] { "YourCompany.Controllers" }
);
I had renamed the namespaces, so, i only delete de folders bin and obj and rebuild, work again.
If you're using RazorGenerator, just informing the namespaces parameter could be not enough.
I got to solve adding the statement marked below at Global.asax.cs:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ControllerBuilder.Current.DefaultNamespaces.Add("MyProject.Controllers"); // This one
}
Another plausible cause of this issue could be found below:
Multiple types were found that match the controller named 'Home'
use this
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "ProjectName.Controllers" }
);
Use only the name of the project:
Public Class RouteConfig
Public Shared Sub RegisterRoutes(ByVal routes As RouteCollection)
routes.IgnoreRoute("{resource}.axd/{*pathInfo}")
routes.MapRoute( _
name:="Default", _
url:="{controller}/{action}/{id}", _
defaults:=New With {.controller = "Home", .action = "Index", .id = UrlParameter.Optional} _
, namespaces:={"MvcAreas"})
End Sub
I had the same issue and found that the older version had created compiled files in the "bin" folder.
Once I deleted these the error disappeared.
As Chris Moschini mention the namespaces parameter may not be enough if you have two areas with same controller name with different namespaces and the default none area route will return 500 server error.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
new string[] { "MyCompany.MyProject.WebMvc.Controllers"}
);
It "best" to override the default route handler and add this line:
RequestContext.RouteData.DataTokens["UseNamespaceFallback"] = false;
I had this issue after I added a reference to another project that had the same routes and the problem continued after I removed the reference.
Resolved by deleting the .dll file of that added reference from the bin folder and rebuilding.
Like many others, I had this problem after creating a new MVC template project from VS2017 menu, on building the project I would get the op's error message. I then used the answer https://stackoverflow.com/a/15651619/2417292 posted earlier in this thread by cooloverride
for mvc4 projects.
This still didn't fix my issue so I renamed my Home view folder and HomeController file to be the view folder Company/ and controller file CompanyController. This then worked for me, not a fix per say but a workaround if your not stuck on having the route Home/Index my other issue was I couldn't find the reference causing the error and due to my dev platform being Azure WebApplication vs a full VM with a complete file system and IIS settings to mess with.
For MVC5 below code works for issue same controller name for different areas. You have to specify which area controller have to hit first.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "ApplicationName.Areas.AreaName.Controllers" }
).DataTokens.Add("area", "AreaName");
This issue occurred when I accidentally added
[Route("api/[controllers]s")]
instead of
[RoutePrefix("api/[controllers]s")]
to the top of my ApiController.

How to have a profile url like facebook. (asp.net)

HI i am new to aspdotnet and want to ask how do I able to have a facebook like profile link for each of the registered user in the database.
example:
https://www.facebook.com/james
As you can see after .com there is a unique name. but my question: Is that name a folder or some kind of auto generated link?? How can I implement this kind of link for each of the registered user in my database?
well i can easy do it wit GET but I want to hide the id from the url.
Take a look at your RouteConfig.cs file in your App_Start folder.
The default route (www.facebook.com) is set to your HomeController.Index() method. You can tell that by the "defaults" parameter.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
In the example that you provided, "james" would be a string parameter for that Index method. Obviously, the signature to the method would be:
public ActionResult Index(string id) {
// Do stuff
}

Can I hide a part of a route?

I have an AppController and an AccountController. The AppController only has one view, index, which takes query string parameters from the id part of the url.
The default route is as follows: {controller}/{action}/{id}
This means for the query string parameters to work properly, the view name has to be in the url. url/view/id
I would like to hide that part of the url and render that view by default, so users need only go to url/id.
I have tried {controller}/{id} and {controller}/index/{id} but neither work.
I think this would work. Set the url as : "{controller}/{id}" and give it a default action parameter:
routes.MapRoute(
name: "Default",
url: "{controller}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

MVC 3 How to use MapRoute

Could someone show me how to use the MapRoute method? I have tried creating my own routes, but it's not working. What i want to accomplish is a route that routes "http://servername/home/default.aspx" into controller "Home" and action "Default". Also, would it be possible to say that if the user is browsing the default.aspx "file", it would actually point to the "Index" action?
I have tried reading the MSDN references and googling, but it didn't make me any wiser.
Probably too late to help the developer who raised the question but may help someone else. New to MVC but what I found is the map routes seem to be processed in the order they are added. I had a similar problem, my specific route was not working until I started adding the default route as the last route.
If the default map route is added before your custom one and your custom URL matches the structure defined by the default map route you will never reach your custom route.
The route you want to configure the first part of your question is:
routes.MapRoute(
"",
"home/default.aspx",
new { controller = "Home", action = "Default" }
);
Assuming you wish to 'browse' default.aspx with some sort of parameter you can do something like:
routes.MapRoute(
"",
"home/default.aspx/{param}",
new { controller = "Home", action = "Default", param = UrlParameter.Optional }
);
And you would then need to create your Default action to accept string param.
You also have to make sure the parameter name is the same as the action's parameter name.
Example:
routes.MapRoute(
name: "MyName",
url: "{controller}/{action}/{myParam}",
defaults: new { controller = "MyController", action = "MyAction", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
MyController:
public ActionResult MyAction(string myParam = "")
{
}

Categories