ASP.net маршрутизация MVC с дополнительным первым параметром

мне нужно предоставить следующие возможности для одного из веб-сайтов.

http://www.example.com/[sponsor]/{controller}/{action}

в зависимости от [спонсор], веб-страница должна быть настроена.

я попробовал комбинацию регистрации маршрутов с Application_Start и Session_Start, но не смог заставить ее работать.

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

кроме того, поведение по умолчанию без [спонсор] должны также функция. Может кто-нибудь, пожалуйста, дайте мне знать, если технически возможно иметь дополнительный первый параметр в URL MVC3. Если да, пожалуйста, поделитесь реализации. Спасибо.


Обновленный Код После внесения изменений, предложенных Сергей Кудрявцев, код работает, когда стоимости дают. Если имя не указано, то MVC не маршрутизирует к контроллеру / действию.

обратите внимание, что это работает только для контроллера Home (оба и не являются спонсорами). Для других контроллеров / действий, даже если указан параметр спонсора, это не маршрутизация.

пожалуйста, предложите, что должно быть изменено.

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

4 ответов


в вашем случае sponsor следует рассматривать не как постоянную часть URL, а как переменную часть.

В Глобальном.асакс:

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 и имя компонента шаблона маршрута {sponsor} должно точно соответствовать имени параметра action string sponsor в своих контроллерах.

UPD: добавлен второй маршрут для не-спонсора случай.

обратите внимание, что такая настройка усложнит вашу логику, потому что вы можете спутать разные URL, например URL

http://www.example.com/a/b/c

может совпадать по обоим маршрутам: первый будет иметь sponsor=a, controller=b и action=c; второй будет иметь controller=a, action=b и id=c.

этой ситуации можно избежать, если вы укажете более строгие требования к URL-адресам - например, вы можете захотеть, чтобы идентификаторы были только численное. Ограничения указаны в четвертом параметре


в моем случае, я решил эту проблему с помощью следующих маршрутизаторов:

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 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 на начальный маршрут, чтобы обеспечить, чтобы {sponsor} token - это имя действительного спонсора.

Вы можете использовать RouteConstraint в этом ответе:Asp.Net пользовательская Маршрутизация и пользовательская маршрутизация и добавление категории перед контроллером

помните, что вы должны также применить правило, что имя спонсора не может быть таким же, как любой из ваших имена контроллеров.


Я покажу вам в простом примере, что вам не нужно меняться в маршрут.конфиг.cs только вы должны сделать в маршрут.конфиг.cs просто введите

необязательные параметры URI сначала и по умолчанию Значения

маршрут.конфиг.cs

routes.MapMvcAttributeRoutes();

контроллер

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

              // some code here 

            return View();
        }

результаты

localhost: 2345 / Name / controllername/actionname / id(необязательно)