2010-12-30 11 views
7

Mam problem z określonym ograniczeniem, które próbuję skonfigurować na trasie. Mój adres URL musi wyglądać tak: http://hostname/id-my-title-can-be-that-long gdzie id składa się wyłącznie z cyfr, a tytuł jest pisany małymi literami z separatorem myślników. Identyfikator i tytuł są również oddzielone myślnikiem. Na przykład: http://hostname/123-my-title.Ograniczenie trasy regex ASP.NET MVC

Oto moja definicja trasa:

routes.MapRoute(
    "Test", 
    "{id}-{title}", 
    new { controller = "Article", action = "Index" }, 
    new { id = @"(\d)+", title = @"([a-z]+-?)+" } 
); 

URL jest prawidłowo generowany z pomocnika html:

<%: Html.ActionLink("My link", "Index", "Article", new { id = Model.IdArticle, title = Model.UrlTitle }, null) %> 

gdzie, oczywiście, Model.IdArticle stanowi Int32 i Model.UrlTitle preformowany ciąg mojego tytułu pasujący do moich wymagań (tylko małe litery, spacja zastąpiona myślnikami).

Problem polega na tym, że po kliknięciu łącza nie jest wywoływana właściwa kontrolka &, ponieważ przechodzi do następnej trasy, która jest nieprawidłowa.

dla rekordów, jestem na ASP.NET MVC 2.

Ktoś ma pomysł?

Dzięki z góry, Fabian

+0

Wreszcie, oddzielimy identyfikator od tytułu za pomocą nieokreślonego. Nadal zastanawiam się, dlaczego to nie działa, ale to już nie jest blokowanie. Dzięki za pomoc! –

Odpowiedz

0

Można spróbować przechodząc cały ciąg trasy „{id} - {title}” i analizowania ciąg ręcznie siebie, zanim dostanie się do działania, wykonując coś podobnego do Phil Haack na atrybut slug to id actionfilter - link

Mam nadzieję, że to pomoże.

+0

Przeczytałem ten wpis na blogu wcześniej, ale uważam, że to przesada, gdy mogę podzielić informacje o trasie. Ponieważ mój adres URL może zostać utworzony z trasy, ale nie rozwiązany jako trasa, myślę o jakimś błędzie w MVC. –

+0

Ach, dość fair. Będziemy się zastanawiać :-) – WestDiscGolf

0

Kilka znaków na trasie jest "specjalnych" i podzieli parametry takie jak - i /. Możliwe, że dodatkowe osoby na trasie powodują awarię. Wypróbuj "{id}-{*title}", ponieważ powoduje to, że tytuł zawiera wszystko, co następuje.

Aktualizacja

powyżej Odpowiedzią jest to, co się dzieje, gdy idziesz na StackOverflow przed miałeś wystarczająco dużo kawy.

Natknęliśmy się na ten sam problem dotyczący nazw plików dla plików przesłanych przez użytkowników, trasa zawierała znak "-" jako separator, ale może być również użyta w wartości w późniejszym parametrze, może wygenerować poprawny adres URL, ale nie będzie nie pasuje do tego. W końcu napisałem klasę SpecialFileRoute, aby poradzić sobie z tym problemem i zarejestrować tę trasę. Jest to trochę brzydkie, ale spełnia swoją rolę.

Zauważ, że trzymałem w starym stylu trasę MVC do generowania adresu URL, bawiłem się z tym, aby zrobić to poprawnie, ale jest to coś, do czego można wrócić później.

/// <summary> 
/// Special route to handle hyphens in the filename, a catchall parameter in the commented route caused exceptions 
/// </summary> 
public class SpecialFileRoute : RouteBase, IRouteWithArea 
{ 
    public string Controller { get; set; } 
    public string Action { get; set; } 
    public IRouteHandler RouteHandler = new MvcRouteHandler(); 
    public string Area { get; private set; } 

    //Doc/{doccode} - {CatNumber}.{version} - {*filename}, 

    public SpecialFileRoute(string area) 
    { 
     Area = area; 
    } 

    public override RouteData GetRouteData(HttpContextBase httpContext) 
    { 
     string url = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2); 
     var urlmatch = Regex.Match(url, @"doc/(\w*) - (\d*).(\d*) - (.*)", RegexOptions.IgnoreCase); 
     if (urlmatch.Success) 
     { 
      var routeData = new RouteData(this, this.RouteHandler); 

      routeData.Values.Add("doccode", urlmatch.Groups[1].Value); 
      routeData.Values.Add("CatNumber", urlmatch.Groups[2].Value); 
      routeData.Values.Add("version", urlmatch.Groups[3].Value); 
      routeData.Values.Add("filename", urlmatch.Groups[4].Value); 
      routeData.Values.Add("controller", this.Controller); 
      routeData.Values.Add("action", this.Action); 
      return routeData; 
     } 
     else 
      return null; 
    } 

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) 
    { 
     if (values.ContainsKey("controller") && (!string.Equals(Controller, values["controller"] as string, StringComparison.InvariantCultureIgnoreCase))) 
      return null; 
     if (values.ContainsKey("action") && (!string.Equals(Action, values["action"] as string, StringComparison.InvariantCultureIgnoreCase))) 
      return null; 
     if ((!values.ContainsKey("contentUrl")) || (!values.ContainsKey("format"))) 
      return null; 
     return new VirtualPathData(this, string.Format("{0}.{1}", values["contentUrl"], values["format"])); 
    } 
} 

Trasa w brzmieniu:

context.Routes.Add(new SpecialFileRoute(AreaName) { Controller = "Doc", Action = "Download" }); 

Jak wspomniano powyżej jest to trochę brzydki i kiedy mam czas jest dużo pracy chciałabym zrobić, aby poprawić ten wynik, ale to rozwiązał problem podziału adresu URL na potrzebne parametry. Jest dość silnie związany z konkretnymi wymaganiami tej jednej trasy ze wzorcem URL, Regex i Values, które są zakodowane na sztywno, ale powinny dać ci początek.

+0

Dzięki za informację, ale nie możemy użyć parametru catchall (*) w segmencie zawierającym więcej niż jedną sekcję. –

+0

D'oh, oczywiście. Natrafiłem na ten sam problem jakiś czas temu – Chao

Powiązane problemy