WebApi2 IHttpActionResult strongly typed return values

后端 未结 4 1426
借酒劲吻你
借酒劲吻你 2021-01-18 16:10

It is possible and not ideal to do this: (a vastly simplified example!)

[Serializable]
public class MyRecord
{
    public string key {get; set;}
    public          


        
相关标签:
4条回答
  • 2021-01-18 16:21

    You can refactor your code this way:

    public class Answer<T>
    {
        public T result {get;set;}
        public bool success {get;set;}
        public string exception {get;set;}
    }
    
    public async Task<Answer<MyRecord>> Get(string SomeKey)
    {
        var answer = new Answer<MyRecord>();
        try
        {     
            if(ExistsInDB(SomeKey))
            {
                answer.result = await SomeRecordFromDB(SomeKey);
                answer.success = true;
            }
        }
        catch(Exception e)
        {
            answer.exception = e.Message;            
        }
        return answer;
    }
    
    0 讨论(0)
  • 2021-01-18 16:30

    The problem with using strongly typed method signatures is that there is no way for you to return an "error" object if something is wrong with the request, be it validation errors or not found errors.

    So if you want to use strongly typed signatures then you either have to included some sort of "error" object reference in your return type or explicitly throw exceptions..

    The good thing about using HttpActionResult is that you are not constrained to a specific return type. So you could, for example, return OK(someObject) or BadRequest(errorObject). However, it is up to the developer to write the method correctly and double check that nothing happens like the example you mentioned above.

    0 讨论(0)
  • 2021-01-18 16:34

    First of all, it is a good practice to return IHttpActionResult, indicating the corresponding http status. Something like:

    public async Task<IHttpActionResult> Get(string SomeKey)
    {
        if(ExistsInDB(SomeKey))
            return Ok(SomeRecordFromDB(SomeKey));
    
        return NotFound();
    }
    

    But if you really want to have a strongly typed api, you can do something like:

     public async Task<StronglyTypeResponse> Get()
     {
         return new StronglyTypeResponse();
     }
    

    Or, create a typed response, and you'll keep the http status code, etc in your response:

    public class StronglyTypeResponse
    {
    
    }
    
    public class StronglyTypedResult<T> : IHttpActionResult
    {
        HttpConfiguration _configuration;
        T _content;
        HttpStatusCode _statusCode;
        HttpRequestMessage _request;
    
        public StronglyTypedResult(T content, HttpStatusCode statusCode, HttpRequestMessage request, HttpConfiguration configuration)
        {
            _content = content;
            _request = request;
            _configuration = configuration;
            _statusCode = statusCode;
        }
    
        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            var response = new HttpResponseMessage(_statusCode)
            {
                Content = new ObjectContent<dynamic>(_content, _configuration.Formatters.JsonFormatter),
                RequestMessage = _request,
                ReasonPhrase = "some phrase"
            };
    
            return Task.FromResult(response);
        }
    }
    

    And then you can create your method:

    public async Task<StronglyTypedResult<StronglyTypeResponse>> Get()
    {
        return new StronglyTypedResult<StronglyTypeResponse>(new StronglyTypeResponse(), HttpStatusCode.OK, Request, Configuration);
    }
    

    Creating your own custom generic IHttpActionResult

    It's basically the same:

    public class IHttpActionResult<T> : System.Web.Http.IHttpActionResult
    {
        HttpConfiguration _configuration;
        T _content;
        HttpStatusCode _statusCode;
        HttpRequestMessage _request;
    
        public IHttpActionResult(T content, HttpStatusCode statusCode, HttpRequestMessage request, HttpConfiguration configuration)
        {
            _content = content;
            _request = request;
            _configuration = configuration;
            _statusCode = statusCode;
        }
    
        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            var response = new HttpResponseMessage(_statusCode)
            {
                Content = new ObjectContent<dynamic>(_content, _configuration.Formatters.JsonFormatter),
                RequestMessage = _request,
                ReasonPhrase = "some phrase"
            };
    
            return Task.FromResult(response);
        }
    }
    

    And now you can return the class you want with a typed IHttpActionResult:

    public async Task<IHttpActionResult<YourClass>> Get()
    {
        var yourclass = new YourClass();
    
        return new IHttpActionResult<YourClass>(yourclass, HttpStatusCode.OK, Request, Configuration);
    }
    
    0 讨论(0)
  • 2021-01-18 16:43
    public class ObjectResult : IHttpActionResult
    {
        object _value;
        HttpRequestMessage _request;
    
        public ObjectResult(object value, HttpRequestMessage request)
        {
            _value = value;
            _request = request;
        }
    
    
        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            if (_value == null)
                return Task.FromResult(_request.CreateResponse(HttpStatusCode.NotFound));
    
            var response = _request.CreateResponse(HttpStatusCode.OK, _value);
            return Task.FromResult(response);
        }
    }
    
       //create your method:
    
        public IHttpActionResult Get()
        {
            return new ObjectResult(repository.GetAll(), Request);
        }
    
    0 讨论(0)
提交回复
热议问题