Я хотел бы обернуть IHttpActionResult, потому что мне нужны дополнительные данные, которые будут использоваться клиентским приложением.
Мой первый подход состоял в том, чтобы создать и вернуть простой DTO, обернув объект результата в случае успеха:
Ответ DTO:
public class Response<T>
{
public string ErrorMessage { get; set; }
public bool Success { get; set; }
public string CodeStatus { get; set; }
public T Result { get; set; }
public Response(bool isSuccess, [Optional] T result, [Optional] string codeStatus, [Optional] string errorMessage)
{
Success = isSuccess;
Result = result;
CodeStatus = codeStatus;
ErrorMessage = errorMessage;
}
}
Контроллер:
public IHttpActionResult Get(int id)
{
return BadRequest(new Response<MyObjectClass>(false, null,"Invalid Id",400));
...
return Ok(new Response<MyObjectClass>(true, result);
}
Я нашел это очень неэффективным способом борьбы с обертыванием. Я не нахожу это очень элегантным способом. Я попытался найти какое-то общее решение и в итоге получил следующее:
Пример действия контроллера:
public IHttpActionResult GetById(int id)
{
var result = _someService.Get(id);
if (result == null)
return NotFound().WithError("Invalid Id");
return Ok().WithSuccess(result);
}
Это по-прежнему возвращает Response DTO.
Я завернул IHttpActionResult для создания Response DTO:
public class HttpActionResult : IHttpActionResult
{
private readonly string _errorMessage;
private readonly IHttpActionResult _innerResult;
private readonly object _result;
private readonly bool _isSuccess;
public HttpActionResult(IHttpActionResult inner, bool isSuccess, object result,string errorMessage)
{
_errorMessage = errorMessage;
_innerResult = inner;
_result = result;
_isSuccess = isSuccess;
}
public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
HttpResponseMessage response = await _innerResult.ExecuteAsync(cancellationToken);
response.Content = new ObjectContent(typeof(Response), new Response(_isSuccess, _result, ((int)response.StatusCode).ToString(), _errorMessage), new JsonMediaTypeFormatter());
return response;
}
}
Наконец, я добавил методы расширения в IHttpActionResult, чтобы их было проще использовать в контроллере:
public static class IHttpActionResultExtensions
{
public static IHttpActionResult WithSuccess(this IHttpActionResult inner, object result = null, string message = null)
{
return new HttpActionResult(inner, true, result, message);
}
public static IHttpActionResult WithError(this IHttpActionResult inner, string message = null)
{
return new HttpActionResult(inner, false,null, message);
}
}
Каковы альтернативы переносу http-сообщений в контроллер API? Какие слабые места вы видите в моем решении?
ModelState
, что я не учел в этом сценарии. Я использовал его только для проверки. 21.12.2016ModelState
, но вы можете использовать ее не только для сообщения об ошибках. 21.12.2016