Passing arguments to Url.Action - asp.net

What is the difference between these two ways of passing arguments to an Action?
(1) #Url.Action("MyAction", "MyController")?arg1=5&arg2="hello";
(2) #Url.Action("MyAction", "MyController", new {arg1=5, arg2="hello"});

The difference is whether you're taking ASP.Net Routing into account.
Assuming you have a route defined as follows:
routes.MapRoute(
name: "CallMyAction",
url: "CallMyAction/{arg1}-{arg2}",
defaults: new { controller = "MyController", action = "MyAction" });
Your 1st call would generate the following URL:
/CallMyAction?arg1=5&arg2=hello
While the 2nd call would generate a URL that is adhering the route pattern you defined:
/CallMyAction/5-hello

Related

How to add MessageHandler for a specific controller that is using Routing Attributes in ASP.NET WebAPI 2?

It is possible to add a MessageHandler only for a specific controller that is using Route Attributes?
I want to cut the request earlier in the pipeline if it doesn't contain certain headers. I want to
mention that:
I can't add another route in WebApiConfig, we must use the Routing Attributes from the controller.
I don't want to add the MessageHandler globally.
It has to be a MessageHandler (early in the pipeline). We have alternatives for this but we are trying to do this more efficient.
For example, I've decorated the controller with the following RoutePrefix: api/myapicontroller and one action with Route(""). (I know it is strange, we are selecting a different action based on querystring)
Then, I've added
config.Routes.MapHttpRoute(
name: "CustomRoute",
routeTemplate: "api/myapicontroller/{id}",
defaults: new { id = RouteParameter.Optional },
constraints: null,
handler: new myMessageHandler()
);
If I put this code before config.MapHttpAttributeRoutes(); the myMessageHandler is executing but I get this Message:
No action was found on the controller 'myapicontroller' that matches
the request
If I put config.MapHttpAttributeRoutes(); first, the myMessageHandler is never executed but the my action inside myapicontroller is called.
Unfortunately, you can not set any handlers via AttributeRouting. If you want to assign handler to specific routes you have to register it via MapHttpRoute only. Except you need to add your controller name in defaults section like in Ajay Aradhya's answer and remove Route attribute from your action, because you are allowed to register routes either with Route attribute or MapHttpRoute method, but not both at the same time.
Also note that you need to create pipeline, otherwise you handler will work but request will not hit the controller action.
See my answer on similar question for details.
This article from MS docs explains the same. At last they provide a way to have controller specific handlers.But thats for the conventional routing. I don't know if this helps you or not.
config.Routes.MapHttpRoute(
name: "MyCustomHandlerRoute",
routeTemplate: "api/MyController/{id}",
defaults: new { controller = "MyController", id = RouteParameter.Optional },
constraints: null,
handler: HttpClientFactory.CreatePipeline(new HttpControllerDispatcher(config), new MyCustomDelegatingMessageHandlerA());
);

ASP.NET view routing default values

My default routing follows {controller}/{id}/{action} instead of the standard {controller}/{action}/{id}
Now i need to set up the defaults such that if no id is provided, default to Index action in controller
If Id is provided and no action is provided, default to Detail action
If both Id and Action is provided then route to the corresponding action.
How can I set up this routing?
currently:
routes.MapRoute(
name: "Default",
url: "{controller}/{id}/{action}",
defaults: new { controller = "projects", action = "Index" })
The usual approach would be to set up the routing just like you specified; i.e. create the following routes in order:
{controller}/
{controller}/{id}/
{controller}/{id}/{action}
Evidently, for the various routes, there are no optional parameters anymore. Apply defaults as usual. :)

Get the url without the name of the method that called it

