Ни один HTTP Resource не был найден, что соответствует ошибке URI запроса в ASP.NET Web API

StackOverflow https://stackoverflow.com//questions/23013509

Вопрос

Это эскиз моего класса TransfernController.

Все это код веб-API.

public class TransferController : ApiController
{
  [HttpGet, ActionName("Queue")]
  public IEnumerable<object> GetQueue(Guid sessionId) {...}

  [HttpDelete, ActionName("Delete")]
  public void Delete(Guid sessionId, Guid fileId) {...}

  [HttpGet, ActionName("Cancel")]
  public bool Cancel(Guid sessionId, Guid fileId) {...}

  [HttpGet, ActionName("UploadedBytes")]
  public long GetUploadedByteCount(Guid sessionId, Guid fileId) {...}

  [HttpGet, ActionName("DownloadUrl")]
  public string GetDownloadUrl(string fileId) {...}

  [HttpPost, ActionName("FileChunk")] 
  public void PostFileChunk([FromUri]Guid sessionId, [FromUri]Guid fileId) {...}

  [HttpPost, ActionName("UploadDefinition")]
  public Guid PostUploadItem([FromBody]UploadDefinition uploadDef) {...}

}
.

Это маршрутизация.

public static void Register(HttpConfiguration config)
{
  config.Routes.MapHttpRoute(
    name: "DefaultApi", 
    routeTemplate: "api/{controller}/{action}"
    );
  config.Routes.MapHttpRoute(
    name: "DefaultApiDefaultMethod", 
    routeTemplate: "api/{controller}"
    );
}
.

Это вызов.

$.ajax({
  url: "api/Transfer/Queue",
  data: { sessiondId: login.SessionId() }    
})
.done(function (result) {
  history.push(new UploadItem());
  for (var i = 0; i < result.length; i++) {
    var ui = new UploadItem(result[i]);
    history.push(ui);
  }
})
.fail(function (result) {
  app.showMessage(JSON.parse(result.responseText).Message);
});
.

и это результат.

No HTTP resource was found that matches the request URI 'http://localhost:54770/api/Transfer/Queue?sessiondId=0e2c47b9-e674-446d-a06c-ce16932f9580'.

Это эскиз моего укрепляющего класса USERCONTROLLER.

public class UserController : ApiController 

  [HttpGet, ActionName("Authenticate")]
  public object Authenticate(string email, string password) {...}

  [HttpPost]
  public void Register([FromBody]UserDefinition userDef) {...}

  [HttpGet, ActionName("Pulse")]
  public bool Pulse(Guid sessionId) {...}

}
.

по причинам, не связанным со мной, у меня нет проблем, ничего не призывающих в целостке. Параметры маршаллированы точно так же, и используются маршруты .


Darrel Miller ниже использует тестирование блока для проверки маршрутов. Честно говоря, я пинаю себя за то, что не думаете об этом, и теперь я сделал то же самое.

Но тесты, поскольку он показывает, что они действительно тестируют только разбор URL. Например, этот тест проходит

public void TestMvc4RouteWibble()
{
  var config = new HttpConfiguration();
  config.Routes.MapHttpRoute(
      name: "DefaultApi",
      routeTemplate: "api/{controller}/{action}/{id}",
      defaults: new { id = RouteParameter.Optional }
      );


  var route =
      config.Routes.GetRouteData(new HttpRequestMessage()
      {
        RequestUri = new Uri("http://localhost:54770/api/Transfer/Wibble?sessionId=0e2c47b9-e674-446d-a06c-ce16932f9580&fileId=0e2c47b9-e674-446d-a06c-ce16932f9581")  //?
      });

  Assert.IsNotNull(route);
  Assert.AreEqual("Transfer", route.Values["controller"]);
  Assert.AreEqual("Wibble", route.Values["action"]);

}
.

Несмотря на заметное отсутствие метода, смутителя на контроллере передачи.

Также объект маршрута на самом деле не является объектом HTTPROUTE, это объект HTTPROTEDATA. Но это тривиально исправлено. Объект HTTPROUTE доступен в качестве свойства объекта HTTPROTEDATA.

