开发者

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());
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