どのように私は1つのアクションメソッドのparamを表す2つの異なるクエリ文字列のparamsを渡すことができますか?
-
22-09-2019 - |
質問
私は、次の
のようなアクションメソッドを持っていますpublic JsonResult Index(string version)
{
.. do stuff, return some data v1 or v2. Default = v2.
}
だから、このアクションメソッドは、(ちょうど彼らがschemantically異なっていることを知っている...それが何であれ、出力)Version 1
またはVersion 2
のいずれかとしてフォーマットすることができるいくつかのデータを返します。
だから、ユーザーがこのリソースのアクセスを呼び出したいとき、彼らは次のとおりです。
http://www.blah.com/api/Index
何もあまりにもハードます。
彼らはまた、これを行うことができます...
http://www.blah.com/api/Index?version=1.0
しかし、それはユーザーがクエリ文字列のparams version
またはv
eg. http://www.blah.com/api/Index?v=1.0
これはActionMethodにバージョンパラメータを移入します。可能?
解決
私はあなたがアクションフィルタを使用してアクションメソッドのパラメータを操作することができ推測してます。
基本的にはちょうどQueryString
コレクション内の「V」をチェックし、それが存在する場合は、ActionParameters
コレクションにそれをスローします。
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var version = filterContext.HttpContext.Request.QueryString["v"];
if (!string.IsNullOrEmpty(version))
filterContext.ActionParameters["version"] = version;
}
HTHS、
チャールズ
編集:それはもう少し一般的な作り...
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")];
他のヒント
APIのバージョン管理を処理するための別の方法は、各APIのバージョン用のコントローラの異なるバージョンを実際に持っているあなたはすべて各アクションメソッド内のすべてのバージョン番号のチェックを持っている必要がいけないという方法です。各コントローラには、APIの1つのバージョンにのみ適用されます。
私にはそのクリーナー(IMO)は、経路、時間ではなく、アクション時にバージョン管理を扱います。あなたは、バージョン番号を確認するために、ルーティングの制約でこれを行うことができます。
ルートcontraintが経過した場合に以下の例では、コントローラ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
}
ただ、あなたがたQueryStringチェックを含めるために、ここで、要求ヘッダーまたはRosstifiedの答え@にチェックを変更することで、クエリ文字列によってサポートバージョン選択して技術を組み合わせることができます...この古い質問にはもっと何かを追加します:
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.
}
}