Issue/Try 1:
I have a custom route map:
routes.MapRoute(
name: "User Profile",
url: "User/{userId}/{controller}/{action}/{id}",
defaults: new { Areas = "User", controller = "Kpi", action = "Index", id = UrlParameter.Optional }
);
If i manually navigate to the URL /User/f339e768-fe92-4322-93ca-083c3d89328c/Kpi/View/1 the page loads with a View Error: The view 'View' or its master was not found or no view engine supports the searched locations.
Issue/Try 2:
Stopped using the custom route and set up my controller as instead:
[RouteArea("User")]
[RoutePrefix("{userId}/Kpi")]
public class KpiController : BaseUserController
{
[Route("View/{id}")]
public async Task<ActionResult> View(string userId, int? id = null)
{
[...]
}
}
This now works i can navigate to the URL and the View displays fine.
Issue for both:
Although I can navigate manually to both and they load I can't seem to generate the URL correctly using ActionLink:
#Html.ActionLink(kpi.GetFormattedId(), "View", "Kpi", new { Area = "User", userId = Model.Id, id = kpi.Id }, null)
It generates: /User/Kpi/View/1?userId=f339e768-fe92-4322-93ca-083c3d89328c instead of /User/f339e768-fe92-4322-93ca-083c3d89328c/Kpi/View/1
URL Mapping
After some time i have found the solution for the custom mapping i was adding in the main RouteConfig.cs and not in the Area Registration. Moving the MapRoute to the Area works correctly and without the RouteArea, RoutePrefix and Route attributes in the Controller.
Area Registration
public class UserAreaRegistration : AreaRegistration
{
public override string AreaName => "User";
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
name: "User",
url: "User/{userId}/{controller}/{action}/{id}",
defaults: new { action = "Index", id = UrlParameter.Optional }
);
context.MapRoute(
"User_default",
"User/{controller}/{action}/{id}",
new {action = "Index", id = UrlParameter.Optional}
);
}
}
Links
Instead of using ActionLink i am now using RouteLink.
#Html.RouteLink("KPIs", "User", new { Controller = "Kpi", Action = "Index", userId = Model.Id })
Related
I am in https://localhost:44311/ and I have those 2 buttons
When I press the Customers button I want to go to https://localhost:44311/Customers and see a list of the current Customers. Similarly https://localhost:44311/Movies and see a list of movies.
For those two I have two Controllers, named MoviesController and CustomersController.
This is my code in CustomersController:
namespace MovieLab.Controllers
{
public class CustomersController : Controller
{
public ActionResult AllCustomers()
{
var customers = new List<Customer>
{
new Customer(){ Name = "Customer 1"},
new Customer(){ Name = "Customer 2" }
};
var customerViewModel = new CustomerViewModel()
{
Customers = customers
};
return View(customerViewModel);
}
}
when I build the code above, my URL looks like this https://localhost:44311/Customers/AllCustomers
shouldn't it be https://localhost:44311/AllCustomers? (I named it AllCustomers so the URL doesn't look like Customers/Customers)
Your Default route in RouteConfig.cs looks like this:
url: "{controller}/{action}/{id}"
This will generate a url like:
https://localhost:44311/Customers/AllCustomers
Now to generate your required url, you need to set the route as (add it before the default one):
routes.MapRoute(
name: "MyRoute",
url: "allcustomers",
defaults: new { controller= "Customers", action = "AllCustomers", id = UrlParameter.Optional }
);
// default route
routes.MapRoute("Default", "{controller}/{action}/{id}", new {controller = "Home", action = "Index", id = UrlParameter.Optional} );
The default url of the application is
http://servername/Root/ITProjects
There is a menu item with 'Team' on the default page which should redirect to another controller with index which will display a dropdownlist at the following url
http://servername/Root/ITProjects/Team
It's working fine so far.
However when the user selects an item in the dropdownlist, it should go to the url below
http://servername/Root/ITProjects/Team/Index?Id=7
But it's directing to
http://servername/Team/Index?Id=7
and throwing the 404 error. It is missing the folder path 'Root/ITProjects' after the servername. It's working fine on localhost where there is no folder path but failing on deployment to test or prod servers
[AuthorizeAD(Groups = "APP_xxxx_Users")]
public class TeamController : Controller
{
public int pageSize = 5;
private IProjectService _projectService;
public TeamController(IProjectService projectService)
{
this._projectService = projectService;
}
public ActionResult Index(int? Id, int? page)
{
int pageNumber = (page ?? 1);
var viewModel = new TeamViewModel();
if (Id != null)
{
viewModel.SelectedMember = (int)Id;
viewModel.Tasks = this._projectService.GetTasksByStaff(viewModel.SelectedMember).ToPagedList(pageNumber, pageSize);
}
return View(viewModel);
}
[HttpPost, ActionName("Index")]
public ActionResult IndexPost(int Id, int? page)
{
int pageNumber = (page ?? 1);
var viewModel = new TeamViewModel();
viewModel.SelectedMember = Id;
if (ModelState.IsValid)
{
viewModel.Tasks = this._projectService.GetTasksByStaff(viewModel.SelectedMember).ToPagedList(pageNumber, pageSize);
}
return View(viewModel);
}
}
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 }
);
}
As part of Index view when dropdownlist item is selected
#Html.DropDownListFor(m => m.SelectedMember, new SelectList(Model.StaffList, "UniqueId", "Initials", Model.SelectedMember), new { #class = "btn btn-default btn-color", onchange = #"form.action='/Team/Index?Id=' +this.value;form.submit();" })
Your MVC application is in a sub-directory of another application, so IIS considers the root of the parent application instead of the root of your MVC application.
In IIS, you need to convert the virtual directory to an Application: choose your virtual directory and "Convert to Application." If you are unable to do that, then you need to modify your routes in routes.config to take the virtual directory into account:
routes.MapRoute(
"Default", // Route name
"Root/ITProjects/{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
your default route for controllers looks like this :
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
You can add /Root/ITProjects/ before the URL to change the default controller path
I am trying to remove area name and controller name from URL.I am able to remove area name. But if trying to remove controller name then "Page not found error" displayed. Below is the code snippet which I have used to remove the area and controller name.
public class HomeAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Home";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
//context.MapRoute(
// "Home_default",
// "Home/{controller}/{action}/{id}",
// new { action = "Index", id = UrlParameter.Optional }
//);
//context.MapRoute(
// "Home_default",
// "{controller}/{action}/{id}",
// new { action = "Index", id = UrlParameter.Optional },
// new { controller = "(Home)" }
//);
context.MapRoute(
"Home_default",
"{action}/{id}",
new { action = "Index", id = UrlParameter.Optional },
new { controller = "(Home)" }
);
}
}
In the registerarea function the first two routes(commented) are working perfectly. if I use the first one the URL comes with Area/Controller/Action. If I use second one the area is not coming in URL.The URL come ups with Controller/Action.
In the third one I am trying to remove both area and Controller
Is any thing wrong in my third route. Please suggest
Have you tried this:
routes.MapRoute("default", "{action}/{id}", new {controller = "Home", action = "Index", id = UrlParameter.Optional});
I have a problem with back linking from area view to non area view.
Current structure
Web application tree:
/Controller/BaseController.cs
/Views/Base/Index.cshtml
/Areas/Area1/Controller/SettingsController.cs
/Areas/Area1/Views/Setting/Index.cshtml
Default route config:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute(
name: "Localization",
url: "{culture}/{controller}/{action}/{id}",
defaults: new { culture = "de-DE", area = "", controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { area = "", controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
Area route config:
public class Area1AreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Area1";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Photovoltaics_localized",
"{culture}/Photovoltaics/{controller}/{action}/{id}",
new { culture = "de-DE", action = "Index", id = UrlParameter.Optional }
);
context.MapRoute(
"Area1_default",
"Area1/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
}
Register route configs (Global.asax.cs)
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
[..]
Problem
When I'm inside a base view (/Views/Base/Index.cshtml) the code #Html.ActionLink("My home link", "Index", "Home") generates the link I expected http://localhost:81/de-DE/Home .
When I'm inside a area view (/Areas/Area1/Views/Setting/Index.cshtml) the same code generates a link http://localhost:81/de-DE/Area1/Home but this points to nowhere.
Tried so far
I learned that the code #Html.ActionLink("My home link", "Index", "Home", new { area = ""}, null) works in both, area and non area views and leads to the correct http://localhost:81/de-DE/Home view.
Question
How can I structur my route configs in a way that calling a link creation methode with no area as parameter always links to the base views/controllers?
Or is there a better solution to achieve this?
What I expect is:
#Html.ActionLink("My home link", *action*, "controller")
= http://localhost:81/de-DE/action
#Html.ActionLink("My home link", *action*, *controller*, new { area = *area*}, null)
= http://localhost:81/de-DE/area/action
This has nothing to do with routing. This is the default behaivor for the ActionLink method URL creation. You can see this on the following code (taken from the ASP.NET MVC codeset):
if (values != null)
{
object targetAreaRawValue;
if (values.TryGetValue("area", out targetAreaRawValue))
{
targetArea = targetAreaRawValue as string;
}
else
{
// set target area to current area
if (requestContext != null)
{
targetArea = AreaHelpers.GetAreaName(requestContext.RouteData);
}
}
}
As you can see if you don't pass a value for area, it will take the current area you are in.
The only solution I can think of, would be to create your own HTML extension. Something similar to this:
public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName)
{
return htmlHelper.ActionLink(linkText, actionName, controllerName, new { area = String.Empty });
}
I have some controllers in root and I've registered its rout like this as default:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
And I have an area named 'Admin' which its rout registered like this:
public class AdminAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Admin";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Default_Admin",
"Admin/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
}
My problem is that user can request an action inside a controller (e.g: UserController/Index) in Admin area without specifying its area in url.
I mean these urls both are same:
http://localhost:2374/Admin/Default1/Index
http://localhost:2374/Default1/Index
And I want to avoid the second url.
Thanks