ここでは規則が正しいアプローチであると信じています。あなたが見逃しているのは、MVC 内にライブラリを登録するための適切な拡張メソッドを提供することだけです。
特定のセレクターを渡すすべてのコントローラーにプレフィックスを追加する規則を作成することから始めます。
- 文化接頭辞を追加するために私が書いたものに基づいていますが、アイデアはあなたがリンクした記事と非常に似ています.
- 基本的に、既存の
AttributeRouteModel
を更新します。 または、見つからない場合は新しいものを追加してください。
これはそのような規則の例です:
public class ApiPrefixConvention: IApplicationModelConvention
{
private readonly string prefix;
private readonly Func<ControllerModel, bool> controllerSelector;
private readonly AttributeRouteModel onlyPrefixRoute;
private readonly AttributeRouteModel fullRoute;
public ApiPrefixConvention(string prefix, Func<ControllerModel, bool> controllerSelector)
{
this.prefix = prefix;
this.controllerSelector = controllerSelector;
// Prepare AttributeRouteModel local instances, ready to be added to the controllers
// This one is meant to be combined with existing route attributes
onlyPrefixRoute = new AttributeRouteModel(new RouteAttribute(prefix));
// This one is meant to be added as the route for api controllers that do not specify any route attribute
fullRoute = new AttributeRouteModel(
new RouteAttribute("api/[controller]"));
}
public void Apply(ApplicationModel application)
{
// Loop through any controller matching our selector
foreach (var controller in application.Controllers.Where(controllerSelector))
{
// Either update existing route attributes or add a new one
if (controller.Selectors.Any(x => x.AttributeRouteModel != null))
{
AddPrefixesToExistingRoutes(controller);
}
else
{
AddNewRoute(controller);
}
}
}
private void AddPrefixesToExistingRoutes(ControllerModel controller)
{
foreach (var selectorModel in controller.Selectors.Where(x => x.AttributeRouteModel != null).ToList())
{
// Merge existing route models with the api prefix
var originalAttributeRoute = selectorModel.AttributeRouteModel;
selectorModel.AttributeRouteModel =
AttributeRouteModel.CombineAttributeRouteModel(onlyPrefixRoute, originalAttributeRoute);
}
}
private void AddNewRoute(ControllerModel controller)
{
// The controller has no route attributes, lets add a default api convention
var defaultSelector = controller.Selectors.First(s => s.AttributeRouteModel == null);
defaultSelector.AttributeRouteModel = fullRoute;
}
}
ここで、これがすべてライブラリではなく作成中のアプリの一部である場合は、次のように登録します:
services.AddMvc(opts =>
{
var prefixConvention = new ApiPrefixConvention("api/", (c) => c.ControllerType.Namespace == "WebApplication2.Controllers.Api");
opts.Conventions.Insert(0, prefixConvention);
});
ただし、ライブラリを提供しているので、必要なのは AddMyLibrary("some/prefix")
のような拡張メソッドを提供することです これにより、この規則の追加と、必要なサービスの登録などのその他のセットアップが処理されます。
IMvcBuilder
の拡張メソッドを書くことができます MvcOptions
を更新します そのメソッド内。良い点は、since が IMvcBuilder
の拡張であることです。 、常にデフォルトの AddMvc()
の後に呼び出されます :
public static IMvcBuilder AddMyLibrary(this IMvcBuilder builder, string prefix = "api/")
{
// instantiate the convention with the right selector for your library.
// Check for namespace, marker attribute, name pattern, whatever your prefer
var prefixConvention = new ApiPrefixConvention(prefix, (c) => c.ControllerType.Namespace == "WebApplication2.Controllers.Api");
// Insert the convention within the MVC options
builder.Services.Configure<MvcOptions>(opts => opts.Conventions.Insert(0, prefixConvention));
// perform any extra setup required by your library, like registering services
// return builder so it can be chained
return builder;
}
次に、ライブラリのユーザーに、次のようにアプリ内にライブラリを含めるように依頼します:
services.AddMvc().AddMyLibrary("my/api/prefix/");