阻止调用 Web API 方法
本文关键字:API 方法 Web 调用 | 更新日期: 2023-09-27 17:56:38
我正在使用 ASP.NET Web API创建一个Web API。 我目前正在我的端点上删除功能,以便我可以开始针对它进行开发。
我的 WebApiConfig.cs 文件如下所示:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "ActionAPI",
routeTemplate: "api/{controller}/{id}/{action}",
defaults: new { action = RouteParameter.Optional }
);
在我的用户控制器.cs文件中,我有以下方法:
//Maps to /Users endpoint
[HttpGet]
public IEnumerable<User> GetAllUsers()
{
//Code
}
//Maps to /Users/{id} endpoint
[HttpGet]
public User GetUser(int id)
{
//Code
}
//Maps to /Users/{id}/Enrollments endpoint
[HttpGet, ActionName("Enrollments")]
public IEnumerable<Enrollment> GetUserEnrollments(int id)
{
//Code
}
//Maps to /Users/{id}/Enrollments/{id}
[HttpGet, ActionName("Enrollments")]
public IEnumerable<Enrollment> GetUserEnrollment(int userid, int id)
{
//Code
}
如何防止/Users/GetUser
成为有效路由?
在GetUser(int id)
上使用[NonAction]
会阻止它完全工作。
编辑:这是/Users/GetUser
的当前输出
<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>
Multiple actions were found that match the request: Byui.ILearnAPI2.Business.Entities.User GetUser(Int32) on type Byui.ILearnAPI2.API.Controllers.UsersController System.Collections.Generic.IEnumerable`1[System.String] GetUserEnrollments(Int32) on type Byui.ILearnAPI2.API.Controllers.UsersController
</ExceptionMessage>
<ExceptionType>System.InvalidOperationException</ExceptionType>
<StackTrace>
at System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.SelectAction(HttpControllerContext controllerContext) at System.Web.Http.Controllers.ApiControllerActionSelector.SelectAction(HttpControllerContext controllerContext) at System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken) at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncInternal(HttpRequestMessage request, CancellationToken cancellationToken) at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
</StackTrace>
</Error>
再次查看您的帖子后,我认为您没有正确查看错误。
由于您配置控制器的方式,存在不明确的路由。
找到与请求匹配的多个操作:
GetUser(Int32) on type Byui.ILearnAPI2.API.Controllers.UsersController
GetUserEnrollments(Int32) on type Byui.ILearnAPI2.API.Controllers.UsersController
GetUser和 GetUserEnrollments 共享相同的路由。据我所知,如果您向 GetUser 传递 int 或字符串或其他任何东西,它将无法工作,因为它不知道如何正确解析。
您可以在默认值之前添加路由配置以解决此问题。
config.Routes.MapHttpRoute(
name: "GetUsers",
routeTemplate: "api/users/{id}",
defaults: new { controller = "Users", action = "GetUser" }
);
试试这个。
- 注释掉
GetUserEnrollments(int id)
- 致电
/Users/GetUser
- 你会得到
请求无效。 参数字典包含参数 'id' 的空条目 方法"so14610664"的不可为空类型"System.Int32"。模型.用户 GetUser(Int32)' 在 'so14610664.控制器.用户控制器'.一个可选的 参数必须是引用类型、可为 null 的类型或声明为 可选参数。
- 现在致电
/User/abcdefg
- 您会收到与上述相同的消息。"The request is invalid..."
看,不是GetUser
暴露了,而是它试图将/Users/
之后的任何东西映射到id
并失败,因为GetUser
和"abcdefg"
在值Int32
无效;换句话说:它认为你忘记了id
。
尝试使用属性路由包。 这是一个位于 MVC 路由(App_Start/RouteConfig
中的路由)和/或 Web API 路由(您正在执行的操作 - App_Start/WebApiConfig
中的路由)之上的包
使用该包,可以将 App_Start
中的路由映射替换为代码示例中的类似映射:
//Maps to /Users endpoint
[HttpGet, GET("/Users")]
public IEnumerable<User> GetAllUsers()
{
//Code
}
//Maps to /Users/{id} endpoint
[HttpGet, GET("/Users/{id)"]
public User GetUser(int id)
{
//Code
}
//Maps to /Users/{id}/Enrollments endpoint
[HttpGet, GET("/Users/{id}/Enrollments")]
public IEnumerable<Enrollment> GetUserEnrollments(int id)
{
//Code
}
//Maps to /Users/{userid}/Enrollments/{id}
[HttpGet, GET("/Users/{userid}/Enrollments/{id}")]
public IEnumerable<Enrollment> GetUserEnrollment(int userid, int id)
{
//Code
}
您可以使用 IHttpRouteConstraint 来验证 {id} 是否为整数,并在路由中指定路由约束。
可以在此处找到示例。
GetUsers
返回 404,这是处理它的 Restful 方法。
您可以执行类似操作来验证提供的 id。如果未找到 Id,则可以返回包含所需代码的自定义响应消息。
[HttpGet]
public User GetUser(int id)
{
if (id > 0 && validIds.Contains(id))
{
//Go do something fun...
}
else
throw new HttpResponseException(
new HttpResponseMessage(HttpStatusCode.NotFound)
{
ReasonPhrase = String.Format("A valid id is required. {0} is most definitely not a valid id.", id);
}
);
}