Return Task as plain Task breaks WebAPI

2019-09-02 12:42发布

问题:

This is actually a different angel on this question

Task with result unknown type

Consider this code

public interface IQueryHandler<in TQuery, TResult> where TQuery : Query<TResult>
{
    Task<TResult> Handle(TQuery query);
}

Above interface is invoked like where Task<T> will be exposed as Task

public Task Invoke(Query query)
{
    var queryHandlerType = typeof(IQueryHandler<,>);
    var queryType = query.GetType();
    var queryResultType = queryType.BaseType.GetGenericArguments().First();
    var handler = _container.GetInstance(queryHandlerType.MakeGenericType(queryType, queryResultType)) as dynamic;
    return handler.Handle(query as dynamic);
}

WebApi controller

public Task Get([FromUri] Contract contract)
{
    return _invoker.Invoke(CreateDto<Query>(contract));
}

This will break WebAPI and it will for some reason response redirect me to base url of site

回答1:

It does seem odd that you're getting a redirect response rather than a 204, but either way your action method isn't going to behave as you expect with that method signature. By returning a Task, you're effectively telling the framework you want to (asynchronously) return nothing.

I understand you don't know the T in Task<T> at runtime here, and the way to work around that is to await the result and cast it to an object. This should work:

public async Task<object> Get([FromUri] Contract contract)
{
    var result = await _invoker.Invoke(CreateDto<Query>(contract));
    return result as object;
}