Необязательный параметр, привязанный к параметру .NET WebApi

У меня есть REST API, встроенный в .NET WebApi. Я создал атрибут привязки настраиваемого параметра для извлечения значения из заголовков HTTP. Существуют сценарии, в которых заголовок может присутствовать или отсутствовать в запросе, поэтому я хотел бы иметь возможность сделать что-то вроде следующего, чтобы рассматривать заголовок как необязательный параметр.

public IHttpActionResult Register([FromBody] RegistrationRequest request, [FromHeaderAuthorization] string authorization = null)
{

Это отлично работает, когда я вызываю конечную точку с включенным заголовком авторизации. Однако при вызове конечной точки без заголовка я получаю следующее сообщение об ошибке:

The request is invalid.', MessageDetail='The parameters dictionary does not contain an entry for parameter 'authorization' of type 'System.String'

Я искал, чтобы попытаться определить, можно ли таким образом рассматривать параметр как необязательный, и нашел некоторые смешанные результаты. Похоже, что в C# 8.0 я мог бы добиться этого, используя ссылочный тип, допускающий значение NULL, но Visual Studio указывает, что 8.0 в настоящее время находится в предварительной версии и, следовательно, не является для меня вариантом. Тем не менее, я действительно не смог найти ничего другого, что указывало бы на возможность такого рода вещей или нет.

Мой вопрос: можно ли рассматривать этот параметр заголовка как необязательный или мне нужно сделать это по-другому?


person morris295    schedule 21.06.2019    source источник
comment
Возможно, вы могли бы попытаться создать собственный ModelBinder для этого параметра и проверить нулевые значения.   -  person carlos chourio    schedule 21.06.2019
comment
@carloschourio, вариант использования, с которым я имею дело, заключается в том, что заголовок не будет присутствовать, ни ключ, ни значение. В этом случае будет ли полезен пользовательский ModelBinder? Кажется, что в этом сценарии проверка нулевого значения не будет работать только потому, что ключ или значение вообще не существует.   -  person morris295    schedule 21.06.2019
comment
Обязательно ли выполнять логику с заголовком внутри контроллера? Я думаю, вы могли бы использовать фильтр для получения значения из заголовка, и не имеет значения, присутствует он или нет. Но, возможно, вам придется поместить логику внутри контроллера, а не в фильтре.   -  person carlos chourio    schedule 21.06.2019
comment
Это не обязательно обязательно, нет. Этот REST API является интерфейсом многопользовательского сервера. Существует два сценария развертывания; облако и локальное размещение. Этот заголовок помогает определить, какой клиент выполняет вызов при использовании облака. Для локального размещения тот, кто размещает, считается единственным арендатором. Это вариант использования, с которым я имею дело. Все это говорит о том, что здесь может быть полезен фильтр, поскольку я могу проверить наличие заголовка и сделать все, что мне нужно, если он присутствует или нет. Я посмотрю, как двигаться в этом направлении.   -  person morris295    schedule 21.06.2019
comment
Вы используете ASP.NET Core или .Net Framework?   -  person carlos chourio    schedule 22.06.2019
comment
Я использую .NET Framework   -  person morris295    schedule 22.06.2019
comment
Это работает, когда вы определяете вторую перегрузку без параметра явно? Вот так: public IHttpActionResult Register([FromBody] RegistrationRequest request) => Register(RegistrationRequest, null);   -  person blenderfreaky    schedule 22.06.2019


Ответы (1)


В итоге я отказался от параметра заголовка и пошел немного в другом направлении.

Я уже создал класс для расширения HttpRequestMessage, чтобы делать такие вещи, как получение IP-адреса клиента, вызывающего конечную точку, в итоге я добавил метод для обработки проверки существования заголовка и получения необходимой идентификационной информации по мере необходимости.

public static class HttpRequestMessageExtensions
{
    private const string HttpContext = "MS_HttpContext";
    private const string RemoteEndpointMessage = "System.ServiceModel.Channels.RemoteEndpointMessageProperty";

    /* Method body excluded as irrelevant */
    public static string GetClientIpAddress(this HttpRequestMessage request) { ... }

    /** Added this method for handling the authorization header. **/
    public static Dictionary<string, string> HandleAuthorizationHeader(this HttpRequestMessage request)
    {
        Tenant tenant = new Tenant();
        IEnumerable<string> values;
        request.Headers.TryGetValues("Authorization", out values);
        string tenantConfig = ConfigurationUtility.GetConfigurationValue("tenantConfig");

        if (null != values)
        {
            // perform actions on authorization header.
        }
        else if(!string.IsNullOrEmpty(tenantConfig))
        {
            // retrieve the tenant info based on configuration.
        }
        else
        {
            throw new ArgumentException("Invalid request");
        }

        return tenant;
    }
}
person morris295    schedule 25.06.2019