WebApi - Bind from both Uri and Body

前端 未结 4 1540
小鲜肉
小鲜肉 2020-12-13 12:51

Is it possible to bind a model from both the Uri and Body?

For instance, given the following:

routes.MapHttpRoute(
    name: \"API Default\",
    rou         


        
4条回答
  •  庸人自扰
    2020-12-13 13:23

    Here's an improved version of odyth's answer that:

    1. Works for bodiless requests too, and
    2. Gets parameters from the query string in addition to from route values.

    For brevity I just post the ExecuteBindingAsyncCore method and a new auxiliary method, the rest of the class is the same.

    private async Task ExecuteBindingAsyncCore(ModelMetadataProvider metadataProvider, HttpActionContext actionContext,
            HttpParameterDescriptor paramFromBody, Type type, HttpRequestMessage request, IFormatterLogger formatterLogger,
            CancellationToken cancellationToken)
    {
        var model = await ReadContentAsync(request, type, Formatters, formatterLogger, cancellationToken);
    
        if(model == null) model = Activator.CreateInstance(type);
    
        var routeDataValues = actionContext.ControllerContext.RouteData.Values;
        var routeParams = routeDataValues.Except(routeDataValues.Where(v => v.Key == "controller"));
        var queryStringParams = new Dictionary(QueryStringValues(request));
        var allUriParams = routeParams.Union(queryStringParams).ToDictionary(pair => pair.Key, pair => pair.Value);
    
        foreach(var key in allUriParams.Keys) {
            var prop = type.GetProperty(key, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public);
            if(prop == null) {
                continue;
            }
            var descriptor = TypeDescriptor.GetConverter(prop.PropertyType);
            if(descriptor.CanConvertFrom(typeof(string))) {
                prop.SetValue(model, descriptor.ConvertFromString(allUriParams[key] as string));
            }
        }
    
        // Set the merged model in the context
        SetValue(actionContext, model);
    
        if(BodyModelValidator != null) {
            BodyModelValidator.Validate(model, type, metadataProvider, actionContext, paramFromBody.ParameterName);
        }
    }
    
    private static IDictionary QueryStringValues(HttpRequestMessage request)
    {
        var queryString = string.Join(string.Empty, request.RequestUri.ToString().Split('?').Skip(1));
        var queryStringValues = System.Web.HttpUtility.ParseQueryString(queryString);
        return queryStringValues.Cast().ToDictionary(x => x, x => (object)queryStringValues[x]);
    }
    

提交回复
热议问题