将 Web API 2 的查询字符串绑定到 .NET 4.8 中的 JSON 属性

问题描述 投票:0回答:2

我在 Web API 端点上有以下类和操作。我希望查询字符串

sid
绑定到属性
SportId
,就像 JSON.NET 序列化一样。
SportId
可以很好地用作带有
FromUri
的查询字符串。是否有某种类型的活页夹我可以使用 .NET 4.8 来完成此操作。

public class AppApplicationRequest : AppRequest
    {
        [JsonProperty(PropertyName = "sid")]
        public SportType? SportId { get; set; }

    }


public virtual async Task<AppApplicationResponse> Get([FromUri] AppApplicationRequest request)
{
    return await _appApplicationsService.GetApplication(request);
}
asp.net-mvc asp.net-web-api asp.net-web-api2 model-binding webapi
2个回答
0
投票

这是有关如何完成自定义模型绑定程序的一般指南。

以下是如何为 AppApplicationRequest 类创建自定义模型绑定程序的简单示例:

using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http.ModelBinding;
using Newtonsoft.Json;

public class AppApplicationRequestBinder : IModelBinder
{
    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType != typeof(AppApplicationRequest))
        {
            return false;
        }

        var queryString = actionContext.Request.RequestUri.ParseQueryString();
        var appApplicationRequest = new AppApplicationRequest();

        if (queryString["sid"] != null)
        {
            if (Enum.TryParse(typeof(SportType), queryString["sid"], out object parsedSportType))
            {
                appApplicationRequest.SportId = (SportType)parsedSportType;
            }
        }

        // Add more fields if needed

        bindingContext.Model = appApplicationRequest;
        return true;
    }
}

接下来,注册您的自定义活页夹!这将类似于

WebApiConfig.cs

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // ... Other configurations

        config.BindParameter(typeof(AppApplicationRequest), new AppApplicationRequestBinder());
    }
}

现在您可以注释您想要完成的操作,如下所示:

public virtual async Task<AppApplicationResponse> Get([ModelBinder(typeof(AppApplicationRequestBinder))] AppApplicationRequest request)
{
    return await _appApplicationsService.GetApplication(request);
}

再次强调,这是笼统的,因为您没有在问题中提供太多具体信息,但我希望这有助于您找到正确的方向。如果您在评论中还有后续问题,请告诉我,我会尽力回答,祝您好运


0
投票

我认为将

[ModelBinder]
属性与自定义模型绑定器结合使用会更好,因此首先尝试创建一个实现
IModelBinder
接口的自定义模型绑定器,并在
BindModel
方法中,您可以访问查询字符串参数并将它们绑定到
AppApplicationRequest
类的适当属性。

public class AppApplicationRequestModelBinder : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        var request = (AppApplicationRequest)bindingContext.Model;

        //get the value of the 'sid' query string parameter
        var sidValue = bindingContext.ValueProvider.GetValue("sid").FirstValue;

        //converting the 'sid' value to the appropriate enum type
        if (Enum.TryParse(sidValue, out SportType sportId))
        {
            request.SportId = sportId;
        }

        bindingContext.Result = ModelBindingResult.Success(request);
        return Task.CompletedTask;
    }
}

现在尝试将

[ModelBinder]
属性应用于
AppApplicationRequest
操作方法中的
Get
参数,指定自定义模型绑定器

public virtual async Task<AppApplicationResponse> Get([ModelBinder(typeof(AppApplicationRequestModelBinder))] AppApplicationRequest request)
{
    return await _appApplicationsService.GetApplication(request);
}

或者您可以使用另一个自定义模型绑定器,该绑定器是使用 ASP.NET Web API 2 的

IModelBinder
命名空间中的
System.Web.Http.ModelBinding
接口实现的!

using System;
using System.Threading.Tasks;
using System.Web.Http.Controllers;
using System.Web.Http.ModelBinding;

public class AppApplicationRequestModelBinder : IModelBinder
{
    public Task BindModelAsync(HttpActionContext actionContext, ModelBindingContext bindingContext)
    {
        var request = (AppApplicationRequest)bindingContext.Model;

        //get the value of the 'sid' query string parameter
        var sidValue = bindingContext.ValueProvider.GetValue("sid").RawValue.ToString();

        //converting the 'sid' value to the appropriate enum type
        if (Enum.TryParse(sidValue, out SportType sportId))
        {
            request.SportId = sportId;
        }

        bindingContext.Result = ModelBindingResult.Success(request);
        return Task.CompletedTask;
    }
}

public class AppApplicationRequest : AppRequest
{
    public SportType? SportId { get; set; }
}

public virtual async Task<AppApplicationResponse> Get([ModelBinder(typeof(AppApplicationRequestModelBinder))] AppApplicationRequest request)
{
    return await _appApplicationsService.GetApplication(request);
}

更新

好的,要将查询字符串参数动态绑定到模型,您可以创建适用于任何模型的通用模型绑定器。

看看这个:

public class QueryStringModelBinder<T> : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        var model = Activator.CreateInstance<T>();

        foreach (var property in typeof(T).GetProperties())
        {
            var valueProviderResult = bindingContext.ValueProvider.GetValue(property.Name);
            if (valueProviderResult != null)
            {
                var value = valueProviderResult.FirstValue;
                var convertedValue = Convert.ChangeType(value, property.PropertyType);
                property.SetValue(model, convertedValue);
            }
        }

        bindingContext.Result = ModelBindingResult.Success(model);
        return Task.CompletedTask;
    }
}

有了这个,您可以通过将

[ModelBinder]
属性应用于操作方法中的模型参数,将查询字符串参数绑定到任何模型,因此您不需要为每个模型创建单独的模型绑定器!!!

public virtual async Task<AppApplicationResponse> Get([ModelBinder(typeof(QueryStringModelBinder<AppApplicationRequest>))] AppApplicationRequest request)
{
    return await _appApplicationsService.GetApplication(request);
}
© www.soinside.com 2019 - 2024. All rights reserved.