MVC3 Routing Working 1 Direction Only - asp.net

I am working on an ASP.NET mvc 3 site that contains several project entities, and then each project has several associated subpages, each that works with a component of the project.
So for instance, I could have a project with several photos, milestones, user info, etc. I have a Project Index view, as well as a Project Home which links to several component pages. Most of the components have two views, Index, and Edit/View.
So I set up a route for the edits and views. Note that my route is in an AREA called ProjectManagement
context.MapRoute(
"ProjectManagement_ProjectPageSingle",
"ProjectManagement/{controller}/{action}/{projectNumber}/{projectChildId}",
new { controller = "Project", action = "Home" }
);
and my controller actions all look similar to this:
public ActionResult Edit(string projectNumber, string projectChildId)
This works well and good when I type in the URL directly in the browser. For instance:
~/ProjectManagement/Milestone/Edit/39999P110175/1
however, when I generate an action link using:
<a href="#Url.Action("Edit", new { projectNumber = Model.Project.ProjectNumber, projectChildId = entry.Id})">
the action URL ends up looking like this:
~/ProjectManagement/Milestone/Edit/39999P110175?projectChildId=1
So the route sorta works...but the action link generator doesn't? Not sure where to go from here. Any advice would be much appreciated.
Note that the same thing occurs while using #Html.ActionLink instead of #Url.Action.
Thanks!

You don't seem to have specified the area name:
#Url.Action(
"Edit",
new {
projectNumber = Model.Project.ProjectNumber,
projectChildId = entry.Id,
area = "ProjectManagement"
}
)
Also make sure that there aren't any other routes that might conflict with this one in your area registration which should look like this:
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"ProjectManagement_default",
"ProjectManagement/{controller}/{action}/{projectNumber}/{projectChildId}",
new { controller = "Project", action = "Home" }
);
}

Thanks to Michael for the response. Here's the answer for others.
I had:
context.MapRoute(
"ProjectManagement_ProjectPage",
"ProjectManagement/{controller}/{action}/{projectNumber}",
new { controller = "Project", action = "Home"}
);
///more routes
context.MapRoute(
"ProjectManagement_ProjectPageSingle",
"ProjectManagement/{controller}/{action}/{projectNumber}/{projectChildId}",
new { controller = "Project", action = "Home" }
);
The URL matched the ProjectPage route as well, so it took that one first. Had to flip the order, so the more specific route came first.
Thanks.

Related

Why is this ActionLink to another area not working?

I am testing how to build an action link to a page in another area, and every source I find says to use
Html.ActionLink("[Link Text]", "[action name]", "[controller]", new { area = "[areaName]" }, null)
except for one source I found which suggested
Html.ActionLink("[Link Text]", "[action name]",new { area = "[areaName]", controller = "[controllerName]" })
The problem is, neither of these work for me. In my MVC application I have an area called "Uploader", which contains its own Home controller, and Index page. So, in the main Index page of my MVC project, I create an ActionLink that looks like this:
#Html.ActionLink("Area Test", "Index", "Home", new { area = "Uploader" }, null)
If the link works correctly, I'll get taken to a page that reads "this is the uploader", the text on my area Index page, but instead, the main home/index page of my application just reloads.
The address I see in my browser after this reload is "https://localhost:44352/?area=Uploader".
The HomeController for the area is correctly formatted with an "Area" tag, like so:
namespace TestProject.Areas.Uploader.Controllers
{
[Area("Uploader")]
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}
}
I'm using .Net 5. What am I doing wrong?
Finally found the answer here. It turns out I had my area configuration backwards: the "default" route should come last.
It should be:
endpoints.MapControllerRoute(
name: "areas",
pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
...instead of the other way around.

What should be the naming convention and folder structure for Contact Us View Page in .NET Core MVC?

I have just started learning .NET Core MVC .I am creating a contact us view page .My doubt is should i create a structure where it is like this
1)
Views(folder)
-ContactUs(folder)
-Index.cshtml
Controller(folder)
-ContactUsController.cs
2)
Views(folder)
-Home(folder)
-ContactUs.cshtml
Controller(folder)
-HomeController.cs
3) This is similar to 1 just name change of cshtml file .Would like having a page as ContactUs.cshtml be better at seo rather than Index.cshtml?
Views(folder)
-ContactUs(folder)
-ContactUs.cshtml
Contorller(folder)
-ContactUsController.cs
Honestly from a 'code' point of view it doesn't matter. All the ways you've outlined above will work fine.
You will have the following URLs from them:
1 - /contactus
2 - /home/contactus
3 - /contactus/contactus
As you can see they will all work but you also need to consider things from an SEO point of view.
Ideally, you'd want a simple URL like /contactus to be used so in this case option 1 seems to be the best.
That said, you could still use option 2 or 3 but you would need to set up a Route in order to make the URL 'friendly'.
Something like this:
For example, in startup.cs for Option 2:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "contact",
defaults: new { controller = "Home", action = "ContactUs" });
template: "contactus");
});
says point yoursite.com/contactus to the home controller and the contactus action.
Note: Custom routes need to be placed before the default route.
The way MVC load views for each ActionMethod in a controller is following this order:
/Views/[Controller]/[ActionMethod].cshtml
/Views/Shared/[ActionMethod].cshtml
/Pages/Shared/[ActionMethod].cshtml
For example, for a controller:
public IActionResult View1()
{
return View();
}
public IActionResult View2()
{
return View();
}
The usual folder structure for this should be:
Now, in this specific case. The usual way to offer a ContactUs page, is making this one an ActionMethod of the HomeController, instead of creating an entire controller for it.

