ASP.NET WEB API의 요청 URI 오류와 일치하는 HTTP 리소스가 없습니다.
-
21-12-2019 - |
문제
이것은 TransferController 클래스의 스케치입니다.
이 모든 것은 웹 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'.
이것은 내 사용자 컨트롤러 클래스의 스케치입니다.
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) {...}
}
.
나에게 전혀없는 이유로 userController에서 아무 것도 호출하는 데 어려움이 없습니다. 파라미터는 정확히 동일한 방식으로 마샬링되고 동일 경로가 사용 중입니다.
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 객체가 아니며 httproutedata 객체입니다. 그러나 그것은 사소히 교정됩니다. httproute 객체는 httproutedata 객체의 속성으로 사용할 수 있습니다.
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"]);
}
.
및 턴으로 핸들러 속성이 있습니다. 그러나 NULL 핸들러가 단순히 (MSDN)
을 의미하기 때문에 이것은 덜 유익한 것보다 덜 유익합니다.null의 경우 기본 핸들러는 iHTTPController의 구현에 메시지를 전달합니다.
이제, 내 컨트롤러는 iHTTPController 인터페이스가 지정한 유일한 방법 인 ExecuteAsync 메서드를 확실히 구현하는 Apicontroller에서 파생됩니다. 내가 상상하는 것은 내가 그것에 대해 더 많이 알면 그 방법의 실행을 테스트 할 수 있음을 의미합니다.
해결책 2
OK 그 다음 ... 내 머리에 장치 테스트 아이디어를 넣어 주셔서 감사합니다.
다음은 낮은 다운 :
다른 동사에 동일한 매개 변수 서명을 가질 수 있습니다 (POST PUT DELETE 가져 오기).
는 동일한 동사의 다른 동작 이름에 동일한 매개 변수 서명을 가지고 있습니다.
하나 매개 변수 이름 만 다르므로
그래서 이것은 모두 다른 동사에있는 것이므로
[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;
}
}
.