Çakışan iki eylem yöntemim var. Temel olarak, bir öğenin kimliği veya öğenin adı ve ebeveyninin (öğeler farklı ebeveynler arasında aynı ada sahip olabilir) iki farklı yolu kullanarak aynı görünüme ulaşmak istiyorum. Listeye filtre uygulamak için bir arama terimi kullanılabilir.
Örneğin...
Items/{action}/ParentName/ItemName
Items/{action}/1234-4321-1234-4321
İşte benim eylem yöntemleri ( Removeeylem yöntemleri de vardır ) ...
// Method #1
public ActionResult Assign(string parentName, string itemName) {
// Logic to retrieve item's ID here...
string itemId = ...;
return RedirectToAction("Assign", "Items", new { itemId });
}
// Method #2
public ActionResult Assign(string itemId, string searchTerm, int? page) { ... }
Ve işte yollar ...
routes.MapRoute("AssignRemove",
"Items/{action}/{itemId}",
new { controller = "Items" }
);
routes.MapRoute("AssignRemovePretty",
"Items/{action}/{parentName}/{itemName}",
new { controller = "Items" }
);
pageParametre boş olabileceğinden , hatanın neden oluştuğunu anlıyorum , ancak sorunu çözmek için en iyi yolu bulamıyorum. Tasarımım başlangıçta zayıf mı? Method #1Arama parametrelerini eklemek ve mantığı Method #2her ikisi de arayacakları özel bir yönteme taşımak için imzayı genişletmeyi düşündüm , ancak bunun belirsizliği çözeceğine inanmıyorum.
Herhangi bir yardım büyük mutluluk duyacağız.
Gerçek Çözüm (Levi'nin cevabına dayanarak)
Aşağıdaki sınıfı ekledim ...
public class RequireRouteValuesAttribute : ActionMethodSelectorAttribute {
public RequireRouteValuesAttribute(string[] valueNames) {
ValueNames = valueNames;
}
public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo) {
bool contains = false;
foreach (var value in ValueNames) {
contains = controllerContext.RequestContext.RouteData.Values.ContainsKey(value);
if (!contains) break;
}
return contains;
}
public string[] ValueNames { get; private set; }
}
Ve sonra eylem yöntemlerini dekore ettiniz ...
[RequireRouteValues(new[] { "parentName", "itemName" })]
public ActionResult Assign(string parentName, string itemName) { ... }
[RequireRouteValues(new[] { "itemId" })]
public ActionResult Assign(string itemId) { ... }
return ValueNames.All(v => controllerContext.RequestContext.RouteData.Values.ContainsKey(v));
contains = ...gibi bir şey için bölümü değiştirin :contains = controllerContext.RequestContext.RouteData.Values.ContainsKey(value) || controllerContext.RequestContext.HttpContext.Request.Params.AllKeys.Contains(value);
ActionResult DoSomething(Person p)nerede Personolduğu değişik basit gibi özellikler Nameve buna istekleri doğrudan özellik adları ile yapılır (örneğin /dosomething/?name=joe+someone&other=properties).
controllerContext.HttpContext.Request[value] != nullyerine controllerContext.RequestContext.RouteData.Values.ContainsKey(value); ama yine de güzel bir çalışma.