Come posso passare due diversi params stringa di query che rappresentano un metodo di azione param?

StackOverflow https://stackoverflow.com/questions/2315046

  •  22-09-2019
  •  | 
  •  

Domanda

Ho un metodo di azione come il seguente

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

Quindi, questo metodo azione restituisce alcuni dati, che possono essere formattati sia come Version 1 o Version 2 (qualunque output che è ... è sufficiente sapere che essi sono schemantically diversi).

Così, quando un utente vuole chiamare accedere a questa risorsa, sono le seguenti:

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

nulla di troppo difficile.

possono anche fare questo ...

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

Ma, è possibile fare in modo che l'utente può utilizzare version la stringa di query params o v

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

e questo popolerà il parametro versione nel ActionMethod. Possibile?

È stato utile?

Soluzione

Sto indovinando si poteva manipolare il parametro del metodo di azione (s) utilizzando un filtro azione.

In pratica solo verificare la presenza di una 'v' nella raccolta QueryString, e se esiste, gettarlo nella collezione ActionParameters.

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

HTHS,
Charles

EDIT: il che rende un po 'più generico ...

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;
        }
    }
}

Poi si può chiamare come:

[QueryStringToActionParam("v", "version")];

Altri suggerimenti

Un modo alternativo per gestire il controllo delle versioni delle API è quello di avere in realtà diverse versioni del controller per ogni versione di API, in questo modo non avete bisogno di avere tutto il controllo per ogni numero di versione in ogni metodo di azione. Ogni controller è applicabile solo a una versione di API.

La sua più pulita (IMO) per me gestire la delle versioni al momento percorso piuttosto che il tempo di azione. È possibile farlo con un vincolo di routing per verificare il numero di versione.

Nell'esempio che segue, il V10 e V20 controllore possono essere indirizzati solo se il percorso contraint passato - cioè l'intestazione era presente, se nessuna intestazione default (che è 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) }
        );

Si potrebbe farlo utilizzando la stringa di query per passare alla versione come si sta attualmente facendo e basta cambiare ad un vincolo di percorso, però ho trovato più facile da mantenere con un'intestazione facoltativa nella richiesta. (Sua anche più "RESTful' senza entrare in che tutto il dibattito). Nessuna intestazione significa versione di default (l'ultima) delle API.

Esempio vincolo API Versione:

/// <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
}

Giusto per aggiungere qualcosa in più a questa vecchia domanda ... È possibile combinare le tecniche qui e così sostenere selezione della versione richiesta di intestazione o stringa di query modificando il check-in @ risposta di Rosstified include un controllo 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.
            }
        }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top