Asp.Net Web API action string route mapping - asp.net-mvc-4

I have a contoller named customer and an action method for GetAllCustomers which recieves single string input parameter as FirstName. The issue is that I want the url to be like
MyAPI/Customer/MyFirstName
but the above stated URL is not working for me instead it working as below
MyAPI/Customer?firstname=MyFirstName
How can I make it work like the first url using ApplicationRouting (nuget package)? I have configured the attrbute route for the action method as below.
[GET("Customer/{firstname}")]
public List<Customer> GetAllCustomersFirstname(String firstname)
{
//code goes here
}
Edit
Here is the reference whatI am trying to achieve but it is not happening for me in ApiController
Attribute Routing Github

Open up ApiConfig in the AppStart folder. You need to add the route for that particular action. I think you'll need more than just what you showed there for route since you have to tell it which action to call and what methods to allow. E.g.
config.Routes.MapHttpRoute(
name: "yourRoute",
routeTemplate: "api/{controller}/{firstname}",
defaults: new { controller = "Customer", action = "GetAllCustomersFirstname" });

Related

Adding Attribute Route on Controller adds Parameter to Url

I want to change the URL that will access my controller, but when I do, instead of getting controller/action/id, I get controller/action?id=(the id number) in the URL.
I am using default routing in my MVC .Net Core.
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
On my controller I have [Route("DifferentName/{action=index}")] for attribute routing.
I have tried adding [Route("DifferentName/{action=index}/{id?}")]
but I get an exception "RoutePatternException: The route parameter name 'id' appears more than one time in the route template."
These attributes are incorrect according to the documentation:
[Route("DifferentName/{action=index}/{id?}")]
[Route("DifferentName/{action=index}")]
This is how it should look like for controller when we want to only change its part of URL:
[Route("DifferentName/[action]")]
[action]
[action] will be replaced by your action name when asp .net core will be resolving URLs.
More information about routing and can be found in the documentation
but I get an exception "RoutePatternException: The route parameter
name 'id' appears more than one time in the route template."
I have reproduced your error. I need to confirm with you whether the reason for your error is to add Route attribute to both controller and action.
If so, as the exception points out, you don't need to specify route repeatedly.
Modify the following settings to implement the url like 'Differentname/action/5':
[Route("DifferentName/{action=index}")]
public class ShowPdfController : Controller
{
public IActionResult Index()
{
return View();
}
[Route("{id?}")]
public IActionResult Action(int id)
{
return View();
}
}
Then, you can see the test result of this setting:

Route matching from static Uri + route data extract

