2017-02-13 8 views
2

Поскольку заголовок указывает на все, что я пытаюсь сделать, это возвращать пользовательскую коллекцию ошибок, если «Модель» является неполной.Возврат списка ошибок с помощью BadRequest (WebApi)

В то время как активно «SO'ing/Googling» я не нашел решения, которые помогут решить мою проблему.

Я мог бы использовать «ModelState», но из-за «настройки» я хотел бы сделать это вручную.

код следующим образом:

API Level

// 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 (ошибка объекта), так как ошибка на самом деле является списком