Swashbuckle生成的Swagger有错误

时间:2017-02-06 20:15:24

标签: c# asp.net rest swagger swashbuckle

我正在测试Swashbuckle nuget包针对http://editor.swagger.io/生成的swagger元数据,并在元数据中包含以下部分:

     "/User":{
     "get":{
              <snip>
     }
     "post":{
        "tags":[
           "User"
        ],
        "summary":"Create a new user, adds them to a space and sets dashboard view.",
        "operationId":"User_Post",
        "consumes":[
           "application/json",
           "text/json"
        ],
        "produces":[

        ],
        "parameters":[ // This line is marked as an error.
           {
              "name":"user",
              "in":"body",
              "description":"New user's username and assigned space.",
              "required":true,
              "schema":{
                 "$ref":"#/definitions/F1.Birst.CreateUserRequest"
              }
           },
           {
              "name":"Authorization",
              "in":"header",
              "description":"access token",
              "required":true,
              "type":"string"
           }
        ],
        "responses":{
           "204":{
              "description":"No Content"
           }
        },
        "deprecated":false
     }
  },

报告的错误是:

Swagger Error
Not a valid parameter definition
Jump to line 330
Details
 Object
code:  "ONE_OF_MISSING"
 params: Array [0]
message:  "Not a valid parameter definition"
 path: Array [5]
schemaId:  "http://swagger.io/v2/schema.json#"
 inner: Array [2]
level: 900
type:  "Swagger Error"
description:  "Not a valid parameter definition"
lineNumber: 330

代码生成似乎仍然可以使用NSwag而没有问题。这是Swagger编辑的问题,Swasbuckle的问题,为什么NSwag能够毫无问题地处理这个问题?

其他swagger代码生成器会出现问题吗?

如果Swagger Editor或Swashbuckle不是问题,我将如何在我的代码中修复此问题?目前的定义如下:

    /// <summary>
    /// Create a new user, adds them to a space and sets dashboard view.
    /// </summary>
    /// <param name="user">New user's username and assigned space.</param>
    public void Post([FromBody] CreateUserRequest user)

我已经尝试了

    /// <summary>
    /// Create a new user, adds them to a space and sets dashboard view.
    /// </summary>
    /// <param name="user">New user's username and assigned space.</param>
    public void Post([FromBody][ModelBinder] CreateUserRequest user)

但最终将变量放入查询字符串中。

修改

这是CreateUserRequest的定义。验证器正在为正则表达式抛出错误(这是有效的C#正则表达式)。我假设这是由于验证器使用JS正则表达式语法?

这是&#34;不是有效参数定义的基本原因&#34;?如果是这样,那么我认为它只是另一个错误的副本。在正则表达式中显示正则表达式错误,以及在将类作为参数引用时出现另一个错误?

  "F1.Birst.CreateUserRequest":{
     "required":[
        "username",
        "space"
     ],
     "type":"object",
     "properties":{
        "username":{
           "pattern":"(?i:^f1(\\.(test|churchstaff|churchuser|internal))?\\.\\d+\\.\\d+$)",
           "type":"string"
        },
        "space":{
           "pattern":"(?i:^f1\\.[\\d\\w]+$)",
           "type":"string"
        }
     }
  },

班级定义:

public class CreateUserRequest
{
    [Required]
    [RegularExpression(@"(?i:^f1(\.(test|churchstaff|churchuser|internal))?\.\d+\.\d+$)")]
    public string Username { get; set; }

    [Required]
    [RegularExpression(@"(?i:^f1\.[\d\w]+$)")]
    public string Space { get; set; }
}

1 个答案:

答案 0 :(得分:0)

我能够通过创建一个接受options参数的RegularExpressionAttribute版本,并从正则表达式中删除不区分大小写的命名组来解决此问题。

属性定义

/// <summary>
/// Regular expression validation attribute with ability to specify options.
/// </summary>
/// <remarks>Swagger schema validation fails if you use the (?i:) named group for case insensitive regexes.</remarks>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter)]
public class RegularExpressionWithOptionsAttribute : RegularExpressionAttribute
{
    private Regex Regex { get; set; }
    private RegexOptions Options { get; }

    /// <summary>
    /// Constructor that accepts the regular expression pattern
    /// </summary>
    /// <param name="pattern">The regular expression to use.  It cannot be null.</param>
    /// <param name="options">The options to use for the regular expression.</param>
    public RegularExpressionWithOptionsAttribute(string pattern, RegexOptions options)
        : base(pattern)
    {
        Options = options;
    }

    /// <summary>
    /// Override of <see cref="ValidationAttribute.IsValid(object)"/>
    /// </summary>
    /// <remarks>This override performs the specific regular expression matching of the given <paramref name="value"/></remarks>
    /// <param name="value">The value to test for validity.</param>
    /// <returns><c>true</c> if the given value matches the current regular expression pattern</returns>
    /// <exception cref="InvalidOperationException"> is thrown if the current attribute is ill-formed.</exception>
    /// <exception cref="ArgumentException"> is thrown if the <see cref="Pattern"/> is not a valid regular expression.</exception>
    public override bool IsValid(object value)
    {
        SetupRegex();

        // Convert the value to a string
        var stringValue = Convert.ToString(value, CultureInfo.CurrentCulture);

        // Automatically pass if value is null or empty. RequiredAttribute should be used to assert a value is not empty.
        if (string.IsNullOrEmpty(stringValue))
        {
            return true;
        }

        var match = Regex.Match(stringValue);

        // We are looking for an exact match, not just a search hit. This matches what
        // the RegularExpressionValidator control does
        return (match.Success && match.Index == 0 && match.Length == stringValue.Length);
    }

    /// <summary>
    /// Sets up the <see cref="Regex"/> property from the <see cref="Pattern"/> property.
    /// </summary>
    /// <exception cref="ArgumentException"> is thrown if the current <see cref="Pattern"/> cannot be parsed</exception>
    /// <exception cref="InvalidOperationException"> is thrown if the current attribute is ill-formed.</exception>
    /// <exception cref="ArgumentOutOfRangeException"> thrown if <see cref="MatchTimeoutInMilliseconds" /> is negative (except -1),
    /// zero or greater than approximately 24 days </exception>
    private void SetupRegex()
    {
        if (Regex != null)
            return;

        // Ensure base.SetupRegex is called, to check for empty pattern and setup timeout.
        base.IsValid(null);

        Regex = MatchTimeoutInMilliseconds == -1
            ? new Regex(Pattern, Options)
            : Regex = new Regex(Pattern, Options, TimeSpan.FromMilliseconds(MatchTimeoutInMilliseconds));
    }
}

<强>用法

public class CreateUserRequest
{
    [Required]
    [RegularExpressionWithOptions(@"^f1(\.(test|churchstaff|churchuser|internal))?\.\d+\.\d+$", RegexOptions.IgnoreCase)]
    public string Username { get; set; }
    [Required]
    //[RegularExpressionWithOptions(@"^f1\.[\d\w]+$", RegexOptions.IgnoreCase)]
    public string Space { get; set; }
}