Один контроллер с несколькими получить способами в Интернете ASP.NET API-интерфейс
в Web API у меня был класс аналогичной структуры:
public class SomeController : ApiController
{
[WebGet(UriTemplate = "{itemSource}/Items")]
public SomeValue GetItems(CustomParam parameter) { ... }
[WebGet(UriTemplate = "{itemSource}/Items/{parent}")]
public SomeValue GetChildItems(CustomParam parameter, SomeObject parent) { ... }
}
поскольку мы могли сопоставлять отдельные методы, было очень просто получить правильный запрос в нужном месте. Для подобного класса, который имел только один GET метод, но также имел
14 ответов:
Это лучший способ, который я нашел для поддержки дополнительных методов GET и поддержки обычных методов REST. Добавьте в 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)});Я проверил это решение с помощью тестового класса ниже. Я смог успешно ударить каждый метод в моем контроллере ниже:
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 к методу.
уйти от этого:
config.Routes.MapHttpRoute("API Default", "api/{controller}/{id}", new { id = RouteParameter.Optional });для этого:
config.Routes.MapHttpRoute("API Default", "api/{controller}/{action}/{id}", new { id = RouteParameter.Optional });следовательно, теперь вы можете указать, какое действие (метод) вы хотите отправить свой HTTP-запрос.
проводки "http://localhost:8383/api/Command/PostCreateUser" вызывает:
public bool PostCreateUser(CreateUserCommand command) { //* ... *// return true; }и размещение в "http://localhost:8383/api/Command/PostMakeBooking" вызывает:
public bool PostMakeBooking(MakeBookingCommand command) { //* ... *// return true; }я попробовал это в самостоятельном размещенном приложении службы веб-API, и это работает как шарм :)
Я считаю, что атрибуты должны быть чище, чем вручную добавлять их с помощью кода. Вот простой пример.
[RoutePrefix("api/example")] public class ExampleController : ApiController { [HttpGet] [Route("get1/{param1}")] // /api/example/get1/1?param2=4 public IHttpActionResult Get(int param1, int param2) { Object example = null; return Ok(example); } }Вам также нужно это в вашем webapiconfig
config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); config.Routes.MapHttpRoute( name: "ActionApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } );Хорошие Ссылки http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api Это объясняет маршрутизацию лучше. http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api
вам нужно определить дальнейшие маршруты в global.асакс.cs вот так:
routes.MapHttpRoute( name: "Api with action", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } );
Я не уверен, что вы нашли ответ, но я сделал это, и это работает
public IEnumerable<string> Get() { return new string[] { "value1", "value2" }; } // GET /api/values/5 public string Get(int id) { return "value"; } // GET /api/values/5 [HttpGet] public string GetByFamily() { return "Family value"; }теперь в глобальном.asx
routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapHttpRoute( name: "DefaultApi2", routeTemplate: "api/{controller}/{action}", defaults: new { id = RouteParameter.Optional } ); routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } );
вы пробовали переключиться на WebInvokeAttribute и установить метод "GET"?
Я считаю, что у меня была аналогичная проблема и переключился на явное указание того, какой метод (GET/PUT/POST/DELETE) ожидается для большинства, если не всех, моих методов.
public class SomeController : ApiController { [WebInvoke(UriTemplate = "{itemSource}/Items"), Method="GET"] public SomeValue GetItems(CustomParam parameter) { ... } [WebInvoke(UriTemplate = "{itemSource}/Items/{parent}", Method = "GET")] public SomeValue GetChildItems(CustomParam parameter, SomeObject parent) { ... } }WebGet должны обрабатывать его, но я видел, что у него есть некоторые проблемы с несколькими Get гораздо меньше нескольких Get одного и того же типа возврата.
[Edit: ничто из этого не является действительным с заходом солнца В WCF WebAPI и переход к веб-API ASP.Net на стека MVC]
С новым веб-Api 2 стало проще иметь несколько методов get.
если параметр передан
GETметоды достаточно различны для системы маршрутизации атрибутов, чтобы различать их типы, как в случае сints иGuids Вы можете указать ожидаемый тип в[Route...]атрибутнапример
[RoutePrefix("api/values")] public class ValuesController : ApiController { // GET api/values/7 [Route("{id:int}")] public string Get(int id) { return $"You entered an int - {id}"; } // GET api/values/AAC1FB7B-978B-4C39-A90D-271A031BFE5D [Route("{id:Guid}")] public string Get(Guid id) { return $"You entered a GUID - {id}"; } }для получения более подробной информации об этом подходе, смотрите здесь http://nodogmablog.bryanhogan.net/2017/02/web-api-2-controller-with-multiple-get-methods-part-2/
другие варианты, чтобы дать
GETметоды разные маршруты.[RoutePrefix("api/values")] public class ValuesController : ApiController { public string Get() { return "simple get"; } [Route("geta")] public string GetA() { return "A"; } [Route("getb")] public string GetB() { return "B"; } }смотрите здесь для более подробной информации - http://nodogmablog.bryanhogan.net/2016/10/web-api-2-controller-with-multiple-get-methods/
Я пытался использовать маршрутизацию атрибутов Web Api 2, чтобы разрешить несколько методов Get, и я включил полезные предложения из предыдущих ответов, но в контроллере я только оформил" специальный " метод (пример):
[Route( "special/{id}" )] public IHttpActionResult GetSomethingSpecial( string id ) {...без Также также размещения [RoutePrefix] в верхней части контроллера:
[RoutePrefix("api/values")] public class ValuesController : ApiControllerЯ получал ошибки, заявив, что не найден маршрут, соответствующий представленному URI. Когда-то у меня были оба [маршрута], украшающие метод как и [RoutePrefix], украшающий контроллер в целом, он работал.
In ASP.NET ядро 2.0 вы можете добавить маршрут контроллер:
[Route("api/[controller]/[action]")] public class SomeController : Controller { public SomeValue GetItems(CustomParam parameter) { ... } public SomeValue GetChildItems(CustomParam parameter, SomeObject parent) { ... } }
ни один из приведенных выше примеров не работал для моих личных нужд. Ниже то, что я в конечном итоге делает.
public class ContainsConstraint : IHttpRouteConstraint { public string[] array { get; set; } public bool match { get; set; } /// <summary> /// Check if param contains any of values listed in array. /// </summary> /// <param name="param">The param to test.</param> /// <param name="array">The items to compare against.</param> /// <param name="match">Whether we are matching or NOT matching.</param> public ContainsConstraint(string[] array, bool match) { this.array = array; this.match = match; } public bool Match(System.Net.Http.HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values, HttpRouteDirection routeDirection) { if (values == null) // shouldn't ever hit this. return true; if (!values.ContainsKey(parameterName)) // make sure the parameter is there. return true; if (string.IsNullOrEmpty(values[parameterName].ToString())) // if the param key is empty in this case "action" add the method so it doesn't hit other methods like "GetStatus" values[parameterName] = request.Method.ToString(); bool contains = array.Contains(values[parameterName]); // this is an extension but all we are doing here is check if string array contains value you can create exten like this or use LINQ or whatever u like. if (contains == match) // checking if we want it to match or we don't want it to match return true; return false; }чтобы использовать выше в вашем маршруте используйте:
config.Routes.MapHttpRoute("Default", "{controller}/{action}/{id}", new { action = RouteParameter.Optional, id = RouteParameter.Optional}, new { action = new ContainsConstraint( new string[] { "GET", "PUT", "DELETE", "POST" }, true) });что происходит, это ограничение типа подделок в методе, так что этот маршрут будет соответствовать только методам GET, POST, PUT и DELETE по умолчанию. "True" там говорит, что мы хотим проверить соответствие элементов в массиве. Если бы это было ложно, вы бы сказали исключить тех, кто в stry вы можете использовать маршруты выше этот метод по умолчанию как:
config.Routes.MapHttpRoute("GetStatus", "{controller}/status/{status}", new { action = "GetStatus" });в приведенном выше он по существу ищет следующий URL =>
http://www.domain.com/Account/Status/Activeили что-то подобное.помимо вышесказанного, я не уверен, что я слишком сошел с ума. В конце концов, это должно быть за ресурс. Но я вижу необходимость сопоставлять дружественные URL-адреса по разным причинам. Я чувствую себя довольно уверенно, поскольку веб-Api развивается, будет какое-то положение. Если время я построю более постоянное решение и пост.
не мог сделать любой из вышеперечисленных маршрутизации решения -- часть синтаксиса, кажется, изменились, и я все еще новичок в MVC -- в крайнем случае, хотя я собрал это действительно ужасно (и простой) хак, который будет Вам мне теперь -- внимание, это заменяет "общественное Мой_объект GetMyObjects(длинный код)" методом-то менять "идентификатор"'S тип в строку, и измените тип возвращаемого объекта.
// GET api/MyObjects/5 // GET api/MyObjects/function public object GetMyObjects(string id) { id = (id ?? "").Trim(); // Check to see if "id" is equal to a "command" we support // and return alternate data. if (string.Equals(id, "count", StringComparison.OrdinalIgnoreCase)) { return db.MyObjects.LongCount(); } // We now return you back to your regularly scheduled // web service handler (more or less) var myObject = db.MyObjects.Find(long.Parse(id)); if (myObject == null) { throw new HttpResponseException ( Request.CreateResponse(HttpStatusCode.NotFound) ); } return myObject; }
Если у вас есть несколько действий в одном файле, то передайте один и тот же аргумент, например Id для всех действий. Это связано с тем, что действие только может идентифицировать Id, поэтому вместо того, чтобы давать какое-либо имя аргументу, только объявляйте Id так.
[httpget] [ActionName("firstAction")] firstAction(string Id) {..... ..... } [httpget] [ActionName("secondAction")] secondAction(Int Id) {..... ..... } //Now go to webroute.config file under App-start folder and add following routes.MapHttpRoute( name: "firstAction", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); routes.MapHttpRoute( name: "secondAction", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } );
Простая Альтернатива
просто используйте строку запроса.
маршрут
config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } );контроллер
public class TestController : ApiController { public IEnumerable<SomeViewModel> Get() { } public SomeViewModel GetById(int objectId) { } }запросы
GET /Test GET /Test?objectId=1Примечание
имейте в виду, что строка запроса param не должна быть "id" или любой другой параметр в настроенном маршруте.
изменить WebApiConfig и добавить в конце другой стороны.MapHttpRoute вот так:
config.Routes.MapHttpRoute( name: "ServiceApi", routeTemplate: "api/Service/{action}/{id}", defaults: new { id = RouteParameter.Optional } );затем создайте контроллер следующим образом:
public class ServiceController : ApiController { [HttpGet] public string Get(int id) { return "object of id id"; } [HttpGet] public IQueryable<DropDownModel> DropDowEmpresa() { return db.Empresa.Where(x => x.Activo == true).Select(y => new DropDownModel { Id = y.Id, Value = y.Nombre, }); } [HttpGet] public IQueryable<DropDownModel> DropDowTipoContacto() { return db.TipoContacto.Select(y => new DropDownModel { Id = y.Id, Value = y.Nombre, }); } [HttpGet] public string FindProductsByName() { return "FindProductsByName"; } }вот как я ее решила. Я надеюсь, что это поможет кому-то.
Comments