ASP.NET Web API中的自定义方法名称

我正在从WCF Web API转换到新的ASP.NET MVC 4 Web API。 我有一个UsersController,我想有一个名为Authenticate的方法。 我看到如何执行GetAll,GetOne,Post和Delete的例子,但是如果我想向这些服务中添加额外的方法呢? 例如,我的UsersService应该有一个名为Authenticate的方法,在那里它们传递一个用户名和密码,但是它不起作用。

public class UsersController : BaseApiController { public string GetAll() { return "getall!"; } public string Get(int id) { return "get 1! " + id; } public User GetAuthenticate(string userName, string password, string applicationName) { LogWriter.Write(String.Format("Received authenticate request for username {0} and password {1} and application {2}", userName, password, applicationName)); //check if valid leapfrog login. var decodedUsername = userName.Replace("%40", "@"); var encodedPassword = password.Length > 0 ? Utility.HashString(password) : String.Empty; var leapFrogUsers = LeapFrogUserData.FindAll(decodedUsername, encodedPassword); if (leapFrogUsers.Count > 0) { return new User { Id = (uint)leapFrogUsers[0].Id, Guid = leapFrogUsers[0].Guid }; } else throw new HttpResponseException("Invalid login credentials"); } } 

我可以浏览到myapi / api / users /,它会调用GetAll,我可以浏览到myapi / api / users / 1,它会调用Get,但是如果我调用myapi / api / users / authenticate?username = {0} &password = {1}然后它会调用Get(NOT Authenticate)和错误:

参数字典包含“Navtrak.Services.WCF.NavtrakAPI.Controllers.UsersController”中方法“System.String Get(Int32)”的非空types“System.Int32”的参数“id”的空条目。 可选参数必须是引用types,可为空types,或者声明为可选参数。

我怎样才能调用自定义的方法名称,如身份validation?

默认情况下,路由configuration遵循RESTFul约定,这意味着它将只接受Get,Post,Put和Delete操作名称(查看global.asax =>中的路由,默认情况下它不允许指定任何操作name =>它使用HTTP动词来分派)。 所以当你发送一个GET请求到/api/users/authenticate你基本上是调用Get(int id)动作并传递id=authenticate ,因为你的Get动作需要一个整数。

如果你想有不同于标准动作名称的动作名称,你可以在global.asax修改你的路由定义:

 Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { action = "get", id = RouteParameter.Optional } ); 

现在您可以导航到/api/values/getauthenticate来authentication用户。

这是迄今为止我想出来的最好的方法,以便在支持正常的REST方法的同时结合额外的GET方法。 将以下路由添加到您的WebApiConfig中:

 routes.MapHttpRoute("DefaultApiWithId", "Api/{controller}/{id}", new { id = RouteParameter.Optional }, new { id = @"\d+" }); routes.MapHttpRoute("DefaultApiWithAction", "Api/{controller}/{action}"); routes.MapHttpRoute("DefaultApiGet", "Api/{controller}", new { action = "Get" }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Get) }); routes.MapHttpRoute("DefaultApiPost", "Api/{controller}", new {action = "Post"}, new {httpMethod = new HttpMethodConstraint(HttpMethod.Post)}); 

我用下面的testing类validation了这个解决scheme。 我能够成功地击中我的控制器中的每个方法:

 public class TestController : ApiController { public string Get() { return string.Empty; } public string Get(int id) { return string.Empty; } public string GetAll() { return string.Empty; } public void Post([FromBody]string value) { } public void Put(int id, [FromBody]string value) { } public void Delete(int id) { } } 

我证实它支持以下请求:

 GET /Test GET /Test/1 GET /Test/GetAll POST /Test PUT /Test/1 DELETE /Test/1 

请注意 ,如果额外的GET操作不以“Get”开头,则可能需要为该方法添加HttpGet属性。

我是进入MVC4世界的日子。

对于它的价值,我有一个SitesAPIController,我需要一个自定义的方法,可以这样调用:

 http://localhost:9000/api/SitesAPI/Disposition/0 

用最后一个参数的不同值来获得不同configuration的logging。

最后为我工作的是:

SitesAPIController中的方法:

 // GET api/SitesAPI/Disposition/1 [ActionName("Disposition")] [HttpGet] public Site Disposition(int disposition) { Site site = db.Sites.Where(s => s.Disposition == disposition).First(); return site; } 

而这个在WebApiConfig.cs中

 // this was already there config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); // this i added config.Routes.MapHttpRoute( name: "Action", routeTemplate: "api/{controller}/{action}/{disposition}" ); 

只要我把{处置}命名为{id},我遇到了:

 { "Message": "No HTTP resource was found that matches the request URI 'http://localhost:9000/api/SitesAPI/Disposition/0'.", "MessageDetail": "No action was found on the controller 'SitesAPI' that matches the request." } 

当我将它重命名为{disposition}时,它开始工作。 显然,参数名称与占位符中的值匹配。

随意编辑这个答案,使其更加准确/解释。

