...私がこれについて最初に尋ねたと思いますか?
次のルートがあり、それぞれが異なるコントローラーで宣言されているとします。
[HttpGet, Route("sign-up/register", Order = 1)]
[HttpGet, Route("sign-up/{ticket}", Order = 2)]
... Order
パラメーターを除いて、同じコードを使用してMVC5.0でこれを行うことができます。ただし、MVC 5.1にアップグレードすると、質問のタイトルに例外メッセージが表示されます。
URLに一致する複数のコントローラータイプが見つかりました。これは、複数のコントローラーの属性ルートが要求されたURLと一致する場合に発生する可能性があります。
したがって、新しいRouteAttribute.Order
プロパティはコントローラーレベルのみですか? AttributeRouting.NETではSitePrecedence
も実行できることを知っています。すべてのアクションが同じコントローラー内にある場合、上記のようなルートを作成する唯一の方法はありますか?
更新
申し訳ありませんが、これらのルートはWebAPIではなくMVCコントローラー上にあると言っておく必要があります。これがApiControllersにどのように影響するかわかりません。
属性ルーティングの場合、WebAPIはリクエストに一致するすべてのコントローラーを見つけようとします。複数のコントローラーがこれを処理できることがわかった場合、これはユーザーエラーである可能性があると見なされるため、例外がスローされます。このルートプロービングは、最初の一致が勝つ通常のルーティングとは異なります。
回避策として、同じコントローラー内にこれら2つのアクションがある場合、Web APIはルートの優先順位を尊重し、シナリオが機能していることを確認する必要があります。
ticket
がint
になることがわかっている場合は、ルートでそのタイプを指定して、ルートの解決に役立てることができます。
[HttpGet, Route("sign-up/register")] [HttpGet, Route("sign-up/{ticket:int}")]
同じルートプレフィックスASP.NET Web Apiを持つ複数のコントローラータイプ へのリンクを含むuser1145404のコメントによると、このアプローチは私にとってはうまくいきました。
これを修正する方法は2つあります。
ここのような正規表現の制約: 2つの異なるルートでのMVCルート属性エラー
または、次のようなカスタムルート制約: https://blogs.msdn.Microsoft.com/webdev/2013/10/17/attribute-routing-in-asp-net-mvc-5/
IRouteConstraintインターフェイスを実装することにより、カスタムルート制約を作成できます。たとえば、次の制約は、パラメーターを有効な値のセットに制限します。
public class ValuesConstraint : IRouteConstraint
{
private readonly string[] validOptions;
public ValuesConstraint(string options)
{
validOptions = options.Split('|');
}
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
object value;
if (values.TryGetValue(parameterName, out value) && value != null)
{
return validOptions.Contains(value.ToString(), StringComparer.OrdinalIgnoreCase);
}
return false;
}
}
次のコードは、制約を登録する方法を示しています。
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
var constraintsResolver = new DefaultInlineConstraintResolver();
constraintsResolver.ConstraintMap.Add("values", typeof(ValuesConstraint));
routes.MapMvcAttributeRoutes(constraintsResolver);
}
}
これで、ルートに制約を適用できます。
public class TemperatureController : Controller
{
// eg: temp/celsius and /temp/Fahrenheit but not /temp/kelvin
[Route("temp/{scale:values(celsius|Fahrenheit)}")]
public ActionResult Show(string scale)
{
return Content("scale is " + scale);
}
}
私の意見では、これは素晴らしいデザインではありません。自分で明示的に設定しない限り、意図したURLについての判断や、照合時の特定のルールはありません。しかし、少なくともあなたはあなたのURLをあなたが望むように見せることができます。制約リストが長すぎないことを願っています。そうである場合、またはルート文字列パラメーターとその制約をハードコーディングしたくない場合は、actionメソッドの外部でプログラムでビルドし、変数としてRoute属性にフィードすることができます。