ASP.Net MVC 使用路由处理段 [英] ASP.Net MVC Handling Segments with Route

查看:19
本文介绍了ASP.Net MVC 使用路由处理段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 ASP.Net MVC 的新手,遇到了一个问题.在这里.

I am new to ASP.Net MVC and facing a problem. Here it is.

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

when i hit the url i always get null in category parameter

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

我收到此错误

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

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

How can i fix this problem. I need to extract the id from segment and use it. Similarly i need to process the manufacturer and attribute strings too.

还有一件事

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

How can i make my function get at least one parameter regardless of order? I mean i want to make functions like that i can handle category or manufacturer or attributes or category + manufacturer and all the combinations/

推荐答案

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

A placeholder (such as {category}) acts like a variable - it can contain any value. The framework must be able to understand what the parameters in the URL mean. You can do this one of three ways:

  1. 按特定顺序提供它们,并提供特定数量的细分
  2. 将它们放入查询字符串中,以便您拥有名称/值对来识别它们的含义
  3. 制作一系列带有文字段的路由,以提供名称来标识参数是什么

这是选项 #3 的示例.与使用查询字符串参数相比,这有点复杂,但只要您为每个路段提供某种标识符,这当然是可能的.

Here is an example of option #3. It is a bit involved compared to using query string parameters, but it is certainly possible as long as you provide some sort of identifier for each route segment.

这增加了 LINQ 支持,能够获取参数值的所有可能排列.

This adds LINQ support for being able to get every possible permutation of parameter values.

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 的所有可能排列的功能.

RouteCollection Extensions

We extend the MapRoute extension method, adding the ability to add a set of routes to match all possible permutations of the 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 模式:

This adds a complete set of routes to match the URL patterns:

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 时:

Now when you use the following URL:

Home/CategoryProducts/category/c_50_ShowcasesDisplays

将调用 HomeController 上的操作 CategoryProducts.您的类别参数值为 c_50_ShowcasesDisplays.

The action CategoryProducts on the HomeController will be called. Your category parameter value will be c_50_ShowcasesDisplays.

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

It will also build the corresponding URL when you use ActionLink, RouteLink, Url.Action, or UrlHelper.

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

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

这篇关于ASP.Net MVC 使用路由处理段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