0

I have 2 http GET APIs in my controller class which have the same rout but different complex type parameters as follows:

  [httpGet]
  [Route("info")]
  public async Task<IActionResult> GetinfoA(A classAobj){...}
  [httpGet]
  [Route("info")]
  public async Task<IActionResult> GetinfoB(B classBobj){...}
------------------
class A{
   string prop1{get;set;}
   string prop2{get;set;}
}
class B{
 string prop3{get;set;}
   string prop4{get;set;}
}

What I am looking for is to match actions based on the name of class properties for example if query has the parameter prop3 action GetinfoB should be matched and if it has parameter prop1 GetinfoA should be matched. currently I am getting ambiguty error for my requests like /info?prop1="bla"

  • I'm thinking both are likely POST and your just sending different bodies, I don't think you can route based on the body content but I could be wrong. – JSteward May 14 '20 at 20:16
  • No it is GET request – sarah daneshvar May 14 '20 at 20:24
  • I unedrstand what you want to do, but I think this is wrong. You should have some clear routing in your controllers. I would suggest to change routing and use the more descriptive routes getInfoA and getInfoB, respectively. Then you add swagger and you have a nice and clear api documentation. – Stelios Giakoumidis May 14 '20 at 21:13

2 Answers2

0

My first option would be to just name the route differently, but if you really need a single method for two different arguments I would merge those two actions into one receiving a wrapper object as parameter. Kind of:

[Route("info")]
  public async Task<IActionResult> Getinfo(Wrapper obj){
    if (obj.ObjA != null) doA(obj.ObjA);
    else if (obj.ObjB != null) doB(obj.ObjB);
  }
------------------
class Wrapper {
    A ObjA { get; set; }
    B ObjB { get; set; }
}
class A{
   string prop1{get;set;}
   string prop2{get;set;}
}
class B{
 string prop3{get;set;}
   string prop4{get;set;}
}

Or just recieve and object parameter and try to cast it.

But as mentioned, I would go with renaming the routes.

devcrp
  • 1,323
  • 7
  • 17
0

I found the solution which is similar to ASP.NET MVC ambiguous action methods

defined a class as follows:

    public class RequireRouteValuesAttribute : Microsoft.AspNetCore.Mvc.ActionConstraints.ActionMethodSelectorAttribute
    {

        public RequireRouteValuesAttribute(string[] valueNames)
        {
            ValueNames = valueNames.Select(s => s.ToLowerInvariant()).ToArray();
        }

        public override bool IsValidForRequest(RouteContext routeContext, ActionDescriptor action)
        {
            return ValueNames.Any(v => routeContext.HttpContext.Request.Query.Keys.Contains(v));
        }

        public string[] ValueNames { get; private set; }
    }

and then decorated my actions with this class:

[Route("info")]
[RequireRouteValuesAttribute(new[]{"prop1","prop2"})
  public async Task<IActionResult> GetinfoA(A classAobj){...}
[Route("info")]
[RequireRouteValuesAttribute(new[]{"prop3","prop4"})
  public async Task<IActionResult> GetinfoB(A classBobj){...}