问题
I have a legacy url that I wish to map to a route in my ASP.Net MVC application
e.g. http://my.domain.com/article/?action=detail&item=22
Now in route creation action
has a special meaning so my to create this route? The controller is a RedirectController and the action is Item.
routes.MapRoute(
name: "Redirect",
url: "article",
defaults:new { controller = "redirect", action = "item"}
);
So my problem is that action
in the query string gets overwritten by the action
in the defaults
. Is there a way to get around this?
回答1:
controller
,action
and area
are the only reserved words in asp.net MVC. "Reserved" means that MVC gives special meaning to them, especially for Routing.
There are also others words (COM1-9
, LPT1-9
, AUX
, PRT
, NUL
, CON
), not specific to asp.net, than can not be in the url. This is explained why here and how to by-pass here.
Edit : There are no ways to use them because asp.net mvc relies on them in route data.
Here is an decompiled example taken from UrlHelper :
// System.Web.Mvc.RouteValuesHelpers
public static RouteValueDictionary MergeRouteValues(string actionName, string controllerName, RouteValueDictionary implicitRouteValues, RouteValueDictionary routeValues, bool includeImplicitMvcValues)
{
RouteValueDictionary routeValueDictionary = new RouteValueDictionary();
if (includeImplicitMvcValues)
{
object value;
if (implicitRouteValues != null && implicitRouteValues.TryGetValue("action", out value))
{
routeValueDictionary["action"] = value;
}
if (implicitRouteValues != null && implicitRouteValues.TryGetValue("controller", out value))
{
routeValueDictionary["controller"] = value;
}
}
if (routeValues != null)
{
foreach (KeyValuePair<string, object> current in RouteValuesHelpers.GetRouteValues(routeValues))
{
routeValueDictionary[current.Key] = current.Value;
}
}
if (actionName != null)
{
routeValueDictionary["action"] = actionName;
}
if (controllerName != null)
{
routeValueDictionary["controller"] = controllerName;
}
return routeValueDictionary;
}
回答2:
I have managed to crack it using a custom ModelBinder. I create a basic class called QueryString
public class QueryString
{
private readonly IDictionary<string,string> _pairs;
public QueryString()
{
_pairs = new Dictionary<string, string>();
}
public void Add(string key, string value)
{
_pairs.Add(key.ToUpper(), value);
}
public string Get(string key)
{
return _pairs[key.ToUpper()];
}
public bool Contains(string key)
{
return _pairs.ContainsKey(key.ToUpper());
}
}
Then I create my custom binder for that:-
public class QueryStringModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var queryString = new QueryString();
var keys = controllerContext.HttpContext.Request.QueryString.AllKeys;
foreach (var key in keys)
{
queryString.Add(key, controllerContext.HttpContext.Request.QueryString[key]);
}
return queryString;
}
}
In my Global.asax I register it:-
ModelBinders.Binders.Add(typeof(QueryString), new QueryStringModelBinder());
Now I can use that in my RedirectController:-
public RedirectToRouteResult Item(QueryString queryString)
{
// user QueryString object to get what I need
// e.g. queryString.Get("action");
}
来源:https://stackoverflow.com/questions/17669244/routing-reserved-words-in-asp-net