ASP.NET MVC Url.Akcja dodaje bieżące wartości trasy do wygenerowanego adresu url
Widziałem to pytanie kilka razy tutaj w SO, ale żadne z nich nie ma żadnej akceptowalnej odpowiedzi:
ASP.NET MVC @ Url.Akcja zawiera aktualne dane o trasie
ASP.NET MVC domyślnie dodaje wartości trasy
W zasadzie mam kontroler z metodą akcji o nazwie Group, ma przeciążenie, które nie odbiera żadnych parametrów i wyświetla listę elementów oraz inny, który otrzymuje id i wyświetla szczegóły dla tej grupy.
Jeśli Robię coś takiego:
Url.Action("Group", "Groups");
Ze strony głównej witryny ( / ) zwraca adres url w następujący sposób:
"mysite.com/Groups/Group"
Co jest w porządku Teraz, jeśli aktualny adres strony to / Groups / Group/1 And I call the same method
Url.Action("Group", "Groups");
Zwracany adres url jest następujący:
"mysite.com/Groups/Group/1"
Automatycznie dodaje wartość trasy dla bieżącej strony podczas generowania adresu URL. Nawet jeśli wygeneruję adres URL w ten sposób:
Url.Action("Group", "Groups", null);
W ten sposób wyraźnie określając, że nie chcę żadnej trasy wartości, wygenerowany adres URL jest taki sam. Aby uzyskać żądany adres, muszę jawnie ustawić wartość trasy na pusty łańcuch, tak:
Url.Action("Group", "Groups", new {id=""});
To wygeneruje następujący adres url:
"mysite.com/Groups/Group"
Moje pytanie brzmi, dlaczego tak się dzieje? Jeśli nie ustawiam żadnych wartości trasy, nie powinno się dodawać ich do wygenerowanego adresu URL. 7 answers
Url.Action użyje ponownie bieżących parametrów żądania, jeśli nie zostaną one jawnie ustawione. Jest to algorytm dopasowujący adres URL wychodzący. Podczas wyszukiwania parametrów danych trasy w procesie generowania adresu url, parametry są pobierane z:
1) jawnie podane wartości
2) wartości z bieżącego żądania
3) defaults
W kolejności podanej powyżej.
Algorytm dopasowania wychodzącego dla tras jest skomplikowany, więc dobrą praktyką jest jawnie ustaw wszystkie parametry dla request, tak jak w przykładzie
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-20 17:20:15
Moja aplikacja jawnie ustawia wartości trasy i nie chce magicznej wartości z bieżącego żądania. Chcę mieć pełną kontrolę.
Zrobiłem rozszerzenie, które współgra z moją kolekcją route library. stąd pojedynczy param. (Zobacz komentarz mojej biblioteki tras na dole)
Tutaj usuwam wszelkie routevalues z żądania przed wygenerowaniem adresu url.
(uwaga: dla tablicy.zawiera część ignorecase, patrz: Jak mogę zrobić / Align = "left" / Zawiera wielkość liter w tablicy łańcuchów?)
public static string Action(this UrlHelper helper,
RouteValueDictionary routeValues)
{
RemoveRoutes(helper.RequestContext.RouteData.Values);
string url = helper.Action(routeValues["Action"].ToString(), routeValues);
return url;
}
public static void RemoveRoutes(RouteValueDictionary currentRouteData)
{
List<string> keyList = new List<string>(currentRouteData.Keys);
string[] ignore = new[] { "Area", "Controller", "Action" };
foreach (string key in keyList)
{
if (!ignore.Contains(key, StringComparer.CurrentCultureIgnoreCase))
currentRouteData.Remove(key);
}
}
Mam metody rozszerzenia Form i ActionLink, które używają metody RemoveRoutes. Żaden helper w mojej bibliotece mvc nie używa metody, która nie jest stworzoną przeze mnie metodą rozszerzenia. W ten sposób wszystkie routedata są czyszczone przed wygenerowaniem adresów URL.
w celach informacyjnych używam AttributeRouting. Oto przykład jednej trasy z mojej biblioteki tras.
public static RouteValueDictionary DisplayNews(int newsId)
{
RouteValueDictionary route = new RouteValueDictionary();
route["Area"] = _area;
route["Controller"] = _controller;
route["Action"] = "DisplayNews";
route["newsId"] = newsId;
return route;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:37
Kiedy przeczytałem odpowiedź objectbox, pomyślałem, że będę musiał zmodyfikować kilka linków w moim kodzie. Następnie próbowałem dodać domyślną trasę pomijając domyślne parametry, które rozwiązały problem:
routes.MapRoute(
"ArtistArtworkDefPage",
"Artist/{username}/Artwork",
new
{
controller = "Artist",
action = "Artwork",
page = 1
}
);
routes.MapRoute(
"ArtistArtwork",
"Artist/{username}/Artwork/{page}",
new
{
controller = "Artist",
action = "Artwork",
page = 1
},
new { page = @"\d+" }
);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-28 14:24:30
Prosty przykład:
public class ProductController : Controller
{
public ActionResult Edit(int id)
{
return View();
}
[Route("Product/Detail/{id:int}")]
public ActionResult Detail(int id)
{
return View();
}
}
Widok edycji zawiera tylko to:
@{ Layout = null;}
@Url.Action("Detail", "Cmr")
Więc po uruchomieniu strony np. localhost:randomPort/Product/Edit/123
otrzymujesz następną odpowiedź: /Product/Detail/123
Route
atrybut posiada wymagany parametr id
. Parametr Id jest odczytywany z adresu url, chociaż napisaliśmy tylko Url.Action(methodName, controller)
- bez podania parametru. Również nie ma sensu mieć szczegóły metody bez id.
Aby atrybuty działały, należy dodać do RouteConfig.cs
następny wiersz:
public static void RegisterRoutes(RouteCollection routes)
{
...
routes.MapMvcAttributeRoutes();
...
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-10 10:27:42
Głupie obejście znalazłem, że działa do obsługi bieżącej strony routingu danych, w tym zmiana parametru strony według preferencji
@{
var current_route_1 = new RouteValueDictionary(Url.RequestContext.RouteData.Values);
var current_route_2 = new RouteValueDictionary(Url.RequestContext.RouteData.Values);
//If you want to customize the routing values
current_route_1["controller"] = "Controller1";
current_route_2["controller"] = "Controller2";
}
@Url.RouteUrl(current_route_1);
@Url.RouteUrl(current_route_2);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-28 07:23:22
Oto obejście, które nie wymaga trasowania atrybutów ani nie zmienia bieżących wartości trasy w żądaniu. Ten pomysł pochodzi z http://notherdev.blogspot.ca/2013/10/aspnet-mvc-current-values-used-by-url-action.html , który zmieniłem nieco, aby działał bez MvcFutures.
Zbudowałem własne rozszerzenie Action
Na UrlHelper z dodatkowym boolem, który pozwala opcjonalnie ignorować bieżące wartości trasy (aby nie kolidować z istniejącymi metodami akcji na UrlHelper.)
To, co robi, to buduje zupełnie nowy RequestContext z bieżącego, używając bieżącej trasy, ale nie bieżące wartości trasy. Potem przekażemy to pomocnikom bazy. W ten sposób, gdy podstawowe helpery przejdą do sprawdzenia, jakie są wartości trasy z kontekstu żądania, nie znajdą żadnych, a tym samym nie użyją ich podczas generowania adresu URL.
public static string Action(this UrlHelper urlHelper, string actionName, string controllerName, object routeValues, bool ignoreCurrentRouteValues=false) {
var routeValueDictionary = new RouteValueDictionary(routeValues);
var requestContext = urlHelper.RequestContext;
if (ignoreCurrentRouteValues) {
var currentRouteData = requestContext.RouteData;
var newRouteData = new RouteData(currentRouteData.Route, currentRouteData.RouteHandler);
requestContext = new RequestContext(requestContext.HttpContext, newRouteData);
}
return UrlHelper.GenerateUrl(null, actionName, controllerName, routeValueDictionary,
urlHelper.RouteCollection, requestContext, includeImplicitMvcValues: false);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-01 18:04:48
Proste obejście będzie pierwszym wywołaniem
Url.Action("dummy", new { ... })
A następnie zmień nazwę dummy w wynikowym łańcuchu na poprawną nazwę akcji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-18 08:54:02