I don't want to use ASP.NET MVC WebApi, but I do want to use the URL /api/controller/action so that it is handled by my own controller
I'm doing this:
routes.MapRoute(
name: "APIRoute",
url: "api/{controller}/{action}/",
namespaces: new[] { "MyProject.Controllers.APIControllers" }
But it seems that is not possible to use api/ in MapRoute(...)
If I navigate to http://localhost/api/Blah/List it doesn't work
If I change the route to this:
routes.MapRoute(
name: "APIRoute",
url: "apix/{controller}/{action}/",
namespaces: new[] { "MyProject.Controllers.APIControllers" }
(Notice the 'x' in 'apix/')
And then I navigate to http://localhost/apix/Blah/List it works as expected
What can I do? is it possible to override api/ ?
Sounds like you may have created a new project which includes Web API which is why you're having a hard time.
Search your project for WebApiConfig or DefaultApi - if you have any results then Web API has been added to your project and you'll want to amend the default routeTemplate which is by default api/{controller}/{id}.
Related
I have a controller that shows item details based on an input parameter, so something like this:
mydomain.com/book/detail/3
It shows the book with id = 3. Fine!
I would like to shorten the url to this:
mydomain.com/3
I hope this is possible, but I was not able to set this up.
I tried to make a custom route in the RouteConfig - RegisterRoutes but had no luck.
Is this possible with a routing rule? Or other solutions?
Thank you all
Add a custom route before the default one in RouteConfig.cs like this:
routes.MapRoute(
name: "BookRoute",
url: "{id}",
defaults: new { controller = "Book", action = "Detail"}
);
My question up front
How do I construct a route so that MVC will intercept the classic ASP URL and instead execute an MVC action?
I am migrating a legacy classic ASP application to MVC, and need to have MVC intercept a couple of the legacy ASP URLs because they are major endpoints for external access to the application. But I can't seem to figure out how to do it correctly.
I checked a few other questions and didn't quite find what I'm looking for, but maybe my search-fu is poor today. This one is specific to areas but looks similar to mine which still doesn't work, and this one is a possible workaround but I'd really rather handle this completely within MVC and eliminate the legacy file completely.
What I want to do
Given: /foo/bar.asp
Map to: /InboundLinks/HandleBar
(one URL will be a GET request, but the other will be a POST with some sensitive data, so I need them to be intercepted and the POST data still available to MVC, not sure if a 301 redirect will do that or not)
What I DON'T want to do
I do NOT want to run the classic ASP pages at all. (I'm willing to have it solely do a 301 redirect to the MVC URL if that is the only workaround, but that's it) I want the URLs to be intercepted and handled by MVC. I say this because a few questions I found here and elsewhere seemed to generate some confusion on that point.
What I've already tried
routes.MapRoute(
name: "LegacyBarUrl",
url: "foo/bar.asp",
defaults: new { controller = "InboundLinks", action = "HandleBar" }
);
But this returns a 404 Not Found error.
Environment
Visual Studio 2013 running in local dev mode on Windows 7. Deployment will be to IIS 7 on a locked down server I don't control, so installing HTTP modules on the server isn't an option unfortunately. The domain will remain the same.
Many thanks in advance for any help/guidance/etc.
What you've tried must work. Make sure it comes at the top of your routing configuration, and the default route comes after it.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "LegacyBarUrl",
url: "foo/bar.asp",
defaults: new { controller = "InboundLinks", action = "HandleBar" }
namespaces: new[] { "YourProject.Controllers" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "YourProject.Controllers" }
);
}
EDIT:
OK, I've tried this myself as well and it really does not work. So you have two options:
(1) capture and route your request at the IIS level: If you take this path, this extension might be very helpful: http://www.iis.net/downloads/microsoft/url-rewrite]
(2) write your own RouteBase and redirect legacy routes before MVC looks up the routing table: If you take this path, this article would be very helpful to you (it would be too long to write the code here): http://www.mikesdotnetting.com/article/108/handling-legacy-urls-with-asp-net-mvc
To Anyone running into this problem, the 404 is because the server is looking for the physical file before getting into the routes. What is needed is a handler for the extension, in this case for the classic asp that is going to catch the request so the server doesn't look for the file anymore, and the request is handled by your handler.
Add an entry to the web config file in the handlers section like this:
<add name="ClassicASPHandler" path="*.asp" verb="GET" type="System.Web.Mvc.MvcHttpHandler, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
Then add the needed route to the configuration routes table. Now, the route will be handled correctly as opposed of looking for the file and returning a 404.
routes.MapRoute(
name: "LegacyBarUrl",
url: "foo/bar.asp",
defaults: new { controller = "InboundLinks", action = "HandleBar" }
namespaces: new[] { "YourProject.Controllers" }
);
I have the following URL:
http://localhost/FolderB/Index
This goes to the following controller:
/FolderB/HomeController.cs
I need to instead use this URL: http://localhost/SubComponent.
I'm not sure how that is done in asp.net MVC. What is this type of masking called and where does the code live to accomplish it?
I have tried the following in RouteConfig.cs but it doesn't work:
routes.MapRoute(
name: "SubComponent",
url: "SubComponent",
defaults: new { controller="Home", action="Index", id=UrlParameter.Optional},
namespaces: new[] { "MyNamespace" }
A simple way of doing this would be to add another route in MVC that routes SubComponent.
You can add a route by looking for where your routes are wired up, which is usually either in Global.asax.cs or in a class called RouteConfig and adding your own route:
routes.MapRoute(name: "SubComponent", url: "SubComponent/{id}", defaults: new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional
});
The order which routes are added matters, so make sure this call to MapRoute occurs before all others.
And specify an area if you need to.
For ASP.NET MVC 5, use RouteAttribute. For older ASP.NET MVC version, you may have to resort to other open source (or your own custom) implementations e.g. https://github.com/mccalltd/AttributeRouting
For Latest Versions:
https://msdn.microsoft.com/en-us/library/cc668201(v=vs.100).aspx
If you are using ASP.NET 3.5 ASP.NET Routing could be a good choice for you.
MSDN page: msdn.microsoft.com/en-us/library/cc668201.aspx
Using it with ASP.NET MVC at ScottGu blog:
weblogs.asp.net/scottgu/archive/2007/12/03/asp-net-mvc-framework-part-2-url-routing.aspx
Using it with ASP.NET 3.5: www.techbubbles.com/aspnet/aspnet-35-url-routing/
If your website runs under ASP.NET 2.0 Helicon ISAPI Rewrite could be a good choise for you. This is an IIS filter that redirects requests to your pages according to regex-based configuration file. They have a free version for one website.
Have a look at Helicon: www.isapirewrite.com
Hope this helps. Good Luck
I’m working on a new ASP.NET MVC and AngularJS application that is intended to be a collection of SPAs. I’m using the MVC areas concept to separate each individual SPA, and then I’m using AngularJS within each MVC area to create the SPA.
Since I’m new to AngularJS and haven’t been able to find an answer regarding combining both MVC and AngularJS routing, I thought I’d post my question here to see if I could get some help.
I have the standard MVC routing setup, which serves up each MVC area.
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 }
);
routes.AppendTrailingSlash = true;
}
This works fine and gives me URLs like:
http://servername/Application1/
http://servername/Application2/
Now, within each application area, I’m trying to use AngularJS routing, also using $locationProvider.html5Mode(true); so that I get the client-side routing within each area, something like:
http://servername/Application1/view1
http://servername/Application1/view2
http://servername/Application2/view1/view1a
http://servername/Application2/view2/view2a
http://servername/Application2/view3
Here’s my AngularJS routing snippet for Application1:
app1.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
var viewBase = '/Areas/Application1/app/views/';
$routeProvider
.when('/Application1/view1', {
controller: 'View1Controller',
templateUrl: viewBase + 'view1.html'
})
.when('/Application2/view2', {
controller: 'View2Controller',
templateUrl: viewBase + 'view2.html'
})
.otherwise({ redirectTo: '/Application1/view1' });
$locationProvider.html5Mode(true);
}]);
So, initially, it seems to work (at least the URL looks correct). But, when I start navigating between areas or views within an area, or even if I refresh, something gets “lost” and things don’t work. The URL still looks correct but views aren’t found and aren’t getting loaded correctly.
Any help/guidance on how to make ASP.NET MVC and AngularJS routing work together to give me the scenario described above?
Thanks!!!
Thanks for the answer, agbenyezi. I looked at the article you provided but it only got me back to where I was anyway.
However, I was able to figure it out and get it working. The answer turned out to be relatively simple, but it took some time and a lot of searching around. Anyway, since I am using MVC areas, navigating to a URL of http://servername/Application1/view[x] (where Application1 is the MVC controller (in the area) and view1, view2, view3, etc. are Angularjs views), the MVC part of the overall application was getting confused and trying to find an action named view[x] in the Application1 controller (which doesn't exist).
So, in the area's AreaRegistration class (where it's defining specific routes for the area), I just needed to add a kind of catch-all route before any default MVC routes to always force it to the Index action on the Application controller. Something like:
// Route override to work with Angularjs and HTML5 routing
context.MapRoute(
name: "Application1Override",
url: "Application1/{*.}",
defaults: new { controller = "Application1", action = "Index" }
);
Now, when I navigate to http://servername/Application1/view[x] it routes to the Application1 MVC controller, Index action, and then Angularjs takes over routes to the different views, all while having the HTML5 routing construct in the URL.
I'm using attribute routing from ASP.NET 5 RC, included in the Visual Studio 2013 RC release.
I'd like for the root path, /, to lead to the canonical /Home/Index path, but I can't find a way to do this with just attribute routes. Is it possible, and if not, how would I do it if I'm also using OWIN SelfHost? In other words, I'm setting up my own HttpConfiguration class manually in the WebApp.Start<T> method (where T has a Configure(IAppBuilder) method invoked at startup) and not going through the RouteTable.Routes object. Or should I be going through the RouteTable.Routes object? I haven't had much luck with that when I tried it...
EDIT: Here's what I've tried so far:
// normal Web API attribute routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultWeb",
routeTemplate: "{controller}/{action}",
defaults: new { controller = "Home", action = "Index" }
);
The second try below looks a little dubious, since it's not clear how my HttpConfiguration object is related to the static RouteTable.Routes object:
// normal Web API attribute routes
config.MapHttpAttributeRoutes();
RouteTable.Routes.MapRoute(
name: "DefaultWeb",
url: "{controller}/{action}",
defaults: new { controller = "Home", action = "Index" }
);
You can set the default route for the app like this:
[Route("~/", Name = "default")]
public ActionResult Index() {
return View();
}
For anyone who is using .NET Core 1.x, you'll need to do this as well as use Jay's answer above.
In your Startup.cs file, add this to your Configure method.
app.UseMvcWithDefaultRoute();
Then, any controller action you want as the default, put the attribute [Route("", Name = "default")]