Web Api'deki istekle eşleşen birden fazla eylem bulundu


243

2 "Get" yöntemi almaya çalıştığımda bu hatayı almaya devam ediyorum

İstekle eşleşen birden fazla işlem bulundu: webapi

Yığındaki diğer benzer sorulara bakıyordum ama anlamıyorum.

Ben 2 farklı isimleri ve "HttpGet" özniteliğini kullanarak

[HttpGet]
public HttpResponseMessage Summary(MyVm vm)
{
    return null;
}

[HttpGet]
public HttpResponseMessage FullDetails()
{
    return null;
}

Yanıtlar:


485

Rota haritanız muhtemelen şöyle bir şeydir:

routes.MapHttpRoute(
name: "API Default",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional });

Ancak aynı http yöntemiyle birden fazla işlem yapabilmek için webapi'ye aşağıdaki gibi rota üzerinden daha fazla bilgi sağlamanız gerekir:

routes.MapHttpRoute(
name: "API Default",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional });

RouteTemplate'in artık bir eylem içerdiğine dikkat edin. Burada daha fazla bilgi var: http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api

Güncelleme:

Pekala, şimdi burada ne olduğunuzu anladığımı düşündüğümde başka bir şey daha var:

Belki de eylem url parametresine ihtiyacınız yoktur ve peşinde olduğunuz içerikleri başka bir şekilde tanımlamanız gerekir. Yöntemlerin aynı varlıktan veri döndürdüğünü söylediğiniz için, parametrelerin sizin için açıklamayı yapmasına izin verin.

Örneğin, iki yönteminiz şu şekilde dönüştürülebilir:

public HttpResponseMessage Get()
{
    return null;
}

public HttpResponseMessage Get(MyVm vm)
{
    return null;
}

MyVm nesnesine ne tür veriler iletiyorsunuz? Eğer değişkenleri sadece URI'den geçirebiliyorsanız, o rotaya gitmenizi öneririm. Aksi takdirde, nesneyi isteğin gövdesinde göndermeniz gerekir ve bir GET yaparken çok HTTP değilsiniz (ancak çalışır, sadece MyVm'in önünde [FromBody] 'i kullanın).

Umarım bu, eylem adını veya [HttpGet] özniteliğini kullanmadan tek bir denetleyicide birden fazla GET yöntemine sahip olabileceğinizi gösterir.


Öyle ya da böyle yapmanın herhangi bir avantajı var mı? İkinciyi yaparsam, her yönteme Http eylemi koymak zorunda mıyım? Bu büyük geri çekilme mi?
chobo2

3
Birinin diğerine üstünlük sağlayıp sağlamadığı gerçekten projenize bağlıdır. RESTful bir API oluşturuyorsanız, HTTP kurallarını (GET, POST, PUT, DELETE ...) kullanmak istersiniz. Bu durumda, yönlendirme kodunun ilk bloğu gitmek için bir yoldur, ancak API ile gösterdiğiniz her varlık için farklı bir denetleyici istersiniz. Yöntem adlarınıza dayanarak, bu durum böyle değil, bu yüzden daha açıklayıcı yönlendirme kullanın sanırım. Rotanız eylemi içerdiğinde, http özniteliğini her yönteme açıkça koymak istersiniz.
Jed

1
@ chobo2 Neden sadece denetleyicide buna göre adlandırılmış yöntemleri kullanmıyorsunuz? GetSummary (MyVm wm) ve GetDetails ()
Jed

1
Cevabınız için teşekkürler, her iki eylemimin de farklı isimleri olmasına rağmen rota çözümlemesinin neden çalışmadığını anlamama yardımcı oldu. Neden sadece varsayılan davranış (örneğin neden webapiconfig.cs varsayılan yol şablonu "{action}" inlcude değil) olarak kafam karıştı!
Tejas Sharma

1
alanları kullanarak eğer @bruno ayrıca AdminAreaRegistration böyle 'yönetici' belirli API'leri ekleyebilir stackoverflow.com/a/9849011/16940
Simon_Weaver

67

Web API 2'den itibaren güncelleme.

WebApiConfig.cs dosyanızdaki bu API yapılandırmasıyla:

public static void Register(HttpConfiguration config)
{
    //// Web API routes
    config.MapHttpAttributeRoutes(); //Don't miss this

    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = System.Web.Http.RouteParameter.Optional }
    );
}

Denetleyicimizi şu şekilde yönlendirebilirsiniz:

