Ç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 ( Remove
eylem 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" }
);
page
Parametre 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 #1
Arama parametrelerini eklemek ve mantığı Method #2
her 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 Person
olduğu değişik basit gibi özellikler Name
ve buna istekleri doğrudan özellik adları ile yapılır (örneğin /dosomething/?name=joe+someone&other=properties
).
controllerContext.HttpContext.Request[value] != null
yerine controllerContext.RequestContext.RouteData.Values.ContainsKey(value)
; ama yine de güzel bir çalışma.