.net – 在F#Web Api项目中使用可选的查询参数

我正在使用F#ASP.NET模板将C#webapi项目转换为F#.除了可选的查询参数,一切都很好.我不断得到这个错误
{
    "message": "The request is invalid.","messageDetail": "The parameters dictionary contains an invalid entry for parameter 'start' for method 'System.Threading.Tasks.Task`1[System.Net.Http.HttpResponseMessage] GetvendorFiles(Int32,System.Nullable`1[System.DateTime])' in 'Thor.WebApi.vendorFilesController'. The dictionary contains a value of type 'System.Reflection.Missing',but the parameter requires a value of type 'System.Nullable`1[System.DateTime]'."
}

F#函数签名:

[<HttpGet; Route("")>]
member x.GetvendorFiles( [<Optional; DefaultParameterValue(100)>] count,[<Optional; DefaultParameterValue(null)>] start : Nullable<DateTime> ) =

C#函数签名:

[HttpGet]
[Route("")]
public async Task<HttpResponseMessage> GetvendorFiles(int count = 100,DateTime? start = null)

有没有人知道任何解决方法

更新:
我弄清了这个问题的原因. ASP.NET提取控制器操作using ParameterInfo认值.显然,F#编译器不会像C#一样编译认值(即使使用DefaultParameterValueAttribute)

什么是最好的方式或解决这个问题?是否需要注入或实现自己的ParameterBinding的一些过滤器?

解决方法

您可以使用自定义ActionFilterattribute实现解决此问题.以下代码支持在缺少操作参数时使用DefaultParameterValue值,以及当action参数具有System.Reflection.Missing类型的值时.

代码也在Gist ActionFilter for ASP.NET Web API DefaultParameterValue support in F#中.

namespace System.Web.Http

open System.Reflection
open System.Web.Http.Filters
open System.Web.Http.Controllers
open System.Runtime.InteropServices

/// Responsible for populating missing action arguments from DefaultParameterValueAttribute values.
/// Created to handle this issue https://github.com/aspnet/Mvc/issues/1923
/// Note: This is for later version of System.Web.Http but Could be back-ported.
type DefaultParameterValueFixupFilter() =
  inherit ActionFilterattribute()
  /// Get list of (paramInfo,defValue) tuples for params where DefaultParameterValueAttribute is present.
  let getDefParamVals (parameters:ParameterInfo array) =
    [ for param in parameters do
        let defParamValAttrs = param.GetCustomAttributes<DefaultParameterValueAttribute>() |> List.ofSeq 
        match defParamValAttrs with
        // Review: we are ignoring null defaults.  Is this correct?
        | [x] -> if x.Value = null then () else yield param,x.Value
        | [] -> () 
        | _ -> failwith "Multiple DefaultParameterValueAttribute on param '%s'!" param.Name
    ]
  /// Add action arg default values where specified in DefaultParameterValueAttribute attrs.
  let addActionArgDefsFromDefParamValAttrs (context:HttpActionContext) =  
    match context.ActionDescriptor with
    | :? ReflectedHttpActionDescriptor as ad ->
      let defParamVals = getDefParamVals (ad.MethodInfo.GetParameters())
      for (param,value) in defParamVals do
        match context.ActionArguments.TryGetValue(param.Name) with
        | true,:? System.Reflection.Missing
        | false,_ ->
          // Remove is null-op if key not found,so we handle both match cases OK.
          let _ = context.ActionArguments.Remove(param.Name)
          context.ActionArguments.Add(param.Name,value)
        | _,_ -> ()
    | _ -> ()
  /// Override adding suport for DefaultParameterValueAttribute values.
  override x.OnActionExecuting(context) =
    addActionArgDefsFromDefParamValAttrs context
    base.OnActionExecuting(context)
  /// Override adding suport for DefaultParameterValueAttribute values.
  override x.OnActionExecutingAsync(context,cancellationToken) =
    addActionArgDefsFromDefParamValAttrs context
    base.OnActionExecutingAsync(context,cancellationToken)

相关文章

vue阻止冒泡事件 阻止点击事件的执行 &lt;div @click=&a...
尝试过使用网友说的API接口获取 找到的都是失效了 暂时就使用...
后台我拿的数据是这样的格式: [ {id:1 , parentId: 0, name:...
JAVA下载文件防重复点击,防止多次下载请求,Cookie方式快速简...
Mip是什么意思以及作用有哪些