Routing optional parameters in ASP.NET MVC 5 - c#

I am creating an ASP.NET MVC 5 application and I have some issues with routing. We are using the attribute Route to map our routes in the web application. I have the following action:
[Route("{type}/{library}/{version}/{file?}/{renew?}")]
public ActionResult Index(EFileType type,
string library,
string version,
string file = null,
ECacheType renew = ECacheType.cache)
{
// code...
}
We only can access this URL if we pass the slash char / in the end of url, like this:
type/lib/version/file/cache/
It works fine but does not work without /, I get a 404 not found error, like this
type/lib/version/file/cache
or this (without optional parameters):
type/lib/version
I would like to access with or without / char at the end of url. My two last parameters are optional.
My RouteConfig.cs is like this:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
}
}
How can I solve it? Make the slash / be optional too?

Maybe you should try to have your enums as integers instead?
This is how I did it
public enum ECacheType
{
cache=1, none=2
}
public enum EFileType
{
t1=1, t2=2
}
public class TestController
{
[Route("{type}/{library}/{version}/{file?}/{renew?}")]
public ActionResult Index2(EFileType type,
string library,
string version,
string file = null,
ECacheType renew = ECacheType.cache)
{
return View("Index");
}
}
And my routing file
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// To enable route attribute in controllers
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}
I can then make calls like
http://localhost:52392/2/lib1/ver1/file1/1
http://localhost:52392/2/lib1/ver1/file1
http://localhost:52392/2/lib1/ver1
or
http://localhost:52392/2/lib1/ver1/file1/1/
http://localhost:52392/2/lib1/ver1/file1/
http://localhost:52392/2/lib1/ver1/
and it works fine...

//its working with mvc5
[Route("Projects/{Id}/{Title}")]
public ActionResult Index(long Id, string Title)
{
return view();
}

Related

MapMvcAttributeRoutes ignores [NonAction] attribute

Any public method that returns string, bool or ActionResult in a Controller class is seen as an Action. If you want to mark it as not being an action, you can use the [NonAction] attribute:
[NonAction]
public bool PubMethod( out string param1)
{
return false;
}
this works fine if you do not use attribute mapping routing. The app starts and the method is not seen as an action (it cannot be used as such, since it has an out param), everybody is happy.
If instead you use attribute routing:
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapMvcAttributeRoutes();
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
the [NonAction] attribute is ignored, and the app crashes on the line
routes.MapMvcAttributeRoutes();
complaining that the PubMethod action cannot be called because it has a by ref parameter.
I can't find any mention of this in the docs. Any way to mark a public method as non action when attribute routing is used?

Action attribute that restrict action method by url pattern

Is there an action attribute that allows restricting action method by url pattern?
In my controller, I would like to to have two SearchOrder actions. One for editing order and one for viewing order. If the url path is /Order/EditOrder/SearchOrder/1, I would want it to execute this action.
[HttpGet]
[ActionName("SearchOrder")]
public ActionResult EditOrderSearchOrder()
{
. . . .
}
But if the url path is /Order/ViewOrder/SearchOrder/1, I would want it to execute this action.
[HttpGet]
[ActionName("SearchOrder")]
public ActionResult ViewOrderSearchOrder()
{
. . . .
}
There are many ways. Some of them are
Write in RouteConfig.cs
routes.MapRoute(
name: "Properties",
url: "Order/EditOrder/SearchOrder/{action}/{id}",
defaults: new
{
controller = "YourControllerName",
action = "SearchOrder",\\ bcoz you have given action name attribute otherwise your method name
id = UrlParameter.Optional \\ you can Change optional to Fixed to make passing Id parameter compulsory
}
);
If using Mvc5, you can do Attribute Routing by following a simple syntax:
[Route("Order/EditOrder/SearchOrder/{id?}")] // ? For optional parameter
public ActionResult EditOrderSearchOrder(){}
And
To enable attribute routing, call MapMvcAttributeRoutes in RouteConfig.cs
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute(“{resource}.axd/{*pathInfo}”);
routes.MapMvcAttributeRoutes();
}
}

ASP.NET MVC 5 route config

I have 2 routes:
college/{courseId}/{classId}
college/{courseId}
But sometime when I try to input the 1st url type like college/course1/class2, it go to the 2nd action.
Can I fix route configuration to do it exactly? Here is my code:
[Route("college/{courseId}/{classId}")]
public void ActionResult example1(string courseId, string classId) {
return View();
}
[Route("college/{courseId}")]
public void ActionResult example2(string courseId) {
return View();
}
RouteConfig.cs file:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
AreaRegistration.RegisterAllAreas();
routes.MapMvcAttributeRoutes();
//Default
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
This may be helpful to you.
https://www.nuget.org/packages/routedebugger/
It will show you what routes are matched.
I suspect that they both are matched but are added in the incorrect order.
It may be as simple as inverting the order in which they are adding or making them more specific. ( making the params required)
I recommend you to define only one route and have only one action with an optional parameter:
[Route("college/{courseId}/{classId?}")]
public void ActionResult example1(string courseId, string classId) {
// Do classId null check if necessary
return View();
}
Please notice, there is a question mark after classId parameter in route definition.

