Настраиваемый связыватель модели не вызывается из пользовательского интерфейса Swagger

Я использую .Net framework 4.6.1 и Swashbuckle версии 5.3.2 в своем проекте WebApi. Пользовательский интерфейс Swagger не дает возможности отправлять ввод в качестве тела запроса в мой 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;
    }

Я столкнулся с проблемами ниже:

  • Когда мы используем «ModelBinder» в нашем методе публикации, пользовательский интерфейс Swagger отображает этот экран, где входной параметр публикуется в строке запроса и вызывается CustomModelBinder, который пытается прочитать тело запроса для выполнения привязки и проверки модели и в этом случае получает значение null.

    Общедоступное сообщение HttpResponseMessage ([ModelBinder (typeof (FieldValueModelBinder))] Employee emp)

    «См.

  • Когда мы используем FromBody в нашем методе публикации, пользовательский интерфейс Swagger отображает этот
    экран, на котором мы можем отправить ввод в теле запроса, но в этом случае CustomModelBinder не вызывается, и мы не можем выполнять привязку модели и Проверка.

    общедоступное сообщение HttpResponseMessage ([FromBody] Employee emp)

    См. Интерфейс Image Swagger с помощью FromBody

  • Когда мы пытаемся использовать как «modelbinder», так и «frombody», пользовательский интерфейс Swagger принимает ввод как запрос, и мы получаем следующий ответ:

    См. Пользовательский интерфейс Image Swagger с помощью ModelBinder и FromBody

Пробовал с Postman, API работает нормально, и мы можем передать ввод в теле запроса и получить правильный результат. Привязка пользовательской модели также работает и заполняет сообщение об ошибке в случае недопустимого состояния модели, и затем мы можем использовать эти сообщения для отправки в ответ.

См. Вызов API изображения от почтальона

«См.

Что необходимо изменить, чтобы вызвать привязку пользовательской модели из пользовательского интерфейса Swagger при отправке входных данных в API в теле запроса. Пожалуйста, предложите.


person Nidhi Sonar    schedule 25.01.2018    source источник
comment
Можете ли вы добавить swagger.json, созданный вашим Api?   -  person Helder Sepulveda    schedule 25.01.2018
comment
Пожалуйста, найдите файл swagger json:   -  person Nidhi Sonar    schedule 29.01.2018
comment
github.com/nidhisonar/WebApplication2/blob/master/Swagger.Json   -  person Nidhi Sonar    schedule 29.01.2018
comment
Подробнее см. Мой PullRequest на Github ...   -  person Helder Sepulveda    schedule 29.01.2018


Ответы (1)


Вы можете сделать это с помощью 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"
                    }
                }
            };
        }
    }
}
person Helder Sepulveda    schedule 29.01.2018