【问题标题】:Post Action method overload with same route name in ASP.Net Web API Controller在 ASP.Net Web API 控制器中具有相同路由名称的 Post Action 方法重载
【发布时间】:2020-09-19 11:16:08
【问题描述】:

是否可以有两个具有相同路由名称和相同方法但参数不同的操作? 我试过这个:

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

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

我收到了状态码 500 (InternalServerError),这是原始响应:

{"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()"}

【问题讨论】:

  • 不可能
  • 但是 HttpGet 可能吗?
  • 不,不可能。您可以拥有相同的route 和不同的http state,即。 (getpost)。但这不可能有两个GET 和相同的route
  • @RithikBanerjee 这也是不可能的
  • 一个请求可以在两种方法中映射一种方法吗?

标签: c# asp.net-web-api asp.net-web-api-routing asp.net-apicontroller


【解决方案1】:

不可能有许多具有相同路由和相同 HTTP 动词的操作。

您可以做的是有一个接受基类模型(可能是抽象类)和自定义解析器的单一操作。

例子:

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;
        }
    }
}

而且,如果您使用 JSON 媒体类型传输有效负载,则附加到您的 JSON 反序列化器的自定义 JSON 解析器。这是 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();
    }
}

现在将转换器添加到序列化程序设置或使用[JsonConverter(typeof(RequestPayload))] 属性标记您的RequestPayload 类定义,它将开始将JSON 转换为RequestPayloadWithSignRequestPayloadWithoutSign 类型。

【讨论】:

    【解决方案2】:

    只能使用不同的 HTTP 动词。否则,您必须定义不同的路线。

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

    【讨论】:

    • 如果请求负载是模型 A,那么它应该使用参数 A 执行操作,如果请求负载是模型 B,那么它应该使用参数 B 执行操作。可能吗?
    • 我认为您不能使用自定义对象来做到这一点。欺骗它的一种方法是,拥有一种方法,然后根据有效负载进行委托。检查以下链接:-stackoverflow.com/questions/14353466/…
    【解决方案3】:

    对于多个方法,不可能使用与 http Get 相同的方法类型。你应该有不同的路线

    【讨论】:

    • 必须有某种或其他方式。
    • 不可能用同一个动词
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-10
    • 2017-01-28
    • 2014-10-07
    • 2013-06-14
    • 2014-05-30
    • 2019-08-29
    相关资源
    最近更新 更多