MVC url routing key value pairs parameters
I know that I can create a url mapping that supports this 开发者_开发技巧url
user / idex / userId / 1 / categoryId / abc
ActionResult Index (String userId, String categoryID)
What I wonder is whether it is possible to generalize this mechanism and write a single mapping that can support all url-based parameters passed as key / value pairs.
controller / action / *key1 / value1 / key2 / value2 ....*
With a single mapping I need to supported for example all these url
user / idex / userId / 1 / categoryId / abc
ActionResult Index (String userId, String categoryID)
category / idex / catId / 1 / groupId / 2
ActionResult Index (catId String, String groupId)
category / idex / catId / 1 / groupId / 2
ActionResult Index (catId String, String groupId)
news / detail / newsId / 1 / groupId / 2 / option / 3
ActionResult Index (newsid String, String groupId, String optionId)
I don't think you can do it that way, but you could do:
routes.MapRoute(
"Grouped", // Route name
"{controller}/{action}/{id}/{groupid}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional, groupid = UrlParameter.Optional } // Parameter defaults
);
But then all the actions you want to use this for, there methods should be defined as
ActionResult ActionName (string id, string groupid)
giving news/detail/1/2 and category/index/1/2
I did it!!
using a custom value provider!
I changed the format of the value pairs parameter
from key1 / value1 / key2 / value2
to a more clear key1=value1;key2=value2
public class KeyValuePairValueProviderFactory : ValueProviderFactory {
public override IValueProvider GetValueProvider(ControllerContext controllerContext) {
return new KeyValuePairValueProvider(controllerContext.HttpContext.Request.Path);
}
private class KeyValuePairValueProvider : IValueProvider {
private readonly Dictionary<String,String> _valuesDictionary = new Dictionary<String,String>();
public bool ContainsPrefix(string prefix) {
return true;
}
public KeyValuePairValueProvider(String rawUrl) {
// The url have to be in this format
// controller/key=value
// controller/key=value/
// controller/key=value?op=1
// controller/key=value/?op=1
// controller/action/key=value
// controller/action/key=value?op=1
// controller/action/key=value/?op=1
// controller/action/key=value;key=value
// controller/action/key=value;key=value?op=1
// controller/action/key=value;key=value/?op=1
String parameters = "";
// removing the querystring
if(rawUrl.Contains("?")){
// i split on the ? and take the first part
rawUrl = rawUrl.Split('?')[0];
}
// controller/key=value
// controller/action/key=value
// controller/action/key=value/
// controller/action/key=value;key=value
// check if the url without the querystring contains a = simbol
// if yes I proceed into extract parameters
if(rawUrl.Contains("=")){
// removing last slash
if (rawUrl.LastIndexOf('/')+1 == rawUrl.Length) {
rawUrl = rawUrl.Remove(rawUrl.LastIndexOf('/'));
}
int startIndex = rawUrl.LastIndexOf("/")+1;
int endIndex = rawUrl.Length;
int lenght = endIndex-startIndex;
parameters = rawUrl.Substring(startIndex,lenght);
String[] pairs = parameters.Split(';');
foreach (String pair in pairs) {
String key = pair.Split('=')[0];
String value = pair.Split('=')[1];
_valuesDictionary.Add(key, value);
}
}
}
public ValueProviderResult GetValue(string key) {
if (_valuesDictionary.ContainsKey(key)) {
return new ValueProviderResult(
_valuesDictionary[key]
, _valuesDictionary[key]
, CultureInfo.CurrentUICulture);
} else {
return null;
}
}
}
}
Sure, it can be enanced using regex.
Then, in the global.asax
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{*catchall}", // URL with parameters
new { controller = "Home", action = "Index" } // Parameter defaults
);
}
protected void Application_Start() {
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
ValueProviderFactories.Factories.Add(new KeyValuePairValueProviderFactory());
}
精彩评论