Как изменить результат возврата API в ядре asp.net 2.2?

Мое требование заключается в том, что когда возвращаемый тип действия недействителен или Task, вместо этого я хотел бы вернуть свой собственный ApiResult. Я попробовал механизм промежуточного программного обеспечения, но ответ, который я наблюдал, имеет значение null как для ContentLength, так и для ContentType, в то время как мне нужно JSON-представление пустого экземпляра ApiResult. Где я должен сделать это преобразование тогда?


person Nico    schedule 15.01.2019    source источник
comment
Вы создаете свой собственный объект класса и возвращаете его в последней строке вашего метода действия API.   -  person yogihosting    schedule 15.01.2019
comment
Я не хочу повторять это в каждом методе действия. Я просто хочу, чтобы метод действия возвращал void. Это может быть достигнуто в веб-API 2 с помощью пользовательского DelegatingHandler, потому что даже действие void или Task, возвращающее действие, будет генерировать результат HttpResponseMessage, которым я могу манипулировать.   -  person Nico    schedule 15.01.2019
comment
Похоже на Здесь подойдет фильтр действий.   -  person Kirk Larkin    schedule 15.01.2019
comment
Стоит отметить, что если действия выполняют какую-либо асинхронную работу, они не должны возвращать void.   -  person jpgrassi    schedule 15.01.2019
comment
@jpgrassi спасибо за указание. Я знаю об этом.   -  person Nico    schedule 16.01.2019


Ответы (2)


В ядре .net есть несколько фильтров, и вы можете попробовать Фильтры результатов.

Для void или Task он вернет EmptyResult в OnResultExecutionAsync.

Попробуйте реализовать свой собственный ResultFilter как

public class ResponseFilter : IAsyncResultFilter
{
    public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
    {
        // do something before the action executes
        if (context.Result is EmptyResult)
        {
            context.Result = new JsonResult(new ApiResult());
        }
        var resultContext = await next();
        // do something after the action executes; resultContext.Result will be set
    }
}
public class ApiResult
{
    public int Code { get; set; }
    public object Result { get; set; }
}

И зарегистрируйте его в Startup.cs

services.AddScoped<ResponseFilter>();
services.AddMvc(c =>
                {                       
                    c.Filters.Add(typeof(ResponseFilter));
                }).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
person Edward    schedule 16.01.2019
comment
Можно еще кое-что спросить? Работают ли зарегистрированные фильтры результатов и средства форматирования вывода таким образом, что они будут выполняться по порядку, независимо от того, а не сокращают ли остальные в зарегистрированном списке, если во время выполнения конвейера нет исключений? - person Nico; 16.01.2019
comment
Следует отметить, что если действие возвращает значение void, средства форматирования вывода вообще не будут вызываться. - person Nico; 16.01.2019
comment
@Nico Вы имеете в виду, что после добавления ResponseFilter output formatter не вызывается? - person Edward; 16.01.2019
comment
Нет, я имел в виду, когда в фильтре результатов не было преобразования из void в мой собственный ApiResult. Таким образом, просто использовать только средства форматирования вывода недостаточно. - person Nico; 16.01.2019
comment
Еще одна вещь: ContentLength никогда не устанавливается. Не знаю, какой объект должен отвечать за установку этого значения. - person Nico; 16.01.2019
comment
Я не мог заставить это работать должным образом, потому что любые изменения, которые я внесу в resultContext.Result, не будут отправлены обратно в ответ API. Я заработал, используя вместо этого IAlwaysRunResultFilter, а затем OnResultExecutionAsync. - person Bertus van Zyl; 04.07.2019

Все, что вам нужно сделать, это проверить тип возврата, и на основе возврата вы можете выполнять любые операции, которые хотите.

Вот абстрактная демонстрация: У вас есть метод:

 public Action SomeActionMethod()
    {
        var obj = new object();
        return (Action)obj;
    }

Теперь в вашем коде вы можете использовать следующий код, чтобы получить имя метода:

 MethodBase b = p.GetType().GetMethods().FirstOrDefault();
        var methodName = ((b as MethodInfo).ReturnType.Name);

Где p в приведенном выше коде — это класс, содержащий методы, тип возвращаемого значения которых вы хотите знать.

после того, как у вас есть имя метода, вы можете решить, что возвращать переменная methodName.

Надеюсь, поможет.

person Nabeel    schedule 15.01.2019