Web Api在默认情况下期望以api / {controller} / {id}forms的URL覆盖此默认路由。 您可以使用以下两种方式中的任何一种设置路由。

第一个选项:

在WebApiConfig.cs中添加下面的路由注册

 config.Routes.MapHttpRoute( name: "CustomApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); 

用HttpGet和参数如下装饰你的动作方法

 [HttpGet] public HttpResponseMessage ReadMyData(string param1, string param2, string param3) { // your code here } 

以上调用方法url将如下所示

HTTP://本地主机:[yourport] / API /迈德特/ ReadMyData参数1 =值1&参数2 =值2&参数3 =值3

第二个选项将路由前缀添加到Controller类,并使用HttpGet装饰您的操作方法,如下所示。 在这种情况下,不需要改变任何WebApiConfig.cs。 它可以有默认路由。

 [RoutePrefix("api/{controller}/{action}")] public class MyDataController : ApiController { [HttpGet] public HttpResponseMessage ReadMyData(string param1, string param2, string param3) { // your code here } } 

以上调用方法url将如下所示

HTTP://本地主机:[yourport] / API /迈德特/ ReadMyData参数1 =值1&参数2 =值2&参数3 =值3

请参阅本文以获取有关命名操作的更多讨论。 它还表明,您可以使用[HttpGet]属性,而不是用“get”前缀操作名称。

http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api

如果您在ASP.NET MVC 6中使用ASP.NET 5 ,那么大多数答案根本无法工作,因为您通常会让MVC为您创build适当的路由集合(使用默认的RESTful约定),这意味着你不会find任何Routes.MapRoute()调用来Routes.MapRoute()编辑。

Startup.cs文件调用的ConfigureServices()方法将MVC与内置于ASP.NET 5中的dependency injection框架一起注册:这样,当稍后在该类中调用ApplicationBuilder.UseMvc() ,MVC框架将自动添加这些默认路由到您的应用程序。 通过查看框架源代码中的UseMvc()方法实现,我们可以看看引擎背后发生了什么:

 public static IApplicationBuilder UseMvc( [NotNull] this IApplicationBuilder app, [NotNull] Action<IRouteBuilder> configureRoutes) { // Verify if AddMvc was done before calling UseMvc // We use the MvcMarkerService to make sure if all the services were added. MvcServicesHelper.ThrowIfMvcNotRegistered(app.ApplicationServices); var routes = new RouteBuilder { DefaultHandler = new MvcRouteHandler(), ServiceProvider = app.ApplicationServices }; configureRoutes(routes); // Adding the attribute route comes after running the user-code because // we want to respect any changes to the DefaultHandler. routes.Routes.Insert(0, AttributeRouting.CreateAttributeMegaRoute( routes.DefaultHandler, app.ApplicationServices)); return app.UseRouter(routes.Build()); } 

关于这一点的好处是,框架现在处理所有的艰苦工作,迭代所有Controller的Actions并设置它们的默认路由,从而为您节省一些重复的工作。

坏事是,关于如何添加自己的路线,很less或没有文件。 幸运的是,您可以通过使用基于约定和/或基于属性的方法(又名属性路由 )轻松完成此操作。

公约为基础

在您的Startup.cs类中,将其replace为:

 app.UseMvc(); 

有了这个:

 app.UseMvc(routes => { // Route Sample A routes.MapRoute( name: "RouteSampleA", template: "MyOwnGet", defaults: new { controller = "Items", action = "Get" } ); // Route Sample B routes.MapRoute( name: "RouteSampleB", template: "MyOwnPost", defaults: new { controller = "Items", action = "Post" } ); }); 

基于属性的

关于MVC6的一个好处是,您也可以通过使用相应的RouteAttribute和/或HttpGet / HttpPost模板参数(如下所示)来装饰Controller类和/或Action方法,从而在每个控制器的基础上定义路由:

 using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNet.Mvc; namespace MyNamespace.Controllers { [Route("api/[controller]")] public class ItemsController : Controller { // GET: api/items [HttpGet()] public IEnumerable<string> Get() { return GetLatestItems(); } // GET: api/items/5 [HttpGet("{num}")] public IEnumerable<string> Get(int num) { return GetLatestItems(5); } // GET: api/items/GetLatestItems [HttpGet("GetLatestItems")] public IEnumerable<string> GetLatestItems() { return GetLatestItems(5); } // GET api/items/GetLatestItems/5 [HttpGet("GetLatestItems/{num}")] public IEnumerable<string> GetLatestItems(int num) { return new string[] { "test", "test2" }; } // POST: /api/items/PostSomething [HttpPost("PostSomething")] public IActionResult Post([FromBody]string someData) { return Content("OK, got it!"); } } } 

该控制器将处理以下请求:

  [GET] api/items [GET] api/items/5 [GET] api/items/GetLatestItems [GET] api/items/GetLatestItems/5 [POST] api/items/PostSomething 

另请注意,如果使用两种方法来避免,基于属性的路由(定义时)将覆盖基于约定的路由,并且它们都将覆盖由UseMvc()定义的默认路由。

欲了解更多信息,您还可以阅读以下文章 。