7

我已经配置了 Web API 帮助页面文档。

我有下面的类,它将在其他模型类中继承。

public class ResponseBase
{
    public string ErrorReason { get; set; }
    [IgnoreDataMember]
    public bool IsRejected { get; set; }
}

我不希望 IsRejected 被序列化并作为响应可用,因此我使用 IgnoreDataMember 属性对其进行了修饰。

继承 ResponseBase 的模型类示例。

public class Reading : ResponseBase
{
    //Other properties
}

我在我的 Web API 控制器中有以下方法:

[HttpPost]
[ValidationResponseFilter]
[Route("")]
[ResponseType(typeof(Reading))]
public IHttpActionResult Add(List<Reading> readingList)
{
    //Logic here
}

现在对于读取对象列表的请求参数的文档,它将列出读取的所有属性以及 ResponseBase 类(继承)。我希望帮助页面文档将 ErrorReason 列为仅响应中的参数之一。

[ApiExplorerSettings(IgnoreApi = true)]除了在 ErrorReason 上设置属性之外,我还能做任何配置吗?如果我这样做,ErrorReason 在请求和响应参数中都将不可用。我只想在响应参数列表中显示它。

4

2 回答 2

0

通常,最佳实践是创建一个与您想要接受的完全匹配的自定义对象。其原因之一是安全性。请参阅“过度发布”和“发布不足”:http : //www.asp.net/web-api/overview/formats-and-model-binding/model-validation-in-aspnet-web-api这样您将创建一个仅包含您需要的属性的新对象。

public class ResponseBaseVM
    {
        public string ErrorReason { get; set; }
        /*public bool IsRejected { get; set; }*/ 
    }
public class ReadingVM : ResponseBaseVM
    {
        //Other properties that you only want available to user
    }

然后你会接受 ReadingVM 的列表,但响应类型仍然是 typeof(reading)

[HttpPost]
[ValidationResponseFilter]
[Route("")]
[ResponseType(typeof(List<Reading>))] //will still display response with IsRejected
public IHttpActionResult Add(List<ReadingVM> readingListVM)
{
    //Logic here
}

--- 解决方法 ---

同样,我认为您应该遵循上述方法。您要求解决问题,就在这里。在 HelpPageConfigurationExtensions.cs 类中找到您的“GenerateApiModel”方法并将其替换为:

private static HelpPageApiModel GenerateApiModel(ApiDescription apiDescription, HttpConfiguration config)
{
    HelpPageApiModel apiModel = new HelpPageApiModel()
    {
        ApiDescription = apiDescription,
    };

    ModelDescriptionGenerator modelGenerator = config.GetModelDescriptionGenerator();
    HelpPageSampleGenerator sampleGenerator = config.GetHelpPageSampleGenerator();
    GenerateUriParameters(apiModel, modelGenerator);
    GenerateRequestModelDescription(apiModel, modelGenerator, sampleGenerator);
    GenerateResourceDescription(apiModel, modelGenerator);
    GenerateSamples(apiModel, sampleGenerator);

    //This will remove request body parameters from your Api Help Page matching 'IsRejected'
    var isRejectedParameter = apiModel.RequestBodyParameters.SingleOrDefault(x => x.Name == "IsRejected");
    if (isRejectedParameter != null)
        apiModel.RequestBodyParameters.Remove(isRejectedParameter);

    //This will remove elements with 'IsRejected' for the Help Page sample requests 
    var sampleRequests = new Dictionary<MediaTypeHeaderValue, object>();
    foreach (var kvp in apiModel.SampleRequests)
    {
        //1.) iterate through each object in SampleRequests dictionary.
        //2.) modify the json or xml to remove the "IsRejected" elements
        //3.) assign modified results to a new dictionary
        //4.) change the HelpPageApiModel. SampleRequests setter to be not private
        //5.) assign new dictionary to HelpPageApiModel.SampleRequests
        if (Equals(kvp.Key, new MediaTypeHeaderValue("application/json")))
        {
            var jObject = JObject.Parse(kvp.Value.ToString());
            jObject.Remove("IsRejected");
            sampleRequests.Add(new MediaTypeHeaderValue("application/Json"), jObject.ToString());
        }
        else if(Equals(kvp.Key, new MediaTypeHeaderValue("text/json")))
        {
            //do stuff
        }
        else if (Equals(kvp.Key, new MediaTypeHeaderValue("application/xml")))
        {
            //do stuff
        }
        else if (Equals(kvp.Key, new MediaTypeHeaderValue("text/xml")))
        {
            //do stuff
        }
        else
        {
            //form urlencoded or others
            sampleRequests.Add(kvp.Key,kvp.Value);
        }
    }
    apiModel.SampleRequests = sampleRequests;

    return apiModel;
}

现在您可以看到“IsRejected”存在于响应中,但不存在于请求中。 请求帮助页面覆盖

于 2016-02-27T16:49:25.833 回答
0

我建议您使用 HTTP 状态代码作为传达成功或失败的一种方式,例如它们的意图,除非您出于特定原因想要将错误作为 HTTP 状态代码 200(OK)返回。

处理这种情况的一般方法是在一切正常时返回 2xx 状态码,在发生错误时返回 4xx 或 5xx 状态码。通过这种方式,客户可以清楚地区分错误情况和成功操作。

可以在Exception Not Found -blog 上找到关于错误处理主题的一篇很好的博客文章,从中获取了控制器操作的这个很好的示例:

[Route("CheckId/{id}")]
[HttpGet]
public IHttpActionResult CheckId(int id)  
{
    if (id > 100)
    {
        var message = new HttpResponseMessage(HttpStatusCode.BadRequest)
        {
            Content = new StringContent("We cannot use IDs greater than 100.")
        };
        throw new HttpResponseException(message);
    }
    return Ok(id);
}
于 2016-09-05T10:10:26.677 回答