ASP.Net MVC 使用路由处理段
ASP.Net MVC Handling Segments with Route
我是 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 时,我总是在类别参数中得到 null
http://localhost:50877/Home/CategoryProducts/c_50_ShowcasesDisplays
我收到这个错误
Object reference not set to an instance of an object
我该如何解决这个问题。我需要从段中提取 id 并使用它。同样,我也需要处理制造商和属性字符串。
还有一件事
如何让我的函数无论顺序如何至少获得一个参数?我的意思是我想制作这样的功能,我可以处理类别或制造商或属性或类别 + 制造商以及所有组合/
占位符(例如{category}
)就像一个变量——它可以包含任何值。框架必须能够理解 URL 中参数的含义。您可以通过以下三种方式之一执行此操作:
- 按特定顺序提供它们,并提供特定数量的细分
- 将它们放入查询字符串中,这样您就有 name/value 对来识别它们是什么
- 制作一系列带有文字段的路线,以提供名称来识别参数是什么
这是选项 #3 的示例。与使用查询字符串参数相比,它有点复杂,但只要您为每个路由段提供某种标识符,它肯定是可能的。
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:
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:
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
、
时,也会生成相应的URL
@Html.ActionLink("ShowcasesDisplays", "CategoryProducts", "Home",
new { category = "c_50_ShowcasesDisplays" }, null)
// Generates URL /Home/CategoryProducts/category/c_50_ShowcasesDisplays
我是 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 时,我总是在类别参数中得到 null
http://localhost:50877/Home/CategoryProducts/c_50_ShowcasesDisplays
我收到这个错误
Object reference not set to an instance of an object
我该如何解决这个问题。我需要从段中提取 id 并使用它。同样,我也需要处理制造商和属性字符串。
还有一件事
如何让我的函数无论顺序如何至少获得一个参数?我的意思是我想制作这样的功能,我可以处理类别或制造商或属性或类别 + 制造商以及所有组合/
占位符(例如{category}
)就像一个变量——它可以包含任何值。框架必须能够理解 URL 中参数的含义。您可以通过以下三种方式之一执行此操作:
- 按特定顺序提供它们,并提供特定数量的细分
- 将它们放入查询字符串中,这样您就有 name/value 对来识别它们是什么
- 制作一系列带有文字段的路线,以提供名称来识别参数是什么
这是选项 #3 的示例。与使用查询字符串参数相比,它有点复杂,但只要您为每个路由段提供某种标识符,它肯定是可能的。
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:
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:
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
、
@Html.ActionLink("ShowcasesDisplays", "CategoryProducts", "Home",
new { category = "c_50_ShowcasesDisplays" }, null)
// Generates URL /Home/CategoryProducts/category/c_50_ShowcasesDisplays