MVC 5 routing with 1 parameter

I want the url to be
domain.com/doc/{project}
I have a controller called Projects or "ProjectsController.cs."
This controller has an action (ActionResult) I want to reach with my custom url route called "DocumentationIndex."
DocumentationIndex does have a parameter. It's a simple string parameter.
The following continues to give me a 404.
routes.MapRoute(
name: "Documentation",
url: "doc/{project}",
defaults: new { controller = "Projects", action = "DocumentationIndex", project = "" }
);
Can anyone point me in the right direction?
You can use attribute routing to define this within the controller:
public class ProjectsController
{
[Route("doc/{*project}")]
public ActionResult DocumentationIndex(string project = "")
{ // ... }
}
You'll need to ensure attribute routing is enabled in your Route Config:
routes.MapMvcAttributeRoutes();
The * in the {*projects} will ensure that the route parameter matches the rest of your URL, even if it contains special characters.
Try this:
routes.MapRoute(
"Documentation",
"doc/{project}",
new { controller = "Projects", action = "DocumentationIndex" }
);
Your controller code:
public class ProjectsController ... {
//
public ActionResult DocumentationIndex(string project = "") {
// ...
}
}

ASP.NET MVC Page-URL and Controller/Action Routing

I have problems building an ASP.NET MVC page which allows two sorts of routing.
I have a database where all pages are stored with an url-path like: /Site1/Site2/Site3
i tried to use an IRouteConstraint in my first route, to check wether the requested
site is a site from my database (permalink).
In the second case, i want to use the default asp.net mvc {controller}/{action} functionality, for providing simple acces from an *.cshtml.
Now i don't know if this is the best way. Furthermore i have the problem, how to root with the IRouteContraint.
Does anyone have any experiance with this?
I'm using asp.net mvc 5.
Problem solved, final solution:
Adding this two routes:
routes.MapRoute(
"FriendlyUrlRoute",
"{*FriendlyUrl}"
).RouteHandler = new FriendlyUrlRouteHandler();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Page", action = "Load", id = UrlParameter.Optional },
namespaces: controllerNamespaces.ToArray()
);
My own Route-Handler:
public class FriendlyUrlRouteHandler : System.Web.Mvc.MvcRouteHandler
{
protected override IHttpHandler GetHttpHandler(System.Web.Routing.RequestContext requestContext)
{
var friendlyUrl = (string)requestContext.RouteData.Values["FriendlyUrl"];
WebPageObject page = null;
if (!string.IsNullOrEmpty(friendlyUrl))
{
page = PageManager.Singleton.GetPage(friendlyUrl);
}
if (page == null)
{
page = PageManager.Singleton.GetStartPage();
}
// Request valid Controller and Action-Name
string controllerName = String.IsNullOrEmpty(page.ControllerName) ? "Page" : page.ControllerName;
string actionName = String.IsNullOrEmpty(page.ActionName) ? "Load" : page.ActionName;
requestContext.RouteData.Values["controller"] = controllerName;
requestContext.RouteData.Values["action"] = actionName;
requestContext.RouteData.Values["id"] = page;
return base.GetHttpHandler(requestContext);
}
}
You can use attribute routing which is in MVC 5 and combine attribute routing with convention-based routing to check the condition that you want on controller class or action methods.
And you could make the constraint yourself to use it on the action methods like this:
public class ValuesConstraint : IRouteConstraint
{
private readonly string[] validOptions;
public ValuesConstraint(string options)
{
validOptions = options.Split('|');
}
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
object value;
if (values.TryGetValue(parameterName, out value) && value != null)
{
return validOptions.Contains(value.ToString(), StringComparer.OrdinalIgnoreCase);
}
return false;
}
}
To use attribute routing you just need to call MapMvcAttributeRoutes during configuration and call the normal convention routing afterwards. also you should add your constraint before map the attributes, like the code below:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
var constraintsResolver = new DefaultInlineConstraintResolver();
constraintsResolver.ConstraintMap.Add("values", typeof(ValuesConstraint));
routes.MapMvcAttributeRoutes(constraintsResolver);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Now on your controller class you can check the route and decide what to do with different urls like below:
for example: // /mysite/Site1 and /mysite/Site2 but not /mysite/Site3
[Route("mysite/{site:values(Site1|Site2)}")]
public ActionResult Show(string site)
{
return Content("from my database " + site);
}
And you could do all kind of checking just on you controller class as well.
I hope this gives you a bit of clue to achieve the thing that you want.

Categories

Resources