I have the following action
public ActionResult TemplateBuilder(int id, int? processId) { }
And then I have the following
#Url.Action("TemplateBuilder","InspectionTemplate")/id/processId
The url then looks like: InspectionTemplate/TemplateBuilder/1/2
But if I use
return RedirectToAction("TemplateBuilder","InspectionTemplate", new { id=1, processId = 2});
Then I get the following result: InspectionTemplate/TemplateBuilder/1?processId=2
How can I fix that.
Here is my Routing
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "IDRoute",
url: "{controller}/{action}/{id}",
defaults: new
{
controller = "Login",
action = "Index",
id = UrlParameter.Optional
}
);
routes.MapRoute(
name: "ProcessRoute",
url: "{controller}/{action}/{id}/{processId}",
defaults: new
{
controller = "InspectionTemplate",
action = "TemplateBuilder",
id = UrlParameter.Optional,
processId = UrlParameter.Optional
}
);
routes.MapRoute(
name: "DateRoute",
url: "{controller}/{action}/{year}/{month}/{day}",
defaults: new
{
controller = "Inspection",
action = "Assign",
year = UrlParameter.Optional,
month = UrlParameter.Optional,
day = UrlParameter.Optional
}
);
}
You have 3 issues with your route definitions
Only the last parameter in a route definition can be marked with
UrlParameter.Optional. If you were to provide only one, then the
routing engine has no way of knowing which parameter should be bound
so the value(s) would be added as query string parameters).
The main issue however is the order of the routes. The routing
engines searches the definitions in the order they are declared and
stops as soon as it finds a matching one, and in your case the
IDRoute will match so the routes need to be swapped.
That alone however may cause issues with other route definitions, so
its best to make your route uniquely identifiable, for example by
specifying the controller name in the route definition.
Your definitions should be
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "ProcessRoute",
url: "InspectionTemplate/{action}/{id}/{processId}",
defaults: new { controller = "InspectionTemplate", action = "TemplateBuilder", processId = UrlParameter.Optional }
);
routes.MapRoute(
name: "DateRoute",
url: "Inspection/{action}/{year}/{month}/{day}",
defaults: new { controller = "Inspection", action = "Assign", } // assumes all parameters are required
);
// The default will only be match if the url does not start with '/InspectionTemplate/' or '/Inspection/'
routes.MapRoute(
name: "IDRoute",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional }
);
}
Related
I have a website that need a departmentID for all sites, so i rewrote the default route to the following:
routes.MapRoute(
name: "Main",
url: "{deptID}/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", deptID = "", id = UrlParameter.Optional }
);
It works fine when you for example use the following URL:
http://domain/2/Home/Index
or just simply:
http://domain/2
My problem is that when i go to "http://domain/" i get an error because i dont have specified the departmentID.
How can i add a second route which will fire when you just go to the domain.
I have tried to add the following:
routes.MapRoute(
name: "Start",
url: "/",
defaults: new { controller = "Department", action = "Select"}
);
Which doesnt work since you cant just put "/" as an URL.
I have also tried to add the default route and then just change the defaults object:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Department", action = "Select", id = UrlParameter.Optional }
);
This doesnt work either.
You have to modify your code as below
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Department",
url: "{deptID}/{controller}/{action}",
defaults: new { controller = "Department", action = "Index"}
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Output
Let me know if the above code still not worked for you.
I have this in my RouteConfig:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "StoreSearch",
url: "{storeName}",
defaults: new { controller = "Search", action = "Store" }
);
Basically I have a 2nd route so if I type in localhost:9000/facebook there is no such controller by the name of facebook so my 2nd router should pickup facebook as the storeName and hit my Search controller's Store action. But at the moment I get 404.
Any ideas how do I fix this?
If you have specific set of stores or a way to verify them you can add a constraint to the route.
To add a generic constraint with match predicate
public class ServerRouteConstraint : IRouteConstraint
{
private readonly Func<Uri, bool> _predicate;
public ServerRouteConstraint(Func<Uri, bool> predicate)
{
this._predicate = predicate;
}
public bool Match(HttpContextBase httpContext, Route route, string parameterName,
RouteValueDictionary values, RouteDirection routeDirection)
{
return this._predicate(httpContext.Request.Url);
}
}
and then in the route add a paramater
routes.MapRoute(
name: "StoreSearch",
url: "{storeName}",
defaults: new { controller = "Search", action = "Store" }, constraints:
//this could be new { controller ="pattern" }
new {
serverRoute = new ServerRouteConstraint(url =>
{
//this will check that the route starts with a specific string in this case Settings
return url.PathAndQuery.StartsWith("/Settings",
StringComparison.InvariantCultureIgnoreCase);
})
});
For examples check: https://www.c-sharpcorner.com/UploadFile/dacca2/route-constraints-in-mvc/
Also, routes should be added from most specific to most general.
You should place any custom route above the Default route.
Just swap the order and you good to go
//before default route
routes.MapRoute(
name: "StoreSearch",
url: "{storeName}",
defaults: new { controller = "Search", action = "Store" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
I want to have my URL to be /{page number} for my home page for example localhost:50915/1 for page 1 for a list of records, my URL routing is as follows:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "EditForm",
url: "{controller}/{formid}",
defaults: new { controller = "ManageForm", action = "Update", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Home",
url: "{page}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
The second MapRoute method is the one which I added to perform the desirable action. It works perfectly fine, but whenever I try to access another Controller "ManageController" for e.g localhost:50915/ManageForm it returns me the home page (same page showing the list of records).
Here is a snapshot of my solution:
Whenever I tried to remove the lines of codes which perform this URL rerouting for the Home Page pagination, everything works fine, but of course the URL will be as localhost:50915?page=1
My HomeController is as follows:
public class HomeController : Controller
{
//
// GET: /Home/
[HttpGet]
public ViewResult Index(int page = 1)
{
const int pageSize = 4;
FormCollection forms = FormService.GetAllActiveForms(page, pageSize);
var formModel = new FormListViewModel
{
Forms = forms,
PagingInfo = new PageInfo
{
PageNumber = page,
PageSize = pageSize,
TotalItems = forms.Count > 0 ? forms[0].TotalRecord : 0
}
};
return View(formModel);
}
}
Help much appreciated thanks.
You cannot use localhost:50915/ManageForm cause it conflicts with another route definition. MVC does not see the difference between "{controller}/{formid}" and "{page}" when your route parameter is optional.
You have to use your first route as localhost:50915/ManageForm/{formId} to get it working.
Solution would be to map a new routing for the manage form to result in the url /ManageForm/Create
I have changed the RouteConfig.cs as follows:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//<host>/{page}
routes.MapRoute(
name: "Home",
url: "{page}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
//ManageForm/Create
routes.MapRoute(
name: "CreateForm",
url: "{controller}/Create",
defaults: new { controller = "ManageForm", action = "Index", id = UrlParameter.Optional }
);
//ManageForm/{formid}
routes.MapRoute(
name: "EditForm",
url: "{controller}/{formid}",
defaults: new { controller = "ManageForm", action = "Update", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Im trying to make a custom router for my mvc-learning project.
I want to keep the standrard route that directs to {controller}/{action}/{id} in case of a URL like
domain.com/user/details/72
but if i get a url like this one
domain.com/2
i want to route to a specifik controller action that takes the number as an id. So i dont want the URL to specify controller and action, cause i want the url to be real short and the controller and action should always be the same.
Ive kind of made it work but i get very strange unpredictable results so i wanted to ask if im doing something very weird. Here are my routes:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "DisplayKombak",
url: "{kombakId}",
defaults: new { controller = "Kombak", action = "DisplayKombak", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
Try something like this:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "DisplayKombak",
url: "{kombakId}",
defaults: new {controller = "Kombak", action = "DisplayKombak"}
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new {controller = "Home", action = "Index", id = UrlParameter.Optional}
);
}
}
And KombakController.cs:
using System.Web.Mvc;
namespace WebApplication1.Controllers
{
public class KombakController : Controller
{
public ActionResult DisplayKombak(string kombakId)
{
return View();
}
}
}
You may be able to force this behavior by adding route constraints.
routes.MapRoute(
name: "DisplayKombak",
url: "{kombakId}",
defaults: new { controller = "Kombak", action = "DisplayKombak", id = UrlParameter.Optional },
new {kombakId = #"\d+" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new {controller = #"\D+" }
);
The constraint on the first route will prevent the route from matching unless the first route segment is an integer, the constraint on the second route will prevent the route from matching if the first route segment is not a string of letters.
I'm working on an image viewer, so I've a controller named Viewer and when I pass it routeValues it is passed in the URL like this :
http://www.mywebsite.com/Viewer?category=1&image=2
Here is the link used to get on this page :
#Url.Action("Index", new { category = p.Category, image = p.Image })
But I do like to have this URL :
http://www.mywebsite.com/Viewer/1/2
I have tried to do a few tricks in the RegisterRoutes method of the RouteConfig class but I can not get the previous result.
public class RouteConfig
{
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 }
);
routes.MapRoute(
name: "Viewer",
url: "{controller}/{action}/{category}-{image}",
defaults: new { controller = "Viewer", action = "Index", category = 1, image = 1 }
);
}
}
Does anyone know where I can do this?
Thanks a lot !
You need to put your more specific route before the default route, because the routes are evaluated in the same order in which you declared them:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Viewer",
url: "{controller}/{action}/{category}/{image}",
defaults: new { controller = "Viewer", action = "Index", category = 1, image = 1 }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}