MVC url路由键值对参数

时间:2011-09-08 08:12:12

标签: c# asp.net-mvc model-view-controller asp.net-mvc-3 url-routing

我知道我可以创建支持此网址的网址映射

user / idex / userId / 1 / categoryId / abc

ActionResult Index (String userId, String categoryID)

我想知道是否有可能推广这种机制并编写一个可以支持作为键/值对传递的所有基于url的参数的映射。

controller / action / * key1 / value1 / key2 / value2 .... *

我需要支持单个映射,例如所有这些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)

新闻/明细/ newsId / 1 / groupId / 2 / 选项 / 3

ActionResult Index (newsid String, String groupId, String optionId)

2 个答案:

答案 0 :(得分:0)

我认为你不能这样做,但你可以这样做:

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

但是你想要使用它的所有动作,那么方法应该被定义为

ActionResult ActionName (string id, string groupid)

提供新闻/详情/ 1/2 类别/索引/ 1/2

答案 1 :(得分:0)

我做到了!!

使用自定义值提供程序!

我更改了值对参数

的格式

来自 key1 / value1 / key2 / value2

更清晰 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;
            }
        }
    }
}

当然,它可以使用正则表达式进行。

然后,在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());
}