如何在控制器操作上使用多态性一方法 [英] How to use polymorphism one method on controller actions

查看:17
本文介绍了如何在控制器操作上使用多态性一方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试将ASP.NET Web API转换为ASP.NET核心Web API,但遇到错误

我在ASP.NET WebAPI中的代码

public class TestController : ApiController
{
    // GET /test
    public object Get()
    {
        return "get";
    }

    // GET /test?id={id}
    public object Get(string id)
    {
        return id;
    }

    // GET /test?id={id}&anyParam={anyParam}
    public object Get(string id, string anyParam)
    {
        return id + anyParam;
    }
}

config.Routes.MapHttpRoute("Controller", "{controller}");

尝试将其转换为ASP.NET Core 2.1/3.0

[ApiController]
[Route("{controller}")]
public class TestController : ControllerBase
{
    // GET /test
    public object Get()
    {
        return "get";
    }

    // GET /test?id={id}
    public object Get(string id)
    {
        return id;
    }

    // GET /test?id={id}&anyParam={anyParam}
    public object Get(string id, string anyParam)
    {
        return id + anyParam;
    }
}

services.AddControllers(); 
app.UseRouting();
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });

和我在ASP.NET Core中拥有

AmbiguousMatchException:请求与多个终结点匹配

推荐答案

合理的解决方案是只有一个接受三个参数的方法。

但是,合理的解决方案不会产生最有趣的堆栈溢出答案,所以下面是如何使用两个自定义属性来实现这一点的,一个属性声明所需的参数,另一个属性声明排除哪些参数:

public class RequireRequestParameterAttribute : ActionMethodSelectorAttribute
{
    private readonly string[] _requiredNames;
    public RequireRequestParameterAttribute(params string[] names)
    {
        this._requiredNames = names;
    }
    public override bool IsValidForRequest(
        RouteContext routeContext,
        ActionDescriptor action
    ) =>
        this._requiredNames
            .All(
                routeContext
                   .HttpContext
                   .Request
                   .Query
                   .ContainsKey
            );
}

public class DisallowRequestParameterAttribute : ActionMethodSelectorAttribute
{
    private readonly string[] _forbiddenNames;
    public DisallowRequestParameterAttribute(params string[] names)
    {
        this._forbiddenNames = names;
    }
    public override bool IsValidForRequest(
        RouteContext routeContext,
        ActionDescriptor action
    ) =>
        !(this._forbiddenNames
             .Any(
                 routeContext
                     .HttpContext
                     .Request
                     .Query
                     .ContainsKey
              )
        );
}

现在可以按如下方式应用属性:

[ApiController]
[Route("[controller]")]
public class TestController : ControllerBase
{
    // GET test
    public object Get()
    {
        return "Get";
    }


    // GET test?id={id}
    [RequireRequestParameter("id")]
    [DisallowRequestParameter("anyParam")]
    public object Get(string id)
    {
        return id;
    }

    // GET test?id={id}&anyParam={anyParam}
    [RequireRequestParameter("id", "anyParam")]
    public object Get(string id, string anyParam)
    {
        return $"{id}: {anyParam}";
    }
}

这意味着如果您使用第三个参数添加另一个方法,您将承担添加或修改其他方法的DisallowRequestParameter属性的维护负担。

这篇关于如何在控制器操作上使用多态性一方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