ASP.NET MVC Routing in Azure - asp.net-mvc

I have an Azure Web Role project that was recently MVC'd by another developer. According to the developer the app works with no problem when run on it's own (i.e. as a simple web app). However, when I try to run it in the context of the Azure cloud service, I'm seeing a number of 404 errors. I suspect something is not quite right with the routing. Here's an abbreviated version of the current RegisterRoutes method that's part of Global.asax.cs:
public static void RegisterRoutes(RouteCollection routes){
routes.IgnoreRoute("{Services}/{*pathInfo}");
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Configuration",
"Configuration",
new { controller = "Configuration", action = "Index" }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Account", action = "Index", id = "" }
);}
When the app starts up, the correct view from the Account controller's Index action is displayed. However if I try to navigate to Configuration I get a 404. Converesly if I change the method to this:
public static void RegisterRoutes(RouteCollection routes){
routes.IgnoreRoute("{Services}/{*pathInfo}");
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Account",
"Account",
new { controller = "Account", action = "Index" }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Configuration", action = "Index", id = "" }
);}
I get the correct view from the Configuration controller's Index action, but I can't navigate to the Account view.
I'm guessing this is a simple problem to solve, but not knowing what exactly was done to "MVC" the Azure app and being new to MVC has me beating my head into the wall.
Here's the configuration of the machine where I'm encountering this issue:
Windows 7 Ultimate with IIS 7.0
Visual Studio 2008 SP1
ASP.NET MVC 1.0
Windows Azure SDK 1.0
Thoughts?

Try using my Routing Debugger. It can help you understand what's going on. http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx
It's weird that the behavior would be different locally than in Azure. Also, you should post your controller code (remove the contents of the action methods, we just need to see the method signatures).
If I had to make a wild guess, I'd guess your Configuration route (in the first example you gave) needs to add id="" in the defaults section.

Haacked: Thanks for pointing me to the debugger. That helped me hunt down the issue in a matter of minutes.
The answer was much simpler than I thought. It all had to do with the following line of code:
routes.IgnoreRoute("{Services}/{*pathInfo}");
I put this line in to help resolve an issue I was having with ASP.NET MVC and WCF RIA Services (more info on that here). The curly braces shouldn't be there. I don't want to replace Services. The code should look like this:
routes.IgnoreRoute("Services/{*pathInfo}");
You can read a full write-up here.

I don't think this is your problem, but you might verify that the System.Web.Mvc reference has its Copy Local = true.

Related

How to create an MVC route to intercept classic ASP URLs?

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

ASP.NET MVC 404 Error for SubDirectories

I've added a custom 404 page to my asp.net mvc application. It works totally great except for on some paths that have been excluded from the MVC routing engine. As you can imagine, I'd like my 404 page to work for those URLs as well.
So the question is: Can I add some setting in IIS I can use to just point it to the 404 page's endpoint.
Thanks!
No, there isn't any custom setting on IIS.
Works for me. I have the following settings set in web.confg
My RegisterRoutes method is as below
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
I ended up writing a StaticContentController that simply opens a file stream and returns it to the browser. The path is controlled tightly by the routing engine to avoid security issues, and it is heavily cached.
A note on the file stream, when I first implemented it, I was using MVC's return File(... method, but that locks the file while it is streaming it, so I had some instances of file contention for files that were written to and served concurrently. That's why I switched to returning a FileStream, so I could pass the correct file sharing options that allow for the file to be written to by another process.

MVC4 project blank page

I've lost the last two hours trying to fix that problem. I can't remember what I've changed to my project but now it is returning a blank page no matter what the URL I write is. No controller is reached, I don't even get any single HTML tag.
I'm running on Windows 7 Starter and I use Visual Studio 2012 and IIS Express. Everything was working fine with this project, I was able to navigate and to access the controllers without any problem. I googled and found several articles suggesting to enable HTTP Routing, and similar HTTP modules in the Add/Removes functionalities section of the Control Panel. I checked all the stuff that are related to IIS but it's not working.
What I really don't understand is that first it was working without any problem and I can't remember which critical change I could have done to this project (I lastly worked on it 2 days ago) And secondly, others project are working just fine so IIS is properly configured. I checked in global.asax and RegisterRoutes is properly called. I haven't changed the default routing system.
I don't have any idea of what I should try since I don't get any error message. I would appreciate any kind of help. Thank you!
Update 1: It looks like the MVC framework is never called : nothing happens even if I try to debug and to put a breakpoint at the beginning of the Application_Start() in Global.asax
Update 2: Here is my RouteConfig.cs file :
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 }
);
}
And here is my Application_Start function which is anyway never called according to debugging :
protected void Application_Start()
{
//ModelBinders.Binders.DefaultBinder = new PerpetuumSoft.Knockout.KnockoutModelBinder();
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "Utilisateurs", "ID", "AdresseMail", true);
}
(I tried to comment the useless lines (Websecurity since I'm not using it in the controller I'm trying to reach, Knockout and BundleConfig) but I got the same result). But this function is never called anyway.
I have the same problem and it turned out my _ViewStart.cshtml hadn't deployed to the server. I uploaded that and it worked. Check all your files are up correctly.

RedirectToAction Causes "No route in the route table matches the supplied values" in ASP.NET MVC 3

I have a project that I recently upgraded to ASP.NET MVC 3. On my local machine, everything works fine. When I deploy to the server, I get an error anytime I use a RedirectToAction call. It throws a System.InvalidOperationException with the error message No route in the route table matches the supplied values. My assumption is that there is some configuration problem on the server, but I can't seem to be able to figure it out.
I ran into this with areas within MVC3 when redirecting across areas. As others have said, Glimpse is very useful here.
The solution for me was to pass in the Area within the route values parameter changing:
return RedirectToAction("ActionName", "ControllerName");
to:
return RedirectToAction("ActionName", "ControllerName", new { area = "AreaName" });
I had a similar problem once with RedirectToAction and found out that you need a valid route registered that leads to that action.
Check out glimpse and see if you can get some route debugging information:
http://getglimpse.com/
You could add a route table to your RouteConfig.cs file like below:
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapMvcAttributeRoutes();
var namespaces = new[] { typeof(HomeController).Namespace };
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("name", "url", new { controller = "controllerName", action = "actionName" }, namespaces);
}
NB: the "url" is what you'd type into the address bar say: localhost:/home
After setting up the route, use RedirectToRoute("url").
Or if you'd prefer the RedirectToAction() then you don't need to set up the above route, use the defaults.
RedirectToAction(string action name, string controller name);
I hope this helps.
There's a difference with trailing slashes in routes not working with MVC 3.0. MVC 2.0 doesn't have a problem with them. I.e., if you change the following:
"{controller}.mvc/{action}/{id}/"
to:
"{controller}.mvc/{action}/{id}"
it should fix this (from this thread, worked for me). Even when you use the upgrade wizard to move to MVC 3.0, this still throws InvalidOperationException. I'm not aware whether this is what Schmalls was talking about though.
In my case, default route was missing:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

Subdomain Points To Blog Folder (Non-MVC) on an MVC 3 Site

I have an MVC 3 site that is working and currently quite basic. There is a folder off of the root called Blog where I have BlogEngine.net setup. Both work as I want. I had to do the following code in the global.asax file to make sure that MVC would ignore any request going to the Blog folder as follows:
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{folder}/{*pathinfo}", new { folder = "Blog" });
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home",
action = "Index",
id = UrlParameter.Optional } // Parameter defaults
);
}
What I am looking for is to be able to go to: blog.mysite.com and have it go directly to the /blog folder. I have a Subdomain setup through my hosting provider. However, I am not sure what to do beyond this to tell it to go anywhere. When I currently go to blog.mysite.com, it just takes me to the home page.
I suspect I will have to add a MapRoute assume it will be smart enough to still Ignore the {folder} one.
I think the answer to this question might help you along:
Is it possible to make an ASP.NET MVC route based on a subdomain?

Resources