Wcf Web Api service routes conflicting with regula

2019-04-11 15:31发布

问题:

I noticed that my mvc app is creating wrong url's when using:

@using (Html.BeginForm("Test", "Test"))
{
    <input type="submit" value="Submit" />
}

This is the generated html source:

<form action="/books?action=Test&amp;controller=Test" method="post">

Notice that action starts with /books. This is WRONG!

What I've noticed is that Html.BeginForm is always including the beginning of the first web api which has been registered with MapServiceRoute. (see code below)

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    var builder = HttpHostConfiguration.Create();
    routes.MapServiceRoute<BooksService>("books", builder);

    routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
    );
}

I spent a long time trying to figure out why the url's were broken in my app, but got nowhere. I then decided to test with an extremly simple mvc app and sure enough the problem can be easily reproduced. The mvc app I tested this on is as simple as it can get, was created by an asp mvp. You can find it here. All I did was add the TestController and the Views/Test/Index.cshtml view. In the view I added the Html.BeginForm shown above. If you launch the app and visit the test controller you can see the url is wrong by just hovering the mouse over the submit button (or look at the html source).

Anyone know how to avoid this problem?

EDIT: This applies for web api preview 4 (april 2011).

回答1:

another way is to define a route constraint:

public class WcfRoutesConstraint : IRouteConstraint {
    public WcfRoutesConstraint(params string[] values) {
        this._values = values;
    }

    private string[] _values;

    public bool Match(HttpContextBase httpContext, Route route, string parameterName,
RouteValueDictionary values, RouteDirection routeDirection) {

    // Get the value called "parameterName" from the
    // RouteValueDictionary called "value"
    string value = values[parameterName].ToString();

    // Return true is the list of allowed values contains
    // this value.
    bool match = !_values.Contains(value);
    return match;
    }
}

Assigning the constraint to the MVC routes

routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
        new { controller = new WcfRoutesConstraint(new string[] {"contact","login"}) }
    );

This prevents MVC from touching the Urls "/login" and "/contact"



回答2:

Found the answer. It is a known issue. Glenn Block posted a workaround. I just tested, and this does indeed fix the issue. It will be fixed with the next drop.

http://codebetter.com/glennblock/2011/08/05/integrating-mvc-routes-and-web-api-routes-2/



回答3:

In our next drop in our protoype branch we've included a WebApiRoute that addresses this (using the approach I mentioned in my blog post). MapServiceRoute uses it.