2

Is it possible to have two actions with same route name and same method but different parameter? I have tried this:

[HttpPost]
[Route("gstr4")]
public HttpResponseMessage SubmitGSTR4([FromBody] RequestPayloadWithoutSign requestPayload)
{ }

[HttpPost]
[Route("gstr4")]
public HttpResponseMessage FileGSTR4([FromBody] RequestPayloadWithSign requestPayload)
{ }

I received a Status Code of 500 (InternalServerError) and here is raw response:

{"Message":"An error has occurred.","ExceptionMessage":"Multiple actions were found that match the request: \r\nFileGSTR4 on type APIPortal.Controllers.GSTR4Controller\r\nSubmitGSTR4 on type APIPortal.Controllers.GSTR4Controller","ExceptionType":"System.InvalidOperationException","StackTrace":"   at System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.SelectAction(HttpControllerContext controllerContext)\r\n   at System.Web.Http.Controllers.ApiControllerActionSelector.SelectAction(HttpControllerContext controllerContext)\r\n   at System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"}
Rithik Banerjee
  • 447
  • 4
  • 16

3 Answers3

3

It's not possible to have many actions with the same route and the same HTTP verb.

What you could do is to have a single action which accepts a model of a base class (possibly an abstract class) and a custom resolver.

Example:

public abstract class RequestPayload 
{
}

public class RequestPayloadWithoutSign : RequestPayload
{
}

public class RequestPayloadWithSign : RequestPayload
{
   public string Sign { get; set; }
}

public class MyController
{
    [HttpPost]
    [Route("gstr4")]
    public HttpResponseMessage SubmitGSTR4([FromBody] RequestPayload payload)
    {
        switch(payload)
        {
            case RequestPayloadWithoutSign a:
                // handle RequestPayloadWithoutSign
                break;
            case RequestPayloadWithSign b:
                // handle RequestPayloadWithSign
                break;
        }
    }
}

And, if you're using JSON mediatype for transmitting payloads, a custom JSON resolver attached to your JSON deserializer. Here's an example for Newtonsoft.Json:

class HolderConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(RequestPayload);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jo = JObject.Load(reader);
        if (jo.ContainsKey("sign"))
        {
            return new RequestPayloadWithSign
            {
                Sign = (string) jo["sign"]
            };
        }

        return new RequestPayloadWithoutSign();
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

Now add the converter to serializer settings or mark your RequestPayload class definition with [JsonConverter(typeof(RequestPayload))] attribute and it will start converting JSONs to either RequestPayloadWithSign or RequestPayloadWithoutSign types.

Jacek
  • 829
  • 12
  • 31
0

It's not possible for the same method type as http Get for multiple methods. You should have a different route

Vivek Nuna
  • 25,472
  • 25
  • 109
  • 197
0

It is only possible with different HTTP verbs. Otherwise, you have to define different routes.

https://learn.microsoft.com/en-us/aspnet/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api

Dilberted
  • 1,172
  • 10
  • 23
Laky
  • 29
  • 2
  • if the request payload is of model A then it should hit action with parameter A and if the request payload is of model B then it should hit action with parameter B. Possible? – Rithik Banerjee Jun 01 '20 at 10:40
  • I don't think you can do it with custom objects. One way to trick it is, to have one method and then delegate based on the payload. Check the following link:-https://stackoverflow.com/questions/14353466/overload-web-api-action-method-based-on-parameter-type – Laky Jun 02 '20 at 07:49