ASP.Net MVC 使用路由处理段

标签 asp.net asp.net-mvc routes action asp.net-mvc-routing

我是 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 
    }
);

这是我的 Controller 方法。

public ActionResult CategoryProducts(string category, string manufacturer, string attribute) 
{
    string[] categoryParameter = category.Split('_');
    .
    .
    .
    return View();
}

当我点击网址时,类别参数中总是为空

http://localhost:50877/Home/CategoryProducts/c_50_ShowcasesDisplays

我收到此错误

未将对象引用设置为对象实例

我该如何解决这个问题。我需要从段中提取 id 并使用它。同样,我也需要处理制造商和属性字符串。

还有一件事

如何使我的函数至少获得一个参数(无论顺序如何)?我的意思是我想要制作这样的功能,我可以处理类别或制造商或属性或类别+制造商以及所有组合/

最佳答案

占位符(例如{category})就像一个变量 - 它可以包含任何值。框架必须能够理解 URL 中的参数的含义。您可以通过以下三种方式之一执行此操作:

  1. 按特定顺序并针对特定数量的分割提供它们
  2. 将它们放入查询字符串中,以便您可以通过名称/值对来识别它们
  3. 使用文字段创建一系列路由,以提供名称来识别参数是什么

这是选项#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: 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 };
    }
}

路由集合扩展

我们扩展了 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

当您使用 ActionLinkRouteLinkUrl.ActionUrlHelper 时,它还会构建相应的 URL >.

@Html.ActionLink("ShowcasesDisplays", "CategoryProducts", "Home", 
    new { category = "c_50_ShowcasesDisplays" }, null)

// Generates URL /Home/CategoryProducts/category/c_50_ShowcasesDisplays

关于ASP.Net MVC 使用路由处理段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32476261/

相关文章:

c# - 如何修复传入字典的模型项类型错误?

c# - .Where Lambda 表达式加载整个表

ruby-on-rails - 创建新的Rails Action 行不通吗?

javascript - 如何正确使用Express 4多路路由器

jquery - jquery如何计算字符串中字符出现的次数

asp.net - 在 Entity Framework 5 中重命名导航属性不会更新代码

asp.net - CSS 问题 : google Chrome not displaying the back groung Image and hence Drop down list not getting displayed properly

c# - 如何使用 C# .NET 4 实现 DDD

routes - BottomNavigationBar保存偏移位置并导航到细节 flutter

c# - 固定顶部导航栏覆盖按钮