I have a .Net Core 2.2 MVC app with routes defined as route attributes on my MVC actions.
I would like to find the matching route (if any) and what the route data are from a given Uri (i.e. not the current HTTP request but a static Uri coming from a database for instance).
I already use the LinkGenerator.GetPathByAction() method to get the "route URL" for a specific action with route data. What I am after would be the opposite: a method that takes a URL/Uri and return the matching route and its route data.
For instance if I have a route registered with the following template:
[Route("/my-action/{id:int}/{name}")]
the URL "/my-action/5/my-test-name" would return the following route data:
id: 5
name: my-test-name
I went through the routing documentation but I haven't found anything.
https://github.com/aspnet/AspNetCore.Docs/blob/master/aspnetcore/fundamentals/routing.md
The only option that I see would be to somehow call the RouteMiddleware (https://github.com/aspnet/AspNetCore/blob/master/src/Http/Routing/src/RouterMiddleware.cs) with a mock HttpContext which seems overkill if even doable?
I would like to find the matching route (if any) and what the route data are from a given Uri.
If you want to get the route data in the action with the matching route , you could directly use GetRouteData in the current HttpContext object like below :
[Route("/GetRouteData/{id:int}/{name}")]
public void GetRouteData()
{
var routeData = HttpContext.GetRouteData();
var routeCollection = routeData.Values;
var id = routeData?.Values["id"]?.ToString();
var name = routeData?.Values["name"]?.ToString();
}
About finding out if a URL matches an action in ASP.NET MVC Core , you could refer to the following links :
https://joonasw.net/view/find-out-if-url-matches-action
https://weblog.west-wind.com/posts/2019/May/15/Accessing-RouteData-in-an-ASPNET-Core-Controller-Constructor
https://rimdev.io/asp-net-core-routes-middleware/

How to create custom Routing in ASP.NET Core

I need help with URL rewriting. I am new to ASP.NET Core MVC. When I type anything in {param} part then routing should redirect it to my controller.
So if anyone to types in {param} like
https://mydoamin.com/{param}
then it should be redirected to this url:
https://mydoamin.com/{controller}/{action}/{actionurl}={param}
I found the answer for my question. Just define new custom route in your startup.cs file before your default route.
routes.MapRoute(
"Member", // Route name
"{actionURL}", // URL with parameters
new { controller = "Pages", action = "Details" } // Parameter defaults
);
It's working form me.
We can do the same using this approach.
I find this more convenient.
[Http("add/user/{user}/{password}")]
public IActionResult AddUser(string user, string password)
{
//do your things here...
}
I could recommend you to see this blog post from Stephen Walther: ASP.NET 5 Deep Dive: Routing
I am not sure if this works as you want. https://mydoamin.com/{controller}/{action}/{actionurl}={param} seems not to be a valid URL to me. The part {actionurl}={param} is probably the query part which is comes as a key/value pair and starts always with a ?. You could probably fix your routing if your desired URL would look like https://mydoamin.com/{controller}/{action}/?key1=value1&key2=value2
I don't know still this is useful OR not but in asp.net core 3 this worked for me like a charm.
routes.MapRoute(
"MoviesByReleaseDate",
"movies/released/{year}/{month}",
new { controller = "Movies", action = "ByReleaseDate" }
);

MVC4 - My Custom Route isn't working

So I have a custom route in my MVC4 web app below:
routes.MapRoute(
name: "SecondarySportsCategoryLanding",
url: "sports/{name}/{id}",
defaults: new { controller = "FrontCategoriesController", action = "Sports", name = UrlParameter.Optional, id = UrlParameter.Optional }
);
I have that placed above my default one as well. What's happening is when I go to /sports I get this error:
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /sports
I have the controller specified, and inside that I have an Action titled Sports with 2 optional parameters (defaulted to nulls). Any ideas?
controller = "FrontCategoriesController" should be controller = "FrontCategories"
Because the framework automatically inserts Controller into the value for you.

MVC2 Routing with WCF ServiceRoute: Html.ActionLink rendering incorrect links!

I have a WCF service that lives side-by-side with an MVC2 web site. I'd like for my URL for the service to look like this:
http://localhost/projdir/Service
The MVC site is in its infancy so it still has all its boilerplate controllers etc.
The following code works at first glance in global.asax:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add(new ServiceRoute("Service", new ServiceHostFactory(),
typeof(MyService)));
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index",
id = UrlParameter.Optional } // Parameter defaults
);
}
The service appears just where I described and works as advertised. Great.
However, I just noticed that ordering my code this way changes all of my ActionLink's. For example, the "About" tab on the MVC site now appears like this:
http://localhost/projdir/Service?action=About&controller=Home
This is obviously incorrect (it should be http://localhost/projdir/Home/About/ ).
If I move the ServiceRoute addition below the default MapRoute() call, then I get a missing controller error. (Actually I get a "StructureMapControllerFactory did not return an instance of a controller" error, because I'm wired up with StructureMap, duh, it's not a controller to begin with.)
Interestingly, it only seems to be affecting the output of Html.ActionLink(). I can manually type in http://localhost/projdir/Home/About/ and get to the correct page.
What horribly obvious newbie mistake am I making?
Try moving the Service route after the MVC route. But to avoid the "missing controller" error that you got before, add the MVC route with a Route Constraint. These route constraints can be Regex - basically you'd want your route constraint to be any controller that is not "Service". When a request for "Service" is requested, it will make it fall through and his the WCF Service Route.
I resolved with that:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { controller = "^(?!api).*" }
);
routes.Add(new ServiceRoute("api", new DataServiceHostFactory(), typeof(dwService)));
I hope this good for you
Another solution is to inherit the ServiceRoute and override the GetVirtualPath method to return null as described here
public class AppServiceRoute : ServiceRoute
{
public AppServiceRoute(string routePrefix, ServiceHostFactoryBase serviceHostFactory, Type serviceType)
: base(routePrefix, serviceHostFactory, serviceType)
{
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
return null;
}
}
This way, reverse route mapping never select this route for any Action. Works like a charm