2017-02-13 51 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(對象錯誤),因爲錯誤實際上是列表