Как я могу передать два разных параметра строки запроса, которые представляют один параметр метода действия? - PullRequest
2 голосов
/ 23 февраля 2010

У меня есть метод действия, подобный следующему

public JsonResult Index(string version)
{
   .. do stuff, return some data v1 or v2. Default = v2.
}

Итак, этот метод действия возвращает некоторые данные, которые могут быть отформатированы как Version 1 или Version 2 (независимо от того, какой вывод ... просто знайте, что они схематически отличаются).

Итак, когда пользователь хочет вызвать доступ к этому ресурсу, они следующие:

http://www.blah.com/api/Index

ничего особенного.

они тоже могут это сделать ...

http://www.blah.com/api/Index?version=1.0

НО, возможно ли сделать так, чтобы пользователь мог использовать параметры строки запроса version или v

eg. http://www.blah.com/api/Index?v=1.0 

, и это заполнит параметр версии в ActionMethod. Возможно ли это?

Ответы [ 3 ]

3 голосов
/ 23 февраля 2010

Полагаю, вы могли бы управлять параметрами метода действия с помощью фильтра действий.

В основном просто проверьте наличие 'v' в коллекции QueryString, и, если оно существует, бросьте его в коллекцию ActionParameters.

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    var version = filterContext.HttpContext.Request.QueryString["v"];
    if (!string.IsNullOrEmpty(version))
        filterContext.ActionParameters["version"] = version;
}

HTHS
Charles

РЕДАКТИРОВАТЬ: сделать его немного более общим ...

public class QueryStringToActionParamAttribute : ActionFilterAttribute
{
    private string _queryStringName;
    private string _actionParamName;

    public QueryStringToActionParamAttribute(string queryStringName, string actionParamName)
    {
        _queryStringName = queryStringName;
        _actionParamName = actionParamName;
    }

    public override void OnActionExecuting(ActionExecutedContext filterContext)
    {
        var queryStringValue = filterContext.HttpContext.Request.QueryString[_queryStringName];
        if (!string.IsNullOrEmpty(queryStringValue))
        {
            filterContext.ActionParameters[_actionParamName] = queryStringValue;
        }
    }
}

Тогда вы могли бы назвать это как:

[QueryStringToActionParam("v", "version")];
0 голосов
/ 23 января 2015

Просто чтобы добавить что-то еще к этому старому вопросу ... Вы можете комбинировать методы здесь и поддерживать выбор версии по заголовку запроса ИЛИ строке запроса, изменив проверку в ответе @ Rosstified, включив проверку QueryString:

        if (httpContext.Request.Headers[VersionHeader] != null) {
            vers = httpContext.Request.Headers[VersionHeader];
        } else {
            if (httpContext.Request.QueryString["v"] != null) {
                vers = httpContext.Request.QueryString["v"];
            } else {
                vers = "1.0"; // set default here.
            }
        }
0 голосов
/ 23 февраля 2010

Альтернативный способ обработки версий API состоит в том, чтобы фактически иметь разные версии контроллера для каждой версии API, таким образом, вам не нужно выполнять всю проверку для каждого номера версии в каждом методе действия. Каждый контроллер применим только к одной версии API.

Его очиститель (IMO) для меня обрабатывает управление версиями во время маршрута, а не во время действия. Вы можете сделать это с помощью ограничения маршрутизации, чтобы проверить номер версии.

В приведенном ниже примере контроллеры V10 и V20 могут быть направлены только в том случае, если пройдено ограничение маршрута - т.е. присутствует заголовок, если заголовок по умолчанию отсутствует (то есть v2).:

routes.MapRoute(
            "EmployeeListingv1",
            "employees",
            new { controller = "V10Employees", action = "Index" },  // Parameter defaults
            new { ApiV = new ApiVersionConstraint(ApiVersion.Version10) }
    );

routes.MapRoute(
                "EmployeeListingv2",
                "employees",
                new { controller = "V20Employees", action = "Index" },  // Parameter defaults
                new { ApiV = new ApiVersionConstraint(ApiVersion.Version20) }
        );

Вы можете сделать это, используя строку запроса, чтобы передать версию, аналогичную текущей в данный момент, и просто перейти на ограничение маршрута, однако я обнаружил, что проще поддерживать использование необязательного заголовка в запросе. (он также более «RESTful», не вдаваясь в эту дискуссию). Отсутствие заголовка означает стандартную (последнюю) версию API.

Пример ограничения версии API:

/// <summary>
/// Enable routing of requests to controllers based on the 
/// API version contained in the header.
/// </summary>
public class ApiVersionConstraint : IRouteConstraint   
{
    const string VersionHeader = "X-MY-API-NAME-HERE-VERSION";

    private ApiVersion _version = ApiVersion.Unsupported;

    public ApiVersionConstraint(ApiVersion version)
    {
        this._version = version;
    }

    #region IRouteConstraint Members

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        string vers = string.Empty;

        if (httpContext.Request.Headers[VersionHeader] != null)
        {
            vers = httpContext.Request.Headers[VersionHeader];
        }
        else
        {
            vers = "2.0"; // set default here.
        }

        ApiVersion fromHeader = ApiVersion.Unsupported;

        switch (vers)
        {
            case "1.0":
                {
                    fromHeader = ApiVersion.Version10;
                    break;
                }
            case "2.0":
                {
                    fromHeader = ApiVersion.Version20;
                    break;
                }

            default:
                {
                    fromHeader = ApiVersion.Unsupported;
                    break;
                }
        }

        return fromHeader == _version;

    }

    #endregion
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...