我有ASP.net Web Api项目,因此我决定该支持版本了。我正在使用官方的Microsoft Nuget支持版本控制(更多信息here),我决定按名称空间进行版本控制(例如here)。
不幸的是,我无法使代码正常工作。如果我这样调用我的方法:
http://localhost:7291/api/Saved/GetNumberOfSavedWorkoutsForUser?api-version=2.0
我得到错误:
Multiple types were found that match the controller named 'Saved'. This can happen if the route that services this request ('api/{controller}/{action}/{id}') found multiple controllers defined with the same name but differing namespaces, which is not supported.
如果我这样称呼它:
http://localhost:7291/v2/Saved/GetNumberOfSavedWorkoutsForUser
我收到错误404:
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
我不确定自己在做什么错。这是我的代码:
Startup.cs
public void Configuration(IAppBuilder app)
{
var configuration = new HttpConfiguration();
var httpServer = new HttpServer(configuration);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
// reporting api versions will return the headers "api-supported-versions" and "api-deprecated-versions"
configuration.AddApiVersioning(o =>
{
o.AssumeDefaultVersionWhenUnspecified = true;
o.ReportApiVersions = true;
o.DefaultApiVersion = ApiVersion.Default;
});
configuration.Routes.MapHttpRoute(
"VersionedUrl",
"v{apiVersion}/{controller}/{action}/{id}",
defaults: null,
constraints: new { apiVersion = new ApiVersionRouteConstraint() });
configuration.Routes.MapHttpRoute(
"VersionedQueryString",
"api/{controller}/{action}/{id}",
defaults: null);
app.UseWebApi(httpServer);
ConfigureAuth(app);
}
保存的控制器(v1)
namespace Master.Infrastructure.Api.Controllers
{
[Authorize]
[RoutePrefix("api/Saved")]
[ApiVersion("1.0")]
public class SavedController : ApiController
{
private readonly IUserService _userService;
public SavedController(IUserService userService)
{
_userService = userService;
}
[HttpGet]
[ActionName("GetNumberOfSavedWorkouts")]
public async Task<NumberOfSavedWorkouts> GetNumberOfSavedWorkouts()
{
var numOfSavedWorkouts = new NumberOfSavedWorkouts
{
CurrentNumberOfSavedWorkouts =
await _userService.GetNumberOfSavedWorkoutsForUserAsync(User.Identity.GetUserId())
};
return numOfSavedWorkouts;
}
}
}
保存的控制器(v2)
namespace Master.Infrastructure.Api.V2.Controllers
{
[Authorize]
[ApiVersion("2.0")]
[RoutePrefix("v{version:apiVersion}/Saved")]
public class SavedController : ApiController
{
private readonly ISavedWorkoutService _savedWorkoutService;
public SavedController(ISavedWorkoutService savedWorkoutService)
{
_savedWorkoutService = savedWorkoutService;
}
[ActionName("GetNumberOfSavedWorkoutsForUser")]
public async Task<IHttpActionResult> GetNumberOfSavedWorkoutsForUser()
{
var cnt = await _savedWorkoutService.CountNumberOfSavedWorkoutsForUser(User.Identity.GetUserId());
return Ok(cnt);
}
}
}
最佳答案
您的路线不正确。除非您确实需要,否则我强烈建议您不要混合使用路由样式。故障排除可能非常困难。
这里发生了几件事:
您具有通过查询字符串和URL段进行版本控制的配置,您想要哪一个?我只会选择一个。默认和我的建议是使用查询字符串方法。
基于约定的路由不同于基于属性的路由
由于定义了RoutePrefixAttribute,因此您似乎更喜欢属性路由样式。我将删除所有基于约定的路由(例如:configuration.Routes.MapHttpRoute
)。
按照惯例,路由模板:v{apiVersion}/{controller}/{action}/{id}
但在您的属性中是:api/Saved
这些都不符合您的预期路线:http://localhost:7291/api/Saved/GetNumberOfSavedWorkoutsForUser
http://localhost:7291/v2/Saved/GetNumberOfSavedWorkoutsForUser
对于使用路由属性的查询字符串方法,情况应如下所示:
configuration.AddApiVersioning(o => o.ReportApiVersions = true);
namespace Master.Infrastructure.Api.Controllers
{
[Authorize]
[ApiVersion("1.0")]
[RoutePrefix("api/Saved")]
public class SavedController : ApiController
{
private readonly IUserService _userService;
public SavedController(IUserService userService) => _userService = userService;
[HttpGet]
[Route("GetNumberOfSavedWorkouts")]
public async Task<IHttpActionResult> GetNumberOfSavedWorkouts()
{
var userId = User.Identity.GetUserId();
var count = await _userService.GetNumberOfSavedWorkoutsForUserAsync(userId);
return Ok(new NumberOfSavedWorkouts(){ CurrentNumberOfSavedWorkouts = count });
}
}
}
namespace Master.Infrastructure.Api.V2.Controllers
{
[Authorize]
[ApiVersion("2.0")]
[RoutePrefix("api/Saved")]
public class SavedController : ApiController
{
private readonly ISavedWorkoutService _savedWorkoutService;
public SavedController(ISavedWorkoutService savedWorkoutService) => _savedWorkoutService = savedWorkoutService;
[HttpGet]
[Route("GetNumberOfSavedWorkoutsForUser")]
public async Task<IHttpActionResult> GetNumberOfSavedWorkoutsForUser()
{
var userId = User.Identity.GetUserId();
var count = await _savedWorkoutService.CountNumberOfSavedWorkoutsForUser(userId);
return Ok(count);
}
}
}
然后,以下应该工作:
http://localhost:7291/api/Saved/GetNumberOfSavedWorkouts?api-version=1.0
http://localhost:7291/api/Saved/GetNumberOfSavedWorkoutsForUser?api-version=2.0
我希望能有所帮助
关于c# - ASP.net Web Api版本控制,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46177972/