简体   繁体   English

如何将不同类型的参数传递给通用 ServiceFilter 或 ActionFilter

[英]How to pass parameter of different type to a generic ServiceFilter or ActionFilter

I am not very experienced on C# and ASP, and I am not sure I am taking the right approach to this problem.我对 C# 和 ASP 不是很有经验,我不确定我是否对这个问题采取了正确的方法。

This is a brief representation of it:这是它的简要表示:

I have several endpoints related to an user but with different parameters (eg. string or UserDTO) Here are a couple of them:我有几个与用户相关但具有不同参数(例如字符串或 UserDTO)的端点,这是其中几个:

[AllowAnonymous]
[HttpPut("{username}")]
// I want to pass [FromBody]UserUpdateDTO to the filter
[ServiceFilter(typeof(UserChangeManagerFilter<UserUpdateDTO>))]
public ActionResult<InternalStatus> UpdateUser([FromBody]UserUpdateDTO userDto)
{
...
}

[AllowAnonymous]
[HttpDelete("{username}")]
// I want to pass {username} to the filter 
[ServiceFilter(typeof(UserChangeManagerFilter<string>))]
public ActionResult<InternalStatus> DeleteUser(string username)
{
...
}

Now, I need to execute some code after each action is executed.现在,我需要在执行每个操作后执行一些代码。 For this, I have created a generic filter My problem is that the filter needs to know the user details, so the PUT endpoint has to pass the UserDTO element to the filter, and the DELETE endpoint has to pass the username.为此,我创建了一个通用过滤器 我的问题是过滤器需要知道用户详细信息,因此 PUT 端点必须将 UserDTO 元素传递给过滤器,而 DELETE 端点必须传递用户名。 I don't know how to do that exactly, but researching, I have seen that using a generic sercive filter was an option.我不知道该怎么做,但经过研究,我发现使用通用服务过滤器是一种选择。 So I created this one:所以我创建了这个:

namespace ActionFilters.ActionFilters
{
    public class UserChangeManagerFilter<T> : IActionFilter
    {
        private UserInfo _user;

        public UserChangeManagerFilter(UserUpdateDTO userContext)
        {
            _user.Username = userContext.Username;
            _user.Firstname = userContext.FirstName; 
            ...
        }
        public UserChangeManagerFilter(string username)
        {
            _user.Username = username;
            _user.Firstname = ""; 
            ...
        }

        public void OnActionExecuting(ActionExecutingContext context)
        {

        }
        public void OnActionExecuted(ActionExecutedContext context)
        {
              // Do whatever I need to do here
        }
}

I am adding the service in Startup.cs as below:我在 Startup.cs 中添加服务,如下所示:

services.AddScoped<UserChangeManagerFilter<UserUpdateDTO>>();
services.AddScoped<UserChangeManagerFilter<string>>();

When I execute the PUT endpoint, I get当我执行 PUT 端点时,我得到

System.InvalidOperationException: No constructor for type 'ActionFilters.ActionFilters.UserChangeManagerFilter`1[xxx.Services.UserUpdateDTO]' can be instantiated using services from the service container and default values.

When I execute the DELETE endpoint I get当我执行 DELETE 端点时,我得到

System.InvalidOperationException: No constructor for type 'ActionFilters.ActionFilters.UserChangeManagerFilter`1[System.String]' can be instantiated using services from the service container and default values.

I know this is not a direct answer to your question but how about using a non generic filter and then using the OnActionExecuting to inspect the model being passed and extracting the data as needed depending on the type of object received:我知道这不是对您问题的直接回答,但是如何使用非通用过滤器然后使用 OnActionExecuting 来检查正在传递的 model 并根据收到的 object 的类型根据需要提取数据:

   public void OnActionExecuting(ActionExecutingContext context)
   {
       var userDto = actionContext.ActionArguments.Values.OfType<UserUpdateDTO>().Single();
       if(userDto !=null)
       {
           _user.Username = userContext.Username;
           _user.Firstname = userContext.FirstName;
           ...
       }else
       {
           //look for the string value
       }
   }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM