Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/gwt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 3 具有可选第一个参数的ASP.net MVC路由_Asp.net Mvc 3_Asp.net Mvc Routing_Optional Parameters - Fatal编程技术网

Asp.net mvc 3 具有可选第一个参数的ASP.net MVC路由

Asp.net mvc 3 具有可选第一个参数的ASP.net MVC路由,asp.net-mvc-3,asp.net-mvc-routing,optional-parameters,Asp.net Mvc 3,Asp.net Mvc Routing,Optional Parameters,我需要为其中一个网站提供以下功能 [赞助商]/{controller}/{action} 根据[赞助商],必须对网页进行定制 我尝试将路由注册为应用程序启动和会话启动,但无法使其工作 public static void RegisterRoutes(RouteCollection routes, string sponsor) { if (routes[sponsor] == null) { routes.MapRoute( sponsor, //

我需要为其中一个网站提供以下功能

[赞助商]/{controller}/{action}

根据[赞助商],必须对网页进行定制

我尝试将路由注册为应用程序启动和会话启动,但无法使其工作

public static void RegisterRoutes(RouteCollection routes, string sponsor)
{
        if (routes[sponsor] == null)
    {
      routes.MapRoute(
     sponsor, // Route name
     sponsor + "/{controller}/{action}/{id}", // URL with parameters
     new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
     );
    }
}
此外,没有[赞助商]的默认行为也应该起作用。 有人能告诉我在MVC3 URL中有一个可选的第一个参数在技术上是否可行吗。如果是,请分享实施情况。多谢各位


更新代码 在按照Sergey Kudriavtsev的建议进行更改之后,当给定值时,代码就会工作。 如果未提供名称,则MVC不会路由到控制器/操作

请注意,这仅适用于主控制器(包括主控制器和非主控制器)。对于其他控制器/操作,即使指定了发起人参数,也不是路由

请建议需要修改的内容

public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.MapRoute(
             "SponsorRoute",
             "{sponsor}/{controller}/{action}/{id}", // URL with parameters
             new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

        routes.MapRoute(
            "NonSponsorRoute",
            "{controller}/{action}/{id}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional, sponsor = string.Empty }
        );
    }
行动方法

public ActionResult Index(string sponsor)
    {
    }

在您的情况下,
赞助商
不应被视为URL的固定部分,而应被视为可变部分

在Global.asax中:

public static void RegisterRoutes(RouteCollection routes)
{
...
     routes.MapRoute(
     "SponsorRoute",
     "{sponsor}/{controller}/{action}/{id}", // URL with parameters
     new { controller = "Home", action = "Index", id = UrlParameter.Optional }
     );
     routes.MapRoute(
     "NonSponsorRoute",
     "{controller}/{action}/{id}",
     new { controller = "Home", action = "Index", id = UrlParameter.Optional, sponsor=string.Empty }
     );

...
}
在控制器中,例如HomeController.cs:

namespace YourWebApp.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index(string sponsor)
        {
            // Here you can do any pre-processing depending on sponsor value, including redirects etc.
        }
        ...
    }
}
请注意,此参数的类型将始终为
System.String
,路由模板组件的名称
{shandor}
必须与控制器中的操作参数
String shandor
的名称完全匹配

UPD:增加了非赞助商案例的第二条路线

请注意,这样的设置将使您的逻辑复杂化,因为您可能会混淆不同的URL,例如URL

可由两条路线匹配:第一条路线的赞助商=a,控制器=b,行动=c;第二个将具有控制器=a、操作=b和id=c

如果您对URL指定更严格的要求,则可以避免这种情况——例如,您可能希望ID仅为数字。限制在
routes.MapRoute()
函数的第四个参数中指定

另一种消除歧义的方法是在为赞助商指定通用路由之前,为所有控制器指定单独的路由(通常应用程序中不会有太多控制器)

UPD:

区分发起方和非发起方路由的最直接但最不易维护的方法是指定特定于控制器的路由,如下所示:

public static void RegisterRoutes(RouteCollection routes)
{
...
     routes.MapRoute(
     "HomeRoute",
     "Home/{action}/{id}", // URL with parameters
     new { controller = "Home", action = "Index", id = UrlParameter.Optional, sponsor=string.Empty }
     );
     routes.MapRoute(
     "AccountRoute",
     "Account/{action}/{id}", // URL with parameters
     new { controller = "Account", action = "Index", id = UrlParameter.Optional, sponsor=string.Empty }
     );

     ...

     routes.MapRoute(
     "SponsorRoute",
     "{sponsor}/{controller}/{action}/{id}", // URL with parameters
     new { controller = "Home", action = "Index", id = UrlParameter.Optional }
     );

...
}
public class MultiCultureMvcRouteHandler : MvcRouteHandler
{
  protected override IHttpHandler GetHttpHandler(System.Web.Routing.RequestContext requestContext)
  {
    var culture = CultureManager.GetCulture(requestContext.RouteData);

    if (culture != null)
    {
      var cultureInfo = new CultureInfo(culture.Name);

      Thread.CurrentThread.CurrentUICulture = cultureInfo;
      Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureInfo.Name);
    }

    return base.GetHttpHandler(requestContext);
  }
}
请注意,此处所有控制器特定的路由必须在发起路由之前添加


