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
Related
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 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}.
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 Umbraco 4.11.8 and want to create a PDF.
I have HTML code, that should be downloadable as a PDF
I found a package RazorPDF, which works perfectly in a MVC sample.
But when I try it in Umbraco, I don't know how to get it.
Do I need a SurfaceController or anything else.
If yes, how do I say Umbraco to use my (Surface)Controller?
I put it as answer so it's more readable. Feel free to edit.
I don't find my fault or what I'm missing.
My Controller signature is like this: public class PdfCreatorController : Controller
and the method, which I want to call is called public override ActionResult Pdf().
My routing:
RouteTable.Routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
RouteTable.Routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);`.
Then I try to call my controller like www.url.com/PdfCreator/Pdf.
The best place to start for what you need is here: http://our.umbraco.org/documentation/Reference/Mvc/
But no, strictly speaking you don't need a SurfaceController. You would only need one if you wanted to access the Umbraco context for the requests you are making via the controller.
So if you just want to have a controller serve up your PDF, you can have a standard controller implementation. You will have to adjust your routes for this though, and this is all covered in the Umbraco documentation above.
Edit:
You'll need a route like this:
RouteTable.Routes.MapRoute(
name: "PdfRazor",
url: "PdfCreator/{action}"
);
You will also need to add the path to the Web.config for Umbraco to ignore, e.g:
<add key="umbracoReservedPaths" value="~/umbraco,~/install,~/pdfcreator" />
I would like to make some urls of my asp.net MVC4 app shorter. For example I have Account controller and such action ForgotPassword. Url looks like this
http://www.mydomain.com/account/forgotpassword
I would like to make the url shorter(example below) without renaming actual controller and action names. What is the best way to do that?
http://www.mydomain.com/a/fp
You could register a simple route:
routes.MapRoute(
name: "ForgottenPassword",
url: "a/fp",
defaults: new { controller = "Account", action = "ForgottenPassword" }
);
...in RouteConfig.cs if you're using MVC4.
If i am not wrong, then your talking about Friendly URL's?
Please have a look # quysnhat.wordpress.com
There was a very nice post in Hanselman's web.
Also, there were few questions related to friendly url's(in case it helps you) :-
How can I create a friendly URL in ASP.NET MVC?
http://www.intrepidstudios.com/blog/2009/2/10/function-to-generate-a-url-friendly-string.aspx
The easiest but not the best way of doing it is to hand-code your custom routes:
routes.MapRoute(
name: "AccountForgotRoute",
url: "a/fp/{id}",
defaults: new { controller = "Account", action = "ForgotPassword", id = UrlParameter.Optional }
);
The downside to that is if you will have tons of controllers and action methods and you like all of them to be "shortened", then you will have to write a lot of routes.
One alternative is to define your custom routes in a database and write it out on a file. So for example you have in a database row an accountcontroller-forgotpassword key with a value of a/fp, you dynamically build the route definition, write it in a file and let your application pick it up. How your application can pick up the route definition can be done like this. That link is still applicable for MVC 4. But this one is really messy, IMO, but is an alternative.