Action attribute that restrict action method by url pattern - c#

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();
}
}

Related

Is there any way to make a custom route in C# MVC? [duplicate]

This question already has answers here:
Routing in ASP.NET MVC, showing username in URL
(2 answers)
Closed 4 years ago.
I am new to C# MVC,
This is my default RouteConfig File,
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 }
);
}
}
When I run my project http://localhost:50382 it redirects the default home index method.
How can I build custom url like http://localhost:50382/somestringcode and call a specific ActionMethod. Something Like a custom route that points to specific ActionMethod and the stringcode will be passed as parameter.
public ActionResult Method1( string code)
{
return View();
}
What you are searching for is attribute routing. That means specifying URL routes explicitly.
First, you need to enable it
routes.MapMvcAttributeRoutes();
Then add Route attribute to desired action:
[Route("")]
public ActionResult Method1( string code)
{
return View();
}
Since code parameter is simple type, it will be searched in request URL.
You need to do something like this, where controller1 is the controller name that contains Method1, and make sure you place this first, and leave the original route config, so when it doesn't match this route, it will use default route.
Please note this is bad practice, and it will fail in case route is trying to access default action for a controller "Index" as #stephen mentioned in the comments below, and that's why I would suggest adding a prefix ex "Action1" to the route.
routes.MapRoute
(
name: "Method1",
url: "Action1/{code}",
defaults: new { controller = "controller1", action = "Method1", code = "default"}
);

MVC Conventional and Attribute routing not working together

I am using conventional routing on an ASP.Net MVC project and would like to enable Attribute routing in parallel. I have created the following but I am getting a 404 on the conventional route when enabling attribute routing
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Controller
[RoutePrefix("Registration")]
public class RegistrationController : Controller
{
[HttpGet]
[Route("Add/{eventId}")]
public ActionResult Add(int eventId)
{
}
}
Calling
http://localhost/Registration/Add/1
Works, while calling
http://localhost/Registration/Add?eventId=1
No longer works and responds with 404 NotFound
Should work if you make the {eventId} template parameter optional in the route template
[RoutePrefix("Registration")]
public class RegistrationController : Controller {
//GET Registration/Add/1
//GET Registration/Add?eventId=1
[HttpGet]
[Route("Add/{eventId:int?}")]
public ActionResult Add(int eventId) {
//...
}
}
The reason the two were not working is that the route template Add/{eventId} means that the route will only match if the {eventId} is present, which is why
http://localhost/Registration/Add/1
works.
By making it (eventId) optional eventid? it will allow
http://localhost/Registration/Add
to work as the template parameter is not required. This will now allow query string ?eventId=1 to be used, which the routing table will use to match the int eventId parameter argument on the action.
http://localhost/Registration/Add?eventId=1
I also got this issue. Which MVC version are you using?
I faced this issue with MVC in asp.net core.
I think this is a flaw as if you provide Routing attribute on any action method, its conventional route is over ridden and is not longer available so you get 404 error.
For this to work, you can provide another Route attribute to your action method like this. This will work
[Route("Add/{eventId}")]
[Route("Add")]

Multiple controllers, same same controller name

I was wondering if this is possible. Say I have a monolithic Controller, ReportController.cs.
I want to make a totally separate controller file but still keep the /Report/ in the url that we've some to know and expect.
What I tried was this in my global asax:
routes.MapRoute(
"Testing", // Route name
"{test}/{action}/{id}" // URL with parameters
);
and I added a new Controller named ReportTest.cs
the original route looks like this:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "LandingPage", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
Every time I try to call the simple action I have in ReportTest.cs I get this error: "Value cannot be null or empty. Parameter name: controllerName"
Am I misunderstanding how this works. When you have "{controller}/.." is this not saying 'look for any controllers named + controller and use that'. So if I go to .../Report/DoStuff it'll look for the method DoStuff on ReportController right?
So wouldn't my other route just append a search sequence? So if I put .../Report/DoStuff it'll look for the method DoStuff on ReportController and ReportTest right?
The routing format string:
{controller}/{action}/{id}
Means: the first part ("part" being "element after splitting on /") of the request URI is the controller name, the next part the action method and the last part the ID.
The placeholders {controller} and {action} are special. So your route {test}/{action}/{id} will not find any controller, as none is specified, and {test} doesn't mean anything. (Well it does, it'll get added as a route attribute named "test", and assigned a value representing that part of the request URI, so that is irrelevant for this scenario).
If you want to route an URI to a controller that is not mentioned in the URI, then you must literally specify the prefix, and the controller it should be routed to.
So your routing will look like this:
routes.MapRoute(
"SecondReportController",
"Report/NotOnReportController/{id}",
new { controller = "NotAReportController" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "LandingPage", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
Then you can use the following controller:
public class NotAReportController : Controller
{
public ActionResult NotOnReportController(int id)
{
// ...
}
}
You can of course also use attribute routing instead:
public class NotAReportController : Controller
{
[Route("Report/NotOnReportController/{id}")]
public ActionResult NotOnReportController(int id)
{
// ...
}
}

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 = "") {
// ...
}
}

Displaying View of MVC in browser that dont have controller or action

In MVC, I have created a .cshtml file in the path "App/Main/Views".
I dont have any controller or Action for this file. But I need to display the content of .cshtml file in browser.
Please, let me know how I should give route path in 'RouteConfig.cs' file to achieve the above scenario.
Asp.Net MVC is based around Controllers that return views. Your routes point to Actions in Controllers that render Views. What you seem to be looking for is a static view which in this case can be handled as a pure *.html-file instead.
If you have no Controller or Action, it shouldn't be a view.
You can try this configuration
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 = "Main", action = "Index", id = UrlParameter.Optional }
);
}
}
And then in your MainController return that view this way:
public class MainController : Controller
{
// GET: Main
public ActionResult Index()
{
return View("MyView", new MyViewModel{ title = "blabla"});
}
}

Categories

Resources