2017-02-13 97 views
2

正如标题所示,我试图做的就是返回错误的自定义集合,如果“模型”不完整。使用BadRequest返回错误列表(WebApi)

虽然积极“SO /ing /谷歌搜索”,我还没有找到解决方案来帮助我的问题。

我可以使用“模型状态”,但由于“自定义”,我想这样做手动。

代码如下:

API级别

// POST api/<controller> 
[HttpPost] 
[Route("")] 
public async Task<IHttpActionResult> Post([FromBody]Order order) 
{ 
    var modelResponse = new ModelResponse<Order>(order); 
    if (order == null) 
     return BadRequest("Unusable resource, object instance required."); 

    //Check if all required properties contain values, if not, return response 
    //with the details 
    if (!modelResponse.IsModelValid()) 
     return this.PropertiesRequired(modelResponse.ModelErrors()); 

    try 
    { 
     await _orderService.AddAsync(order); 
    } 
    catch (System.Exception ex) 
    { 
     return InternalServerError(); 
    } 
    finally 
    { 
     _orderService.Dispose(); 
    } 

    return Ok("Order Successfully Processed."); 
} 

性能所要求的操作结果

public List<string> Messages { get; private set; } 
public HttpRequestMessage Request { get; private set; } 

public PropertiesRequiredActionResult(List<string> message, 
    HttpRequestMessage request) 
{ 
    this.Messages = message; 
    this.Request = request; 
} 
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) 
{ 
    return Task.FromResult(Execute()); 
} 

public HttpResponseMessage Execute() 
{ 
    HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.BadRequest); 
    response.Content = new ObjectContent() 
     //new List<StringContent>(Messages); //Stuck here 
    response.RequestMessage = Request; 
    return response; 
} 

发现不完整的特性,基于自定义属性

private T _obj; 

public ModelResponse(T obj) 
{ 
    _obj = obj; 
} 

private Dictionary<string, object> GetPropertyAttributes(PropertyInfo property) 
{ 
    Dictionary<string, object> attribs = new Dictionary<string, object>(); 
    // look for attributes that takes one constructor argument 
    foreach (CustomAttributeData attribData in property.GetCustomAttributesData()) 
    { 

     if (attribData.ConstructorArguments.Count == 1) 
     { 
      string typeName = attribData.Constructor.DeclaringType.Name; 
      if (typeName.EndsWith("Attribute")) typeName = typeName.Substring(0, typeName.Length - 9); 
      attribs[typeName] = attribData.ConstructorArguments[0].Value; 
     } 

    } 
    return attribs; 
} 
private IEnumerable<PropertyInfo> GetProperties() 
{ 
    var props = typeof(T).GetProperties().Where(
      prop => Attribute.IsDefined(prop, typeof(APIAttribute))); 

    return props; 
} 
public bool IsModelValid() 
{ 
    var props = GetProperties(); 
    return props.Any(p => p != null); 
} 
public List<string> ModelErrors() 
{ 
     List<string> errors = new List<string>(); 
     foreach (var p in GetProperties()) 
     { 

      object propertyValue = _obj.GetType() 
       .GetProperty(p.Name).GetValue(_obj, null); 

      if (propertyValue == null) 
      { 
       errors.Add(p.Name + " - " + GetPropertyAttributes(p).FirstOrDefault()); 
      } 
     } 
     return errors; 
} 

属性

/// <summary> 
/// The date and time when the order was created. 
/// </summary> 
[API(Required = "Order Created At Required")] 
public DateTime Order_Created_At { get; set; } 

所以忽略了后两个片段的样品,这是更给全过程的概述。我完全理解有一些“开箱即用”的技术,但我喜欢制作自己的实现。

要点,是否有可能返回错误列表与“BadRequest”?

非常感谢。

回答

0

在您的自定义实施IHttpActionResult中,使用请求来创建响应并传递模型和状态码。

public List<string> Messages { get; private set; } 
public HttpRequestMessage Request { get; private set; } 

public HttpResponseMessage Execute() { 
    var response = Request.CreateResponse(HttpStatusCode.BadRequest, Messages); 
    return response; 
} 
+0

绝对地点,谢谢。这也将允许我传递一个状态码,从而保持它的通用性。 –

0

你可能寻找使用这种方法:

BadRequestObjectResult BadRequest(ModelStateDictionary modelState) 

它的用法是这样的,这个例子从another question here in SO

if (!ModelState.IsValid) 
    return BadRequest(ModelState); 

根据模型的错误,你得到这个结果:

{ 
    Message: "The request is invalid." 
    ModelState: { 
     model.PropertyA: [ 
      "The PropertyA field is required." 
     ], 
     model.PropertyB: [ 
      "The PropertyB field is required." 
     ] 
    } 
} 

希望它有帮助

+0

嗨,谢谢。虽然这是正确的答案,任何未来的读者都应该使用这种方法。我期待构建自己的实现。因此,不使用模型状态......除了返回错误的“列表”之外,所有工作都是如此。感谢您的时间。 –

+0

比你可能想要使用BadRequestObjectResult BadRequest(对象错误),因为错误实际上是列表