I am try to get the url of the website plus the current controller without the method that called it.
Inside the ExampleController, ExampleMethod
Request.Url.ToString()
=>http://localhost:51747/.../ExampleController/ExampleMethod
I need
http://localhost:51747/.../ExampleController
The solution I would use is to parse and remove everything after the last slash, but I am not sure if there is already a method to do this using the server info.
Your issue can be solved by using one of the Url.Action HTML helper overloads. To generate your example URL:
http://localhost:51747/.../ExampleController
You would need to do:
#Url.Action("ExampleController", "Index", null, Request.Url.Scheme)
assuming you are using the default ASP.NET MVC Routing config.
In more detail, if the action you provide to the helper is one set as a default in the routeconfig, then it not be specified in the resulting URL.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
See the action = "Index" default? Whatever you have set there is what you will have to use when generating the URL.

Routing multiple gets for WebApi in MVC4

I'm creating a rest API in ASP.NET MVC4, and am having a problem with routing. For reference, I've already read these questions but they haven't answered my problem:
Web API Routing - api/{controller}/{action}/{id} "dysfunctions" api/{controller}/{id}
Web Api Routing for multiple Get methods in ASP.NET MVC 4
Routing in Asp.net Mvc 4 and Web Api
The urls I'm looking to craft can be as follows:
GET /account/id (where id is a Guid) - equivalent to GET /account/?id=x
GET /account/first%20last%20name (where name is a
string) - equivalent to GET /account/?name=x
GET /pendingregistrations/?page=y (here the action is omitted)
POST /pendingregistrations/denyregistration?denyId=x (here an action is specified)
As you can see, in some cases the URL after the controller name maps to a parameter (id and name in #1,2 above), and sometimes the action name (#4 above). In addition, it may be not present at all (#3 above), in which case I assume a default action. Here is the routing that is working for almost all cases:
// Match for an id next.
config.Routes.MapHttpRoute(
name: "WithIdApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { action = "Index" },
constraints: new
{
id = #"^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$"
}
);
// Match for a name next.
config.Routes.MapHttpRoute(
name: "WithNameApi",
routeTemplate: "api/{controller}/{name}",
defaults: new { action = "Index" }
);
// Match for an action last.
config.Routes.MapHttpRoute(
name: "WithActionApi",
routeTemplate: "api/{controller}/{action}",
defaults: new { action = "Index" }
);
This code works for everything except example #4 above, because MVC can't tell the difference between a 'name' parameter, and an 'action' binding. If I change the order (i.e. put the match for action above), then the 'name' parameter example will never work.
Does anyone know of any way I can accomplish this?
Well for anyone else trying to do this, the answer is it isn't possible. Best thing to do is to move the 'name' search into it's own action. For example:
GET /account/id (where id is Guid)
GET /account/name/first%20last
I would have assumed MVC would have attempted to match parameters, or actions, if one or the other failed and other bindings were available, but sadly this is not the case.

ASP.NET MVC Url routing problems

I'm new to MVC and URL routing, and am looking for some guidance.
I would like to be able to have a URL per user, with the format:
http://www.example.com/username
So I added the following route:
routes.MapRoute(
"UserRoute", // Route name
"{username}", // URL
new { controller = "Users", action = "ViewUser", username = UrlParameter.Optional }
);
Which works great if it is the FIRST route, but it has messed up the default {controller}/{action}/{id} route. Now when I try to visit the root page, it tries to load my UsersController "ViewUser" action with a null parameter (or with "favicon.ico" as the parameter).
If I put my new route AFTER the default route, then MVC tries to find the controller called username and fails because it can't find it.
Is there any way to have URLs of the form {username} without mucking up the regular routing system? I could probably write a custom route for every controller I have, but that seems error-prone.
You can check out this link and see if it helps. It is also creating urls with just a username on them.
You can put a constraint to the allowed controller values for the default route, instead of creating a route for each controller.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL
new { controller = "controller1", action = "defaultaction", id = UrlParameter.Optional }, //default values
new { controller = #"controller1|controller2|controller3|..." }
);
when the controller does not match any of those it will try the next route

Resources