ASP.NET MVC 5 URL Depend on Selection

I have a page created on VS13 MVC 5 based on ASP.NET, on my navigator I have my dropdown menu
While I click on Phones link I have URL as: www.sitename.com/phones and it will list all phones which I have on my data base, while I choose a brand (e.g: Samsung) I want my URL will be www.sitename.com/phones/samsung
Simple question I don't want create a view for each brand or model of phone because there are a lot, I can just use SQL and list them on the same page but how to change my URL depending on my choice ? Is the only way is Attribute Routing?
Appreciate any suggestion.
If you are using JS/jQuery you can use the History.js api. https://github.com/browserstate/history.js/
You can then use History.pushState(insert parameters here);. This will not only change the url to your choice but also allow users to go back and forward like usual, it also keeps SEO with web crawlers I think.
You can add a Route to your route config
in RouteConfig.cs
routes.MapRoute(
name: "Product",
url: "{controller}/{productCategory}/{productName}",
defaults: new { controller = "Product", action = "Index", productCategory = UrlParameter.Optional, productName = UrlParameter.Optional }
);
in product controller
public ActionResult index(string productCategory,string productName)
{
//return items by productCategory/ProductName
}

Controller MVC3 link to Folder/Controller/View

I currently got a problem with the namespaces I added this into my global.asax:
routes.MapRoute(
"Admin",
"Admin/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
null, new string[] {"project.Controllers.Admin"}
);
Now my controller is being reached when I type into the url localhost/Admin/Controller/*
Put my controller isn't giving me the right Views. It's giving me the View in Controller/Views. And I want the Views located in Admin/Controller/Views. I tried linking to them directly but thats not going to well. Any idea how this is done?
If you're using ASP.Net 2 or higher, you probably should be adding this Admin section as an ASP.Net MVC Area. Areas are like mini MVC sites with-in separate folders, which should solve your question.

ASP.NET MVC 2 Areas 404

Has anyone been able to get the Areas in ASP.NET MVC 2 to work?
I created a new Area called "Secure" and placed a new controller in it named HomeController. I then Created a new Home/Index.aspx view. However, when I browse to http://localhost/myapp/Secure/ it gives a 404 resource cannot be found. http://localhost/myapp/Secure/Home gives the same error.
My area registration looks like this:
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Secure_default",
"Secure/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
I also tried this:
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Secure_default",
"Secure/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Thanks,
Justin
I am pretty sure it was because your area registration class was in a different namespace that the project it was hosted in. It would explain why your solution worked - you registered it with the overload that takes in the namespace. I had a similar issue and it was fixed by correcting the namespace.
Sure, i've got Areas working with ASP.NET MVC 2.
Its hard for people to debug routes over SO, the easiest way is for you to use Phil Haacks Route Debugger. It'll tell you what routes (and areas) are being resolved for a particular URL. Extremely handy.
However ill take a stab, try changing your route to this:
context.MapRoute(
"Secure_default",
"Secure",
new { action = "Index", controller = "Home", id = UrlParameter.Optional }
);
The url (<yourhost>/Secure) will find your area Secure but not know which controller you hand the request to, as you have not specified a default value for controller in your areas route.
Here's my setup:
Areas
Albums
Controllers
AlbumsController.cs (namespace Web.Areas.Albums.Controllers)
Models
Views
Albums
Index.aspxx
AlbumsAreaRegistration.cs
context.MapRoute(
"Albums_Default",
"Albums",
new { controller = "Albums", action = "Index", id = UrlParameter.Optional)
The URL: http://localhost/Albums triggers the "Index" action of my "AlbumsController" in my "Albums" area.
What does you structure look like?
I got it working, the answer was to change the area registration class to this:
context.MapRoute(
"Secure_Default", // Route name
"Secure/{controller}/{action}/{id}", // URL with parameters
new { area="Secure", controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
new[] { typeof(Controllers.HomeController).Namespace }
);
I have no idea why it worked for another developer and not for me, also I feel like it should "just work" out of the box when you create a new Area, you shouldn't have to fiddle with the route mapping.
Anyway, thanks all for the help and I'm giving the answer to RPM for all his hard work.
Are you calling AreaRegistration.RegisterAllAreas() in your global.asax?
Sub Application_Start()
AreaRegistration.RegisterAllAreas()
RegisterRoutes(RouteTable.Routes)
End Sub
Have you tried using http://localhost/myapp/Secure/Home/index ? I find so many times that when I use index as the view name and don't specify it in the path it never works. It should work but it never works for me.
I don't like calling my views index anyways so not a big deal for me.

Resources