我有一个特定的Controller / Repository的两个GET方法:
public IEnumerable<InventoryItem> GetAllInventoryItems()
{
return inventoryItemsRepository.GetAll();
}
[Route("api/{controller}/{ID}/{CountToFetch}")]
public IEnumerable<InventoryItem> GetBatchOfInventoryItemsByStartingID(string ID, int CountToFetch)
{
return inventoryItemsRepository.Get(ID, CountToFetch);
}
即使我尝试从客户端调用所有这些方法,但有两个参数:
0)
formatargready_uri = string.Format("http://localhost:28642/api/inventoryItems/{0}/{1}", lastIDFetched, RECORDS_TO_FETCH);
var webRequest = (HttpWebRequest)WebRequest.Create(formatargready_uri);
1)
formatargready_uri = string.Format("http://localhost:28642/api/inventoryItems/?ID={0}&CountToFetch={1}", lastIDFetched, RECORDS_TO_FETCH);
var webRequest = (HttpWebRequest)WebRequest.Create(formatargready_uri);
2)
formatargready_uri = string.Format("http://localhost:28642/api/inventoryItems/ID={0}&CountToFetch={1}", lastIDFetched, RECORDS_TO_FETCH);
var webRequest = (HttpWebRequest)WebRequest.Create(formatargready_uri);
...在每种情况下,它仍然是被调用的第一个方法(GetAll)。为什么呢?
这是我的存储库代码:
public IEnumerable<InventoryItem> GetAll()
{
return inventoryItems;
}
public IEnumerable<InventoryItem> Get(string ID, int CountToFetch)
{
return inventoryItems.Where(i => 0 < String.Compare(i.Id, ID)).Take(CountToFetch);
}
......这就是WebApiConfig.cs中的内容:
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApiWithParameters",
routeTemplate: "api/{controller}/{ID}/{CountToFetch}",
defaults: new { ID = RouteParameter.Optional, CountToFetch = RouteParameter.Optional }
);
}
这将显示我尝试将调用路由到我尝试运行的Controller方法:
//[HttpGet]
//[Route("api/{controller}/{ID:string}/{CountToFetch:int}")] <-- throws exception - won't run
//[Route("{controller}/{ID:string}/{CountToFetch:int}")] <-- throws exception - won't run
//[Route("inventoryItems/{ID:string}/{CountToFetch:int}")] <-- throws exception - won't run
//[Route("api/inventoryItems/{ID:string}/{CountToFetch:int}")] <-- throws exception - won't run
//[Route("api/{controller}/{ID}/{CountToFetch}")] // <-- runs, but is not called
[Route("api/InventoryItemsController/{ID}/{CountToFetch}")] // <-- runs, but is not called
//[Route("api/{controller}/{ID:string}/{CountToFetch:int}")] <-- throws exception - won't run
所以我不想要被调用的方法非常强大:无论我如何装饰其他方法,或者我如何调用它,不受欢迎的方法都会运行。
仅仅允许按名称调用Controller方法会不会更容易?例如,给定此控制器方法:
public IEnumerable<InventoryItem> GetBatchOfInventoryItemsByStartingID(string ID, int CountToFetch)
{
return inventoryItemsRepository.Get(ID, CountToFetch); //.Where(i => string.Equals(p.Category, category, StringComparison.OrdinalIgnoreCase));
}
...为什么[c,w]不能像这样从客户端调用:
formatargready_uri = string.Format("http://localhost:28642/api/InventoryItemsController.GetBatchOfInventoryItemsByStartingID/{0}/{1}", lastIDFetched, RECORDS_TO_FETCH);
???
ISTM会更加直观。
所以归结为:为什么我的GetAll()方法被调用,什么时候没有args?
由于lastIDFetched设置为空字符串,路由机制可能会变得混乱:
string lastIDFetched = string.Empty;
...然后是formatargready_uri。以这种方式分配:
formatargready_uri = string.Format("http://locohost:28642/api/InventoryItems/{0}/{1}", lastIDFetched, RECORDS_TO_FETCH);
......起初是:
"http://locohost:28642/api/InventoryItems//100"
(当我希望它是:
"http://locohost:28642/api/InventoryItems/""/100"
)
可能是“丢失”的第一个arg是关闭路由机制的,所以当它看到时:
"http://locohost:28642/api/InventoryItems//100"
......它不知道是否要这样称呼:
public IEnumerable<InventoryItem> GetBatchOfInventoryItemsByStartingID(string ID, int CountToFetch)
{
return inventoryItemsRepository.Get(ID, CountToFetch); //.Where(i => string.Equals(p.Category, category,
StringComparison.OrdinalIgnoreCase)); }
......或者这个:
public IEnumerable<InventoryItem> GetAllInventoryItems()
{
return inventoryItemsRepository.GetAll();
}
???
当我注释掉另一个方法时,客户端别无选择,只能看到Controller / Repository中唯一的现有方法,它在这一行上什么都不做:
var webRequest = (HttpWebRequest)WebRequest.Create(formatargready_uri);
(Controller中的两个arg方法仍未调用)
这就是Controller现在的所有内容:
public class InventoryItemsController : ApiController
{
static readonly IInventoryItemRepository inventoryItemsRepository = new InventoryItemRepository();
[Route("api/InventoryItems/{ID}/{CountToFetch:int}")] // <-- with this route decoration commented out or not, makes no difference
public IEnumerable<InventoryItem> GetBatchOfInventoryItemsByStartingID(string ID, int CountToFetch)
{
return inventoryItemsRepository.Get(ID, CountToFetch); //.Where(i => string.Equals(p.Category, category, StringComparison.OrdinalIgnoreCase));
}
}
这是相应的Repository接口:
interface IInventoryItemRepository
{
IEnumerable<InventoryItem> Get(string ID, int CountToFetch);
InventoryItem Add(InventoryItem item);
}
......存储库实现:
public class InventoryItemRepository : IInventoryItemRepository
{
private readonly List<InventoryItem> inventoryItems = new List<InventoryItem>();
public InventoryItemRepository()
{
// code that populates inventoryItems by calling Add() not shown - it works, though
}
public IEnumerable<InventoryItem> Get(string ID, int CountToFetch)
{
return inventoryItems.Where(i => 0 < String.Compare(i.Id, ID)).Take(CountToFetch);
}
public InventoryItem Add(InventoryItem item)
{
if (item == null)
{
throw new ArgumentNullException("item");
}
inventoryItems.Add(item);
return item;
}
}
...以及调用它的客户端代码:
formatargready_uri = string.Format("http://localhost:28642/api/InventoryItems/{0}/{1}", lastIDFetched, RECORDS_TO_FETCH);
var webRequest = (HttpWebRequest)WebRequest.Create(formatargready_uri);
答案 0 :(得分:1)
首先,为什么在以下属性路由中有{controller}
?通过在此处使用属性路由进行装饰,您已经指示了应该命中的控制器和操作,因此请在此处删除{controller}
并将其替换为控制器名称。
[Route("api/{controller}/{ID}/{CountToFetch}")]
public IEnumerable<InventoryItem> GetBatchOfInventoryItemsByStartingID(string ID, int CountToFetch)
{
return inventoryItemsRepository.Get(ID, CountToFetch);
}
请求1)和2)使用查询字符串的地方不起作用,因为ID和CountToFetch是必需的路由参数。