ASP.Net MVC处理细分路线 [英] ASP.Net MVC Handling Segments with Route

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

问题描述

我是新来的ASP.Net MVC和面临的一个问题。这就是。

  routes.MapRoute(
    的SearchResult,//路线名称
    {控制器} / {行动} / {类别} / {制造商} / {}属性,
    新{
        控制器=家,
        行动=CategoryProducts
        类别= UrlParameter.Optional,
        制造商= UrlParameter.Optional,
        属性= UrlParameter.Optional
    }
);

这是我的控制器的方法。

 公众的ActionResult CategoryProducts(串类,串制造商,字符串属性)
{
    字符串[] = categoryParameter category.Split('_');
    。
    。
    。
    返回查看();
}

当我打的网址,我总是得到类别参数为空

 的http://本地主机:50877 /主页/ CategoryProducts / c_50_ShowcasesDisplays

我得到这个错误

对象引用不设置到对象的实例

我怎样才能解决这个问题。我需要提取从段id和使用它。同样地,我需要处理的制造商和属性串了。

还有一件事

我怎样才能让我的功能得到至少一个参数,无论秩序?我的意思是我要做出那样的我能处理类别或制造商或属性或类别+制造商和功能的所有组合/


解决方案

一个占位符(如 {类别} )的作用就像一个变量 - 它可以包含任何价值。该框架必须能够理解在URL中参数的含义。你可以做三种方式这一个:


  1. 在一个特定的顺序提供它们,并为部分特定数量的

  2. 把它们在查询字符串,所以你有名称/值对,以确定它们是什么

  3. 请了一系列的文字段路线提供名称来识别的参数是什么

下面是选项#3的例子。它是相对于使用查询字符串参数涉及了一点,但肯定是可以的,只要你提供某种标识符每条路段的。

的IEnumerable扩展

这增加了能够得到的参数值的每一种可能的排列LINQ的支持。

 使用系统;
使用System.Collections.Generic;
使用System.Linq的;公共静态类IEnumerableExtensions
{
    //可用于在一定的水平,以获得所有排列
    // 资源: http://stackoverflow.com/questions/127704/algorithm-to-return-all-combinations-of-k-elements-from-n#1898744
    公共静态的IEnumerable<&IEnumerable的LT; T>>组合< T>(这个IEnumerable的< T>元素,诠释K)
    {
        复位K == 0?新的[] {新的T [0]}:
            elements.SelectMany((E,I)=>
            elements.Skip第(i + 1).Combinations(K - 1)。选择(C =方式>(新[] {}ë)CONCAT(C)));
    }    //这一次来自:http://stackoverflow.com/questions/774457/combination-generator-in-linq#12012418
    私有静态的IEnumerable< TSource> prePEND< TSource>(这个IEnumerable的< TSource>源,TSource项)
    {
        如果(来源== NULL)
            抛出新的ArgumentNullException(源);        产生回报的项目;        的foreach(源VAR元素)
            产量返回元素;
    }    公共静态的IEnumerable<&IEnumerable的LT; TSource>>排列< TSource>(这个IEnumerable的< TSource>源)
    {
        如果(来源== NULL)
            抛出新的ArgumentNullException(源);        VAR列表= source.ToList();        如果(list.Count→1)
            从s列表中返回
                   从置换P(list.Take(list.IndexOf(多个))。CONCAT(list.Skip(list.IndexOf(多个)+ 1)))
                   器选择p prePEND(S)。        返回新的[] {list}里;
    }
}

RouteCollection扩展

我们延长图路线扩展方法,将添加一组路线相匹配的URL的所有可能的排列的能力。

 使用系统;
