【问题标题】:Avoid null model when no data is posted in Web API在 Web API 中没有发布数据时避免使用 null 模型
【发布时间】:2015-11-20 23:50:48
【问题描述】:

这个问题和我想达到的类似:

Avoiding null model in ASP.Net Web API when no posted properties match the model

但它没有得到答复。

我有一条采用 GET 模型的路线:

    [HttpGet, Route("accounts")]
    public AccountListResult Post(AccountListRequest loginRequest)
    {
        return accountService.GetAccounts(loginRequest);
    }

模型中填充了来自操作过滤器的附加数据。

在这种情况下,所有需要知道的是 UserId,动作过滤器根据 cookie/header 添加到模型中,并随请求一起传递。

我想使用 WebAPI 中的所有默认模型绑定,但我想避免空对象。

我不相信模型绑定能解决我的问题。

How do I replace the behaviour of Web API model binding so that instead of Null I receive a new instance when no parameters are passed in

这更接近我想要做的,除了它的每个类型很乏味。

【问题讨论】:

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


    【解决方案1】:

    编辑:由于问题是针对 Web API 的,所以我也在下面发布了 Web API 解决方案。

    您可以在操作过滤器中执行以下操作。以下代码仅在您的模型包含默认构造函数时才有效。

    Web API 实现:

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
         var parameters = actionContext.ActionDescriptor.GetParameters();
    
         foreach (var parameter in parameters)
         {
             object value = null;
    
             if (actionContext.ActionArguments.ContainsKey(parameter.ParameterName))
                 value = actionContext.ActionArguments[parameter.ParameterName];
    
             if (value != null)
                continue;
    
             value = CreateInstance(parameter.ParameterType);
             actionContext.ActionArguments[parameter.ParameterName] = value;
         }
    
         base.OnActionExecuting(actionContext);
    }
    
    protected virtual object CreateInstance(Type type)
    {
       // Check for existence of default constructor using reflection if needed
       // and if performance is not a constraint.
    
       // The below line will fail if the model does not contain a default constructor.
       return Activator.CreateInstance(type);
    }
    

    MVC 实现:

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var parameters = filterContext.ActionDescriptor.GetParameters();
    
        foreach (var parameter in parameters)
        {
            if (filterContext.ActionParameters.ContainsKey(parameter.ParameterName))
            {
                object value = filterContext.ActionParameters[parameter.ParameterName];
    
                if (value == null)
                {
                     // The below line will fail if the model does not contain a default constructor.
                     value = Activator.CreateInstance(parameter.ParameterType);                          
                     filterContext.ActionParameters[parameter.ParameterName] = value;
                }
            }                
        }
    
        base.OnActionExecuting(filterContext);
    }
    

    【讨论】:

    • 很棒的东西,我假设这是为 MVC 编写的,因为 WebAPI 有 ActionArguments 而不是参数。不过,我几乎已经在 WebAPI 中实现了您编写的内容,并且它正在工作。非常感谢!
    • 我的错。提供的实现是针对 MVC 的。对于 Web API,实现几乎相似。
    【解决方案2】:

    @Sarathy 的解决方案有效,但不会触发对其创建的对象的模型验证。这可能会导致将空模型传递给操作但 ModelState.IsValid 仍然评估为 true 的情况。

    出于我自己的目的,有必要在创建空模型对象的情况下触发模型的重新验证:

        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            var parameters = actionContext.ActionDescriptor.GetParameters();
    
            foreach (var parameter in parameters)
            {
                object value = null;
    
                if (actionContext.ActionArguments.ContainsKey(parameter.ParameterName))
                    value = actionContext.ActionArguments[parameter.ParameterName];
    
                if (value != null)
                    continue;
    
                value = Activator.CreateInstance(parameter.ParameterType);
                actionContext.ActionArguments[parameter.ParameterName] = value;
    
                var bodyModelValidator = actionContext.ControllerContext.Configuration.Services.GetBodyModelValidator();
                var metadataProvider = actionContext.ControllerContext.Configuration.Services.GetModelMetadataProvider();
    
                bodyModelValidator.Validate(value, value.GetType(), metadataProvider, actionContext, string.Empty);
            }
    
            base.OnActionExecuting(actionContext);
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-30
      • 1970-01-01
      • 1970-01-01
      • 2016-08-09
      • 1970-01-01
      • 1970-01-01
      • 2018-05-16
      • 2021-01-21
      相关资源
      最近更新 更多