[Route("api/ControllerName/Summary")]
[HttpGet]
public HttpResponseMessage Summary(MyVm vm)
{
    rturn null;
}

[Route("api/ControllerName/FullDetails")]
[HttpGet]
public HttpResponseMessage FullDetails()
{
    return null;
}

Burada ControllerName, denetleyicinizin adıdır ("denetleyici" olmadan). Bu, her bir işlemi yukarıda ayrıntıları verilen rota ile almanıza olanak tanır.

Daha fazla okuma için: http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2


Bu çözümü gerçekten beğendim. Varsayılan rotam hala aynı ve istisnalar için bir "istisna"
rotam var

parametreleri url EX ile eşleyebilirsiniz: [Route ("api / ControllerName / Summary / {vm}")]
nulltron

15

Web API'sında (varsayılan olarak) yöntemler, HTTP yöntemi ve rota değerlerinin bir kombinasyonuna göre seçilir .

MyVmkarmaşık bir nesneye benziyor, gövdeden biçimlendirici tarafından okunuyor, böylece rota verileri açısından iki özdeş yönteminiz var (her ikisinin de rotadan herhangi bir parametresi olmadığından) - bu, dağıtım programının ( IHttpActionSelector) uygun olanla eşleşmesini imkansız hale getiriyor .

Belirsizliği gidermek için bunları sorgu dizesi veya route parametresi ile ayırmanız gerekir.


14

Web'de bir sürü arama yaptıktan ve yönlendirme haritası için en uygun formu bulmaya çalıştıktan sonra aşağıdakileri bulduysanız

config.Routes.MapHttpRoute("DefaultApiWithId", "Api/{controller}/{id}", new { id =RouteParameter.Optional }, new { id = @"\d+" });
config.Routes.MapHttpRoute("DefaultApiWithAction", "Api/{controller}/{action}");

Bu eşleme hem eylem adı eşlemesi hem de temel http kuralına uygulanır (GET, POST, PUT, DELETE)


9
Benim için bu işe yaradı, ancak sadece rota konfigürasyonundaki rotaların sırasını değiştirdikten sonra, eylemli olanın önce ortaya çıkması
Fredrik Stolpe

burada tam sipariş önemlidir
AT


5

İşlemleri kullanmadan seçenekler şöyle olur:

  1. yöntemlerden birini farklı bir denetleyiciye taşıyın, böylece çatışmasınlar.

  2. parametreyi alan yalnızca bir yöntem kullanın ve boşsa, diğer yöntemi kodunuzdan çağırın.


Çözüm olabilir, ama optimum değil, yine de
yanımdan

4

Bu çözüm benim için çalıştı.

Lütfen önce Route2'yi WebApiConfig dosyasına yerleştirin. Ayrıca her yöntemin önüne HttpGet ve HttpPost ekleyin ve url'ye denetleyici adını ve yöntem adını ekleyin.

WebApiConfig =>

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

Denetleyici =>

public class ValuesController : ApiController
{

    [HttpPost]
    public string GetCustomer([FromBody] RequestModel req)
    {
        return "Customer";
    }

    [HttpPost]
    public string GetCustomerList([FromBody] RequestModel req)
    {
        return "Customer List";
    }
}

URL =>

http://localhost:7050/api/Values/GetCustomer

http://localhost:7050/api/Values/GetCustomerList

4

Bu, her şeyin doğru olduğunu bilen ve 50 kez kontrol eden herkes için cevaptır .....

Tekrar tekrar bakmadığınızdan emin olun RouteConfig.cs .

Düzenlemek istediğiniz dosyanın adı WebApiConfig.cs

Ayrıca, muhtemelen tam olarak şöyle görünmelidir:

using System.Web.Http;

namespace My.Epic.Website
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
          config.MapHttpAttributeRoutes();

          // api/Country/WithStates
          config.Routes.MapHttpRoute(
            name: "ControllerAndActionOnly",
            routeTemplate: "api/{controller}/{action}",
            defaults: new { },
            constraints: new { action = @"^[a-zA-Z]+([\s][a-zA-Z]+)*$" });

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

Kendimi yaklaşık 3 saat kurtarabilirdim.


1
Teşekkürler, beni yaklaşık 3 saat kurtardın
geedubb

3

Ben iki Get yöntemleri, bir parametresiz ve bir parametre olarak karmaşık bir tür ile aynı hata var olduğunu buldum. Bunu ilk parametre olarak Id adlı int türünde kukla bir parametre ve ardından karmaşık tür parametrem ekleyerek çözdüm. Daha sonra rota şablonuna karmaşık tip parametresini ekledim. Aşağıdakiler benim için çalıştı.

İlk önce:

public IEnumerable<SearchItem> Get()
{
...
}

İkincisi:

public IEnumerable<SearchItem> Get(int id, [FromUri] List<string> layers)
{
...
}

WebApiConfig:

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

3

Web API denetleyicisi yerine MVC denetleyicisi kullanılması nedeniyle mümkündür. Web API denetleyicisinde ad alanını kontrol edin, aşağıdaki gibi olmalıdır

using System.Net;
using System.Net.Http;
using System.Web.Http;

Ad alanı aşağıdaki gibi ise, web api denetleyicisi yöntem çağrısında yukarıdaki hatayı verir

using System.Web;
using System.Web.Mvc;

2

Lütfen farklı ada ve parametrelere sahip iki yönteminiz olduğunu kontrol edin.

Öyleyse lütfen yöntemlerden herhangi birini silin ve deneyin.


2

Ekstra eylemlerle WebAPI denetleyicilerimi artırmaya çalışırken bu sorunla karşılaştım.

Varsayalım

public IEnumerable<string> Get()
{
    return this.Repository.GetAll();
}

[HttpGet]
public void ReSeed()
{
    // Your custom action here
}

Şimdi / api / denetleyici isteğini karşılayan ve TS tarafından açıklanan sorunu tetikleyen iki yöntem vardır.

Ek eylemlerime "kukla" parametreler eklemek istemedim, bu yüzden varsayılan eylemlere baktım ve geldim:

[ActionName("builtin")]
public IEnumerable<string> Get()
{
    return this.Repository.GetAll();
}

"çift" yol bağlaması ile birlikte ilk yöntem için:

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { action = "builtin", id = RouteParameter.Optional },
    constraints: new { id = @"\d+" });

config.Routes.MapHttpRoute(
    name: "CustomActionApi",
    routeTemplate: "api/{controller}/{action}");

Görünüşe göre ilk rota şablonunda "action" parametresi olmamasına rağmen "normal" WebAPI çağrılarının ve ekstra eylem çağrılarının yönlendirilmesini ayırmamıza izin veren varsayılan bir eylem yapılandırabilirsiniz.


2

Benim durumumda Her şey yolundaydı

1) Web Config doğru yapılandırıldı 2) Güzergah öneki ve Güzergah özellikleri uygun

Hala hata alıyordum. Benim durumumda "Route" özniteliği (F12 tuşuna basarak) System.Web.MVc için işaret oldu ama soruna neden System.Web.Http değil.


Bu cevap bana çok yardımcı oldu!
tvb108108

1

[Route("api/[controller]/[action]")]Denetleyici sınıfınıza ekleyebilirsiniz .

[Route("api/[controller]/[action]")]
[ApiController]
public class MySuperController : ControllerBase
{
 ...
}

0

Eski bir soru olduğunu biliyorum, ancak bazen WebAPI'ye bağlanmak için AngularJS gibi hizmet kaynaklarını kullandığınızda, doğru yolu kullandığınızdan emin olun, aksi takdirde bu hata oluşur.


0

Denetleyici yöntemlerinizi [Gtt | PUT | POST | DELETE eylemleri için [HttpPost / Put / Get / Delete] özniteliğiyle süslemediğinizden emin olun. Bu özelliği vanilya Post denetleyici eylemime ekledim ve 404'e neden oldu.

Umarım bu çok sinir bozucu olabilir ve durma ilerleyebileceği için birine yardımcı olur.


0

Örneğin => TestController

        [HttpGet]
        public string TestMethod(int arg0)
        {
            return "";
        }

        [HttpGet]
        public string TestMethod2(string arg0)
        {
            return "";
        }

        [HttpGet]
        public string TestMethod3(int arg0,string arg1)
        {
            return "";
        }

Yalnızca WebApiConfig.cs dosyasını değiştirebiliyorsanız.

 config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}/",
                defaults: null
            );

Bu kadar :)

Ve Sonuç: resim açıklamasını buraya girin


0

Şunu denediniz mi:

[HttpGet("Summary")]
public HttpResponseMessage Summary(MyVm vm)
{
    return null;
}

[HttpGet("FullDetails")]
public HttpResponseMessage FullDetails()
{
    return null;
}

1
HttpGetÖznitelik bir dize bağımsız değişkenini kabul eden bir yapıcıya sahip olmadığından, bu, .NET Core dışındaki projelerde derlenmez .
Hoppeduppeanut
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.