public void TestMvc4RouteWibble()
{
  var config = new HttpConfiguration();
  config.Routes.MapHttpRoute(
      name: "DefaultApi",
      routeTemplate: "api/{controller}/{action}/{id}",
      defaults: new { id = RouteParameter.Optional }
      );


  var routeData =
      config.Routes.GetRouteData(new HttpRequestMessage()
      {
        RequestUri = new Uri("http://localhost:54770/api/Transfer/Wibble?sessionId=0e2c47b9-e674-446d-a06c-ce16932f9580&fileId=0e2c47b9-e674-446d-a06c-ce16932f9581")  //?
      });

  Assert.IsNotNull(routeData);
  Assert.AreEqual("Transfer", routeData.Values["controller"]);
  Assert.AreEqual("Wibble", routeData.Values["action"]);

}
.

И это в свою очередь имеет свойство обработчика. Однако это менее информативно, чем может быть, поскольку нулевой обработчик просто означает (от MSDN)

Если нуль, обработчик по умолчанию отправляет сообщения для реализаций IHTTPController.

Теперь мой контроллер получают из Apicontroller, который, безусловно, реализует метод ExecuteAsync, который является единственным, указанным интерфейсом IHTTPController. Что я представляю, значит, я мог бы проверить выполнение этого метода, если я знал больше об этом.

Это было полезно?

Решение 2

Хорошо, тогда ... спасибо за то, что выступил идею тестирования подразделения в моей голове, он сильно поправился.

Вот низкое расстояние:

Вы можете иметь одинаковые параметры подписи на разных глаголах (Получить поставку Удалить).

Вы не могут иметь идентичные подписи параметров на разных именах действия на одном глаголе.

Вам нужно только варьироваться одно имя параметра .

Так что это нормально, потому что они все на разных глаголах

[HttpDelete, ActionName("Delete")]
public void Delete(Guid sessionId, Guid fileId) {...}

[HttpGet, ActionName("Cancel")]
public bool Cancel(Guid sessionId, Guid fileId) {...}

[HttpPost, ActionName("FileChunk")] 
public void PostFileChunk(Guid sessionId, Guid fileId) {...}
.

Но это не круто, потому что они оба получают

[HttpGet, ActionName("UploadedBytes")]
public long GetUploadedByteCount(Guid sessionId, Guid fileId) {...}

[HttpGet, ActionName("Cancel")]
public bool Cancel(Guid sessionId, Guid fileId) {...}
.

, и вы можете исправить это как это

[HttpGet, ActionName("UploadedBytes")]
public long GetUploadedByteCount(Guid sessionId, Guid uploadBytesFileId) {...}

[HttpGet, ActionName("Cancel")]
public bool Cancel(Guid sessionId, Guid cancelFileId) {...}
.

Может быть, я жесткая задница, но насколько я понимаю, это не маршрутизация, пока метод не будет вызван.

Другие советы

Вот тест, который демонстрирует маршрутизацию, работает хорошо,

[Fact]
public void TestRoute() 
{
    var config = new HttpConfiguration();
    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{action}"
        );


    var route =
        config.Routes.GetRouteData(new HttpRequestMessage()
        {
            RequestUri = new Uri("http://localhost:54770/api/Transfer/Queue?sessionId=0e2c47b9-e674-446d-a06c-ce16932f9580")  //?
        });

    Assert.NotNull(route);
    Assert.Equal("Transfer",route.Values["controller"]);
    Assert.Equal("Queue",route.Values["action"]);

}
.

А вот тест, показывающий выделение диспетчера / действия, также работает,

[Fact]
public void TestDispatch()
{
    var config = new HttpConfiguration();
    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{action}"
        );

    var server = new HttpServer(config);

    var client = new HttpClient(server);
    var response =
        client.GetAsync(new Uri("http://localhost:54770/api/Transfer/Queue?sessionId=0e2c47b9-e674-446d-a06c-ce16932f9580")) // 
            .Result;

    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}


public class TransferController : ApiController
{
   [HttpGet]
   [ActionName("Queue")]
   public IEnumerable<object> Queue(Guid sessionId) 
   {
       return null;
   }

}
.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top