ASP.Net MVC处理段与路由
我是新的ASP.Net MVC,并面临一个问题。 这里是。
routes.MapRoute( "SearchResults",// Route name "{controller}/{action}/{category}/{manufacturer}/{attribute}", new { controller = "Home", action = "CategoryProducts", category = UrlParameter.Optional, manufacturer = UrlParameter.Optional, attribute = UrlParameter.Optional } );
这是我的控制器方法。
public ActionResult CategoryProducts(string category, string manufacturer, string attribute) { string[] categoryParameter = category.Split('_'); . . . return View(); }
当我打我的url,我总是在类别参数为空
http://localhost:50877/Home/CategoryProducts/c_50_ShowcasesDisplays
我得到这个错误
Object reference not set to an instance of an object
我该如何解决这个问题。 我需要从段中提取ID并使用它。 同样我也需要处理制造商和属性string。
还有一件事
我怎样才能让我的function得到至less一个参数,不pipe顺序? 我的意思是我想做的function,我可以处理类别或制造商或属性或类别+制造商和所有组合/
占位符(例如{category}
)就像一个variables – 它可以包含任何值。 框架必须能够理解URL中的参数的含义。 您可以通过以下三种方法之一来完
- 以特定的顺序提供它们,并为特定数量的细分市场提供
- 把它们放在查询string中,所以你有名称/值对来标识它们是什么
- 制作一系列具有文字段的路线,以提供名称来识别参数
这是一个选项#3的例子。 与使用查询string参数相比,这有点牵扯,但只要您为每个路段提供某种标识符,这当然是可能的。
IEnumerable扩展
这增加了LINQ支持,以便能够获得参数值的每个可能的排列。
using System; using System.Collections.Generic; using System.Linq; public static class IEnumerableExtensions { // Can be used to get all permutations at a certain level // Source: http://stackoverflow.com/questions/127704/algorithm-to-return-all-combinations-of-k-elements-from-n#1898744 public static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> elements, int k) { return k == 0 ? new[] { new T[0] } : elements.SelectMany((e, i) => elements.Skip(i + 1).Combinations(k - 1).Select(c => (new[] { e }).Concat(c))); } // This one came from: http://stackoverflow.com/questions/774457/combination-generator-in-linq#12012418 private static IEnumerable<TSource> Prepend<TSource>(this IEnumerable<TSource> source, TSource item) { if (source == null) throw new ArgumentNullException("source"); yield return item; foreach (var element in source) yield return element; } public static IEnumerable<IEnumerable<TSource>> Permutations<TSource>(this IEnumerable<TSource> source) { if (source == null) throw new ArgumentNullException("source"); var list = source.ToList(); if (list.Count > 1) return from s in list from p in Permutations(list.Take(list.IndexOf(s)).Concat(list.Skip(list.IndexOf(s) + 1))) select p.Prepend(s); return new[] { list }; } }
RouteCollection扩展
我们扩展了MapRoute
扩展方法,增加了添加一组路由以匹配URL的所有可能的排列的能力。
using System; using System.Collections.Generic; using System.Web.Mvc; using System.Web.Routing; public static class RouteCollectionExtensions { public static void MapRoute(this RouteCollection routes, string url, object defaults, string[] namespaces, string[] optionalParameters) { MapRoute(routes, url, defaults, null, namespaces, optionalParameters); } public static void MapRoute(this RouteCollection routes, string url, object defaults, object constraints, string[] namespaces, string[] optionalParameters) { if (routes == null) { throw new ArgumentNullException("routes"); } if (url == null) { throw new ArgumentNullException("url"); } AddAllRoutePermutations(routes, url, defaults, constraints, namespaces, optionalParameters); } private static void AddAllRoutePermutations(RouteCollection routes, string url, object defaults, object constraints, string[] namespaces, string[] optionalParameters) { // Start with the longest routes, then add the shorter ones for (int length = optionalParameters.Length; length > 0; length--) { foreach (var route in GetRoutePermutations(url, defaults, constraints, namespaces, optionalParameters, length)) { routes.Add(route); } } } private static IEnumerable<Route> GetRoutePermutations(string url, object defaults, object constraints, string[] namespaces, string[] optionalParameters, int length) { foreach (var combination in optionalParameters.Combinations(length)) { foreach (var permutation in combination.Permutations()) { yield return GenerateRoute(url, permutation, defaults, constraints, namespaces); } } } private static Route GenerateRoute(string url, IEnumerable<string> permutation, object defaults, object constraints, string[] namespaces) { var newUrl = GenerateUrlPattern(url, permutation); var result = new Route(newUrl, new MvcRouteHandler()) { Defaults = CreateRouteValueDictionary(defaults), Constraints = CreateRouteValueDictionary(constraints), DataTokens = new RouteValueDictionary() }; if ((namespaces != null) && (namespaces.Length > 0)) { result.DataTokens["Namespaces"] = namespaces; } return result; } private static string GenerateUrlPattern(string url, IEnumerable<string> permutation) { string result = url; foreach (string param in permutation) { result += "/" + param + "/{" + param + "}"; } System.Diagnostics.Debug.WriteLine(result); return result; } private static RouteValueDictionary CreateRouteValueDictionary(object values) { IDictionary<string, object> dictionary = values as IDictionary<string, object>; if (dictionary != null) { return new RouteValueDictionary(dictionary); } return new RouteValueDictionary(values); } }
用法
public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( url: "Home/CategoryProducts", defaults: new { controller = "Home", action = "CategoryProducts" }, namespaces: null, optionalParameters: new string[] { "category", "manufacturer", "attribute" }); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } }
这添加了一组完整的路由来匹配URL模式:
Home/CategoryProducts/category/{category}/manufacturer/{manufacturer}/attribute/{attribute} Home/CategoryProducts/category/{category}/attribute/{attribute}/manufacturer/{manufacturer} Home/CategoryProducts/manufacturer/{manufacturer}/category/{category}/attribute/{attribute} Home/CategoryProducts/manufacturer/{manufacturer}/attribute/{attribute}/category/{category} Home/CategoryProducts/attribute/{attribute}/category/{category}/manufacturer/{manufacturer} Home/CategoryProducts/attribute/{attribute}/manufacturer/{manufacturer}/category/{category} Home/CategoryProducts/category/{category}/manufacturer/{manufacturer} Home/CategoryProducts/manufacturer/{manufacturer}/category/{category} Home/CategoryProducts/category/{category}/attribute/{attribute} Home/CategoryProducts/attribute/{attribute}/category/{category} Home/CategoryProducts/manufacturer/{manufacturer}/attribute/{attribute} Home/CategoryProducts/attribute/{attribute}/manufacturer/{manufacturer} Home/CategoryProducts/category/{category} Home/CategoryProducts/manufacturer/{manufacturer} Home/CategoryProducts/attribute/{attribute}
现在,当您使用以下url时:
Home/CategoryProducts/category/c_50_ShowcasesDisplays
HomeController
上的操作CategoryProducts
将被调用。 你的分类参数值将是c_50_ShowcasesDisplays
。
当您使用ActionLink
, RouteLink
, Url.Action
或UrlHelper
时,它也会build立相应的URL。
@Html.ActionLink("ShowcasesDisplays", "CategoryProducts", "Home", new { category = "c_50_ShowcasesDisplays" }, null) // Generates URL /Home/CategoryProducts/category/c_50_ShowcasesDisplays