更复杂但更干净的方法是为赞助商和控制器名称实施RouteConstraint,如@CouncellorBen的回答中所述。

除了在默认路由之前添加第二条路由之外,正如Sergey在他的回答中所说,您还必须在初始路由中添加一条
RouteConstraint
,以强制执行
{赞助商}
令牌是有效赞助商的名称

您可以在此答案中使用RouteConstraint:


请记住,您还必须强制执行一条规则,即赞助商名称不能与您的任何控制器名称相同。

在我的情况下,我已使用以下两个路由器解决了此问题:

public class RouteConfig
{
  public static void RegisterRoutes(RouteCollection routes)
  {
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        name: "MultiCulture",
        url: "{culture}/{controller}/{action}",
        defaults: new { controller = "Home", action = "Index" },
        constraints: new { culture = new CultureConstraint(CultureFactory.All.Select(item => item.UrlPrefix).ToArray()) }
    ).RouteHandler = new MultiCultureMvcRouteHandler();

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}",
        defaults: new { controller = "Home", action = "Index" }
    );
  }
}
其中
CultureConstraint
类如下所示:

public class CultureConstraint : IRouteConstraint
{
  private readonly string[] values;

  public CultureConstraint(params string[] values)
  {
    this.values = values;
  }

  public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary routeValues, RouteDirection routeDirection)
  {
    string value = routeValues[parameterName].ToString();

    return this.values.Contains(value);
  }
}
MultiCultureMvcRouteHandler
如下所示:

public static void RegisterRoutes(RouteCollection routes)
{
...
     routes.MapRoute(
     "HomeRoute",
     "Home/{action}/{id}", // URL with parameters
     new { controller = "Home", action = "Index", id = UrlParameter.Optional, sponsor=string.Empty }
     );
     routes.MapRoute(
     "AccountRoute",
     "Account/{action}/{id}", // URL with parameters
     new { controller = "Account", action = "Index", id = UrlParameter.Optional, sponsor=string.Empty }
     );

     ...

     routes.MapRoute(
     "SponsorRoute",
     "{sponsor}/{controller}/{action}/{id}", // URL with parameters
     new { controller = "Home", action = "Index", id = UrlParameter.Optional }
     );

...
}
public class MultiCultureMvcRouteHandler : MvcRouteHandler
{
  protected override IHttpHandler GetHttpHandler(System.Web.Routing.RequestContext requestContext)
  {
    var culture = CultureManager.GetCulture(requestContext.RouteData);

    if (culture != null)
    {
      var cultureInfo = new CultureInfo(culture.Name);

      Thread.CurrentThread.CurrentUICulture = cultureInfo;
      Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureInfo.Name);
    }

    return base.GetHttpHandler(requestContext);
  }
}

我将在一个简单的示例中向您展示,您不必在Route.config.cs 只需在Route.config.cs中执行操作即可

首选可选URI参数和默认值

routes.MapMvcAttributeRoutes();
Route.config.cs

routes.MapMvcAttributeRoutes();
控制器

[Route("{Name}/Controller/ActionName")]
        public ActionResult Details(string Name)
        {            

              // some code here 

            return View();
        }
结果

routes.MapMvcAttributeRoutes();

localhost:2345/Name/controllername/actionname/id(可选)

感谢您的回复。[发起人]应为可选参数。使用{shandor}/{controller}/{action}/{id},url home/索引将被视为[home==shandor]/[index==controller],这将引发资源未找到异常。然后您将需要两个单独的路由-一个有{shandor},另一个没有,我将编辑我的答案一点…您有多少个控制器?你能列出他们的名字吗?这里有7-8个控制器。如果你能建议如何使它为一个功能,我会修改其他。示例控制器:1。家2。帐户…更新了我的答案。我添加的一个简单解决方案对于7-8个控制器或多或少都是可行的,但您应该记住,对于以后添加的每个控制器,您必须添加另一个特定于控制器的路由。如果您希望现在多做一点工作以节省以后的时间,那么您应该实现@consuellorben的答案
CultureFactory。我想,All
会返回一个区域性代码列表,如“de”、“en”、“pl”等@UweKeim抱歉,太晚了,但是是的,你是对的。它返回列表的集合。