使用System.Collections.Generic;
使用System.Web.Mvc;
使用System.Web.Routing;公共静态类RouteCollectionExtensions
{
    公共静态无效图路线(这RouteCollection路线,字符串的URL,对象违约,字符串[]命名空间的String [] optionalParameters)
    {
        图路线(路线,URL,缺省值,空,命名空间,optionalParameters);
    }    公共静态无效图路线(这RouteCollection路线,字符串的URL,对象的默认值,对象的限制,字符串[]命名空间的String [] optionalParameters)
    {
        如果(路线== NULL)
        {
            抛出新的ArgumentNullException(路线);
        }
        如果(URL == NULL)
        {
            抛出新的ArgumentNullException(URL);
        }
        AddAllRoutePermutations(路线,URL,默认,约束,命名空间,optionalParameters);
    }    私有静态无效AddAllRoutePermutations(RouteCollection路线,字符串的URL,对象的默认值,对象的限制,字符串[]命名空间的String [] optionalParameters)
    {
        //最长的路线开始,然后添加短的
        对于(INT长度= optionalParameters.Length;长度大于0; length--)
        {
            的foreach(在GetRoutePermutations(VAR URL路径,默认的限制,命名空间,optionalParameters,长度))
            {
                routes.Add(路线);
            }
        }
    }    私有静态的IEnumerable<路线和GT; GetRoutePermutations(字符串的URL,对象的默认值,对象的限制,字符串[]命名空间的String [] optionalParameters,INT长度)
    {
        的foreach(在optionalParameters.Combinations变种组合(长度))
        {
            的foreach(在combination.Permutations变种置换())
            {
                产量返回GenerateRoute(URL,置换,默认,约束,命名空间);
            }
        }
    }    私人静态路由GenerateRoute(字符串URL,IEnumerable的<串GT;排列,对象的默认值,对象的限制,字符串[]命名空间)
    {
        VAR NEWURL = GenerateUrlPattern(URL,置换);
        VAR的结果=新干线(NEWURL,新MvcRouteHandler())
        {
            默认值= CreateRouteValueDictionary(默认)
            约束= CreateRouteValueDictionary(约束)
            DataTokens =新RouteValueDictionary()
        };
        如果((命名空间= NULL)及!及(namespaces.Length大于0))
        {
            result.DataTokens [命名空间] =命名空间;
        }        返回结果;
    }    私人静态字符串GenerateUrlPattern(字符串URL,IEnumerable的<串GT;置换)
    {
        字符串结果=网址;
        的foreach(以置换字符串参数)
        {
            结果+ =/+参数+/ {+参数+};
        }        System.Diagnostics.Debug.WriteLine(结果);        返回结果;
    }    私有静态RouteValueDictionary CreateRouteValueDictionary(对象值)
    {
        IDictionary的<字符串对象>字典=值的IDictionary<字符串对象&gt ;;
        如果(字典!= NULL)
        {
            返回新RouteValueDictionary(字典);
        }
        返回新RouteValueDictionary(值);
    }
}

用法

 公共类RouteConfig
{
    公共静态无效的RegisterRoutes(RouteCollection路线)
    {
        routes.IgnoreRoute({}资源个.axd / {*} PATHINFO);        routes.MapRoute(
            网址:首页/ CategoryProducts
            默认:新{控制器=家,行动=CategoryProducts},
            命名空间:空,
            optionalParameters:新的String [] {类别,制造商,属性});        routes.MapRoute(
            名称:默认,
            网址:{控制器} / {行动} / {ID}
            默认:新{控制器=家,行动=索引,ID = UrlParameter.Optional}
        );
    }
}

这增加了一套完整的航线相匹配的URL模式:

<$p$p><$c$c>Home/CategoryProducts/category/{category}/manufacturer/{manufacturer}/attribute/{attribute}
首页/ CategoryProducts /分类/ {}类/属性/ {}属性/制造商/生产商{}
首页/ CategoryProducts /制造商/生产商{} /分类/ {}类/属性/ {}属性
首页/ CategoryProducts /制造商/生产商{} /属性/ {}属性/分类/ {}类
首页/ CategoryProducts /属性/ {}属性/分类/ {}类/制造商/生产商{}
首页/ CategoryProducts /属性/ {}属性/制造商/生产商{} /分类/ {}类
首页/ CategoryProducts /分类/ {}类/制造商/生产商{}
首页/ CategoryProducts /制造商/生产商{} /分类/ {}类
首页/ CategoryProducts /分类/ {}类/属性/ {}属性
首页/ CategoryProducts /属性/ {}属性/分类/ {}类
首页/ CategoryProducts /制造商/生产商{} /属性/ {}属性
首页/ CategoryProducts /属性/ {}属性/制造商/生产商{}
首页/ CategoryProducts /分类/ {}类
首页/ CategoryProducts /制造商/生产商{}
首页/ CategoryProducts /属性/ {}属性

现在,当您使用以下网址:

  

的HomeController 将被称为行动 CategoryProducts 。您的类别参数值将是 c_50_ShowcasesDisplays

这也将建立相应的网址,当您使用 ActionLink的 RouteLink 网​​址.Action UrlHelper

  @ Html.ActionLink(ShowcasesDisplays,CategoryProducts,家,
    新{类=c_50_ShowcasesDisplays},NULL)//生成URL /主页/ CategoryProducts /分类/ c_50_ShowcasesDisplays

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

And here is my controller method.

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

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

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

I get this error

Object reference not set to an instance of an object

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.

One more thing

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/

解决方案

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. Provide them in a specific order, and for a specific number of segments
  2. Put them in the query string so you have name/value pairs to identify what they are
  3. Make a series of routes with literal segments to provide names to identify what the parameters are

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.

IEnumerable Extensions

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 };
    }
}

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

Usage

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

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}

Now when you use the following URL:

Home/CategoryProducts/category/c_50_ShowcasesDisplays

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

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天全站免登陆