Как создать динамическую маршрутизацию в Asp.Net Core MVC [duplicate]

Любой родитель, который существует в момент привязки события, и если ваша страница динамически создавала элементы с помощью кнопки имени класса, вы привязывали бы событие к родительскому, который уже существует

$(document).ready(function(){
  //Particular Parent chield click
  $(".buttons").on("click","button",function(){
    alert("Clicked");
  });  
  
  //Dynamic event bind on button class  
  $(document).on("click",".button",function(){
    alert("Dymamic Clicked");
  });
  $("input").addClass("button");  
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="buttons">
  <input type="button" value="1">
  <button>2</button>
  <input type="text">
  <button>3</button>  
  <input type="button" value="5">  
  </div>
<button>6</button>

4
задан Carvellis 5 March 2017 в 18:16
поделиться

1 ответ

Я считаю, что соглашение является правильным подходом здесь, и бит, который вам не хватает, просто предоставляет правильный метод расширения для регистрации вашей библиотеки в 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 внутри tha т. Самое приятное, что поскольку это расширение 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/");
3
ответ дан Daniel J.G. 19 August 2018 в 00:39
поделиться
  • 1
    спасибо, я смог использовать ваше решение. Вместо метода AddMyLibrary () я устанавливаю соглашение о префиксах в IConfigureOptions & lt; MvcOptions & gt; производный класс, поэтому мне не придется просить пользователя добавлять сервисы .AddMvc (). AddMyLibrary (). Единственный способ, которым пользователь может сломать это, если он впоследствии очистит коллекцию конвенций. – Carvellis 6 March 2017 в 18:01
Другие вопросы по тегам:

Похожие вопросы: