Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

asp.net mvc - @Url.Action("Action", "Controller") returns "/cgi-bin?action=Action&controller=Controller"

For some reason it thinks the target is an Apache server - I suspect?

The MVC is V5.2.3 and its dependancies are correct as per nuget . I have searched and searched to no avail.

EDIT The code is simply @Url.Action("Action", "Controller")

So I created a brand new MVC project and using exactly the same code the correct code was returned.

http://localhost:53143/Controller/Action

EDIT 2 I removed my web.config files as the problem is not there.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I got in touch with an expert and he looked at the project and answered as below.

(BTW I have 'cgi-bin' in a route as there are old URLs out in the wild that relate to my domain previously being hosted on an Apache server and which I cannot change.)

The answer I digged a little more into the source code of the mvc helpers and, yes, the two issues (I had a similar problem Html.BeginForm with overload causes form action to be '/cgi-bin?action=Index&controller=Home' and so the HomeController is bypassed) are related since Url.Action and Html.BeginForm boil down to calling one and the same method: UrlHelper.GetUrl... Now, what this method does is:

  1. Retrieve the current URL including controller, action, area...
  2. Add or replace the parameter(s) you specify,
  3. Find the best matching route! <==
  4. If there are any route variables - push the provided parameters into those variables.
  5. Stick the rest of the parameters into the query string <==

I have deliberately highlighted point 3 & 5, with point 3 being the most important. So, UrlHelper.GetUrl (and Url.Action and Html.BeginForm respectively) needs a route and it searches through the available ones to find the first match.

Now, here comes the problem with your mixed webforms-mvc app - an issue which is not present when you are dealing purely with MVC: You are using MapPageRoute!!! Please, note that it is different from MapRoute. And MapPageRoute uses the PageRouteHandler class to create the route whereas MapRoute uses the MvcRouteHandler class and it makes all the difference because PageRouteHandler creates the route in such a way that it's always a good match for UrlHelper.GetUrl("ActionName", "ControllerName") with the action name and controller name being thrown into the query string as parameters (point 5).

So, what happens with your set-up is that Url.Action is searching for a route and is hitting the first one created by MapPageRoute and in your case this is:

routes.MapPageRoute("cgi-bin", "cgi-bin/{*theRestcgi-bin}", "~/home/Search.aspx");

That's where that arcane cgi-bin part of the query string comes from, giving the impression that the framework is actually searching for some virtual/physical folder.

As for the proper solution: either define a suitable route or specify the url as a simple string the way you have done. I think, your solution is the better one as you won't have to move around the route definitions in the RouteConfig class.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...