加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net-web-api – 自定义模型Binder不从Swagger UI调用

发布时间:2020-12-16 09:43:48 所属栏目:asp.Net 来源:网络整理
导读:我在我的WebApi项目中使用.Net framework 4.6.1和Swashbuckle 5.3.2版. Swagger UI没有提供将输入作为请求主体发送到使用自定义模型绑定器的POST Api的选项. – 使用的型号: [ModelBinder(typeof(FieldValueModelBinder))] public class Employee { public
我在我的WebApi项目中使用.Net framework 4.6.1和Swashbuckle 5.3.2版. Swagger UI没有提供将输入作为请求主体发送到使用自定义模型绑定器的POST Api的选项.

– 使用的型号:

[ModelBinder(typeof(FieldValueModelBinder))]
    public class Employee
    {
        public int EmployeeID { get; set; }
        public string EmployeeName { get; set; }
        public string City { get; set; }
    }

– 使用的API Post方法:

[HttpPost]
    // POST: api/Employee
    public HttpResponseMessage Post([ModelBinder(typeof(FieldValueModelBinder))]Employee emp)
    {
        if (!ModelState.IsValid)
            return Request.CreateResponse(HttpStatusCode.BadRequest,"Please provide valid input");
        else
            //Add Employee logic here
            return Request.CreateResponse(HttpStatusCode.OK,"Employee added sucessfully");
    }

– 使用的型号粘合剂:

public class FieldValueModelBinder : System.Web.Http.ModelBinding.IModelBinder
{
    /// <summary>
    /// Store received data in API in KeyValuePair
    /// </summary>
    private List<KeyValuePair<string,string>> kvps;

    /// <summary>
    /// Storing error while binding data in Model class
    /// </summary>
    private Dictionary<string,string> dictionaryErrors = new Dictionary<string,string>();

    /// <summary>
    /// Implementing Base method and binding received data in API to its respected property in Model class
    /// </summary>
    /// <param name="actionContext">Http Action Context</param>
    /// <param name="bindingContext">Model Binding Context</param>
    /// <returns>True if no error while binding. False if any error occurs during model binding</returns>
    public bool BindModel(HttpActionContext actionContext,System.Web.Http.ModelBinding.ModelBindingContext bindingContext)
    {
        try
        {
            var bodyString = actionContext.Request.Content.ReadAsStringAsync().Result;
            if (actionContext.Request.Method.Method.ToUpper().Equals("GET"))
            {
                var uriContext = HttpUtility.ParseQueryString(actionContext.Request.RequestUri.Query);
                if (uriContext.HasKeys())
                {
                    this.kvps = uriContext.AllKeys.ToDictionary(k => k,k => uriContext[k]).ToList<KeyValuePair<string,string>>();
                }
            }
            else if (!string.IsNullOrEmpty(bodyString))
            {
                this.kvps = this.ConvertToKvps(bodyString);
            }
            else
            {
                bindingContext.ModelState.AddModelError(bindingContext.ModelName,"Please provide valid input data.");
                return false;
            }
        }
        catch (Exception ex)
        {
            bindingContext.ModelState.AddModelError(bindingContext.ModelName,"Please provide data in a valid format.");
            return false;
        }

        // Initiate primary object
        var obj = Activator.CreateInstance(bindingContext.ModelType);
        try
        {
            this.SetPropertyValues(obj);
        }
        catch (Exception ex)
        {
            if (this.dictionaryErrors.Any())
            {
                foreach (KeyValuePair<string,string> keyValuePair in this.dictionaryErrors)
                {
                    bindingContext.ModelState.AddModelError(keyValuePair.Key,keyValuePair.Value);
                }
            }
            else
            {
                bindingContext.ModelState.AddModelError("Internal Error",ex.Message);
            }

            this.dictionaryErrors.Clear();
            return false;
        }

        // Assign completed Mapped object to Model
        bindingContext.Model = obj;
        return true;
    }

我面临以下问题:

>当我们在post方法中使用’ModelBinder’时,Swagger UI就是
显示此屏幕,其中输入参数在a中发布
查询字符串和CustomModelBinder被调用并尝试读取
请求正文执行模型绑定和验证并获取null
这个案例.

Public HttpResponseMessage Post([ModelBinder(typeof(FieldValueModelBinder))] Employee emp)

See Image Swagger UI with ModelBinder


>当我们在post方法中使用’FromBody’时,Swagger UI会显示此信息
屏幕,我们可以在请求正文中发送输入,但在此
case调用CustomModelBinder并且我们无法执行
模型绑定和验证.

public HttpResponseMessage Post([FromBody] Employee emp)

See Image Swagger UI with FromBody


>当我们尝试使用’modelbinder’和’frombody’时,Swagger UI需要
输入作为查询,我们得到以下响应:

See Image Swagger UI with ModelBinder and FromBody both

尝试使用Postman,API工作正常,我们能够在请求体中传递输入并获得正确的输出.在模型状态无效的情况下,自定义模型绑定也可以工作并填充错误消息,然后我们可以使用这些消息在响应中发送.

See Image Api call from Postman

See Image ModelState Error

需要更改什么以在将输入数据发布到请求正文中的API时从Swagger UI调用自定义模型绑定器.请建议.

解决方法

您可以使用IDocumentFilter执行此操作,这里是代码:

private class ApplyDocumentVendorExtensions : IDocumentFilter
{
    public void Apply(SwaggerDocument swaggerDoc,SchemaRegistry s,IApiExplorer a)
    {
        if (swaggerDoc != null)
        {
            foreach (var path in swaggerDoc.paths)
            {
                if (path.Value.post != null && path.Value.post.parameters != null )
                {
                    var parameters = path.Value.post.parameters;
                    if (parameters.Count == 3 && parameters[0].name.StartsWith("emp"))
                    {
                        path.Value.post.parameters = EmployeeBodyParam;
                    }
                }
            }
        }
    }

    private IList<Parameter> EmployeeBodyParam
    {
        get
        {
            return new List<Parameter>
            {
                new Parameter {
                    name = "emp",@in = "body",required = true,schema = new Schema {
                        @ref = "#/definitions/Employee"
                    }
                }
            };
        }
    }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读