Как я могу «перегрузить» действия с помощью маршрутизации атрибутов? [Дубликат]

Это одно из мест, с помощью которого привязка данных, используемая во многих новых фреймворках JavaScript, будет очень полезна для вас ...

Итак, если вы используете Angular, React или любые другие фреймворки, которые делают два способа связывания данных, эта проблема просто исправлена ​​для вас, поэтому простым языком ваш результат undefined на первом этапе, поэтому вы получили result = undefined до получения данных, а затем, как только вы получите результат , он будет обновляться и присваиваться новому значению, которое отвечает на ваш вызов Ajax ...

Но как вы можете сделать это в чистом javascript или jQuery, например, как вы задали этот вопрос?

Вы можете использовать обратный вызов, обещание и недавно наблюдаемое, чтобы обрабатывать его для вас, например, в обещаниях мы имеем некоторые функции, такие как success () или then (), которые будут выполняться, когда ваши данные будут готовы для вас, с функцией обратного вызова или подписки на наблюдаемые.

Например, в вашем случае, в котором вы используете jQuery, вы можете сделать что-то вроде этого:

$(document).ready(function(){
    function foo() {
        $.ajax({url: "api/data", success: function(data){
            fooDone(data); //after we have data, we pass it to fooDone
        }});
    };

    function fooDone(data) {
        console.log(data); //fooDone has the data and console.log it
    };

    foo(); //call happens here
});

Для получения дополнительной информации n изучение обещаний и наблюдаемых, которые являются новыми способами для создания асинхронных материалов.

298
задан Wayne Koorts 25 May 2015 в 02:24
поделиться

16 ответов

Вы можете использовать атрибут, если хотите, чтобы ваш код перегружал.

[ActionName("MyOverloadedName")]

Но вам придется использовать другое имя действия для того же метода http (как говорили другие) , Так что это просто семантика в этот момент. Вы предпочитаете иметь имя в своем коде или вашем атрибуте?

У Фила есть статья, связанная с этим: http://haacked.com/archive/2008/08/29/how-a -метод-становится-ан-action.aspx

190
ответ дан JD Conley 26 August 2018 в 09:32
поделиться

Вы можете использовать [ActionName («NewActionName»)] для использования того же метода с другим именем:

public class HomeController : Controller
{
    public ActionResult GetEmpName()
    {
        return Content("This is the test Message");
    }

    [ActionName("GetEmpWithCode")]
    public ActionResult GetEmpName(string EmpCode)
    {
        return Content("This is the test Messagewith Overloaded");
    }
}
1
ответ дан Alex Butenko 26 August 2018 в 09:32
поделиться

Создать базовый метод как виртуальный

public virtual ActionResult Index()

Создать переопределенный метод как переопределить

public override ActionResult Index()

Изменить: это, очевидно, применяется только в том случае, если метод переопределения находится в производном классе который, похоже, не был намерением OP.

0
ответ дан Andiih 26 August 2018 в 09:32
поделиться

Мне нравится этот ответ, размещенный в другом потоке

Это в основном используется, если вы наследуете от другого контроллера и хотите переопределить действие с базового контроллера

ASP. NET MVC - переопределение действия с различными параметрами

0
ответ дан Community 26 August 2018 в 09:32
поделиться

Я достиг этого с помощью Маршрутизация атрибутов в MVC5. По общему признанию, я новичок в MVC из десятилетия веб-разработки с использованием WebForms, но для меня это работало. В отличие от принятого ответа, все перегруженные действия могут быть отображены одним и тем же файлом.

Сначала включите маршрутизацию атрибутов в App_Start / RouteConfig.cs.

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapMvcAttributeRoutes();

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );            
    }
}

класс контроллера с префиксом маршрута по умолчанию.

[RoutePrefix("Returns")]
public class ReturnsController : BaseController
{
    //.......

Затем украсьте действия вашего контроллера, которые перегружают друг друга общим маршрутом и параметрами. Используя ограниченные по типу параметры, вы можете использовать один и тот же формат URI с идентификаторами разных типов.

[HttpGet]
// Returns
public ActionResult Index()
{
    //.....
}

[HttpGet]
[Route("View")]
// Returns/View
public ActionResult View()
{
    // I wouldn't really do this but it proves the concept.
    int id = 7026;
    return View(id);
}

[HttpGet]
[Route("View/{id:int}")]
// Returns/View/7003
public ActionResult View(int id)
{
    //.....
}

[HttpGet]
[Route("View/{id:Guid}")]
// Returns/View/99300046-0ba4-47db-81bf-ba6e3ac3cf01
public ActionResult View(Guid id)
{
    //.....
}

Надеюсь, это поможет и не приведет кого-то к неправильному пути. : -)

9
ответ дан cookdn 26 August 2018 в 09:32
поделиться

Вы можете использовать один ActionResult для работы с Post и Get:

public ActionResult Example() {
   if (Request.HttpMethod.ToUpperInvariant() == "GET") {
    // GET
   }
   else if (Request.HttpMethod.ToUpperInvariant() == "POST") {
     // Post  
   }
}

Полезно, если ваши методы Get и Post имеют соответствующие подписи.

4
ответ дан DevDave 26 August 2018 в 09:32
поделиться

Я только что наткнулся на этот вопрос и, хотя сейчас он довольно старый, он по-прежнему очень уместен. Как ни странно, один правильный комментарий в этой теме был опубликован самонадеянным новичком в MVC, когда он написал сообщение. Даже документы ASP.NET не совсем корректны. У меня большой проект, и я успешно перегружаю методы действий.

Если понимать маршрутизацию, помимо простого шаблона маршрута {controller} / {action} / {id} по умолчанию, может быть очевидно, что действия контроллера могут быть сопоставлены с использованием любого уникального шаблона. Кто-то здесь говорил о полиморфизме и сказал: «HTTP не понимает полиморфизм», но маршрутизация не имеет ничего общего с HTTP.

Лучший способ сделать эту работу - использовать атрибуты маршрутизации, например:

[RoutePrefix("cars/{country:length(3)}")]
public class CarHireController
{
    [Route("{location}/{page:int=1}", Name = "CarHireLocation")]
    public ActionResult Index(string country, string location, int page)
    {
        return Index(country, location, null, page);
    }

    [Route("{location}/{subLocation}/{page:int=1}", Name = "CarHireSubLocation")]
    public ActionResult Index(string country, string location, string subLocation, int page)
    {
        //The main work goes here
    }
}

Эти действия будут позаботьтесь о таких URL, как /cars/usa/new-york и /cars/usa/texas/dallas, которые будут сопоставляться с первым и вторым действиями индекса соответственно.

Изучив этот примерный контроллер, очевидно, что он выходит за рамки шаблона маршрута по умолчанию, упомянутого выше. По умолчанию работает хорошо, если ваша структура URL точно соответствует соглашениям об именах кода, но это не всегда так. Код должен описывать домен, но URL-адреса часто должны идти дальше, потому что их контент должен основываться на других критериях, таких как требования к SEO.

Преимущество шаблона маршрутизации по умолчанию заключается в том, что он автоматически создает уникальные маршруты. Это обеспечивается компилятором, поскольку URL-адреса будут соответствовать уникальным типам контроллеров и членам.

Важное замечание Единственный недостаток заключается в том, что использование маршрутизации для генерации URL-адресов для перегруженных действий не работает, если оно основано на имени действия, например, , при использовании UrlHelper.Action. Но он работает, если вы используете именованные маршруты, например UrlHelper.RouteUrl. И использование названных маршрутов, согласно уважительным источникам, способ как-то идти ( http://haacked.com/archive/2010/11/21/named-routes-to-the-rescue.aspx/ ).

Удачи!

3
ответ дан DvS 26 August 2018 в 09:32
поделиться

Чтобы устранить эту проблему, вы можете записать ActionMethodSelectorAttribute, который исследует MethodInfo для каждого действия и сравнивает его с опубликованными значениями формы, а затем отклоняет любой метод, для которого значения формы не используются, t match (за исключением названия кнопки, конечно).

Вот пример: - http://blog.abodit.com/2010/02/asp-net-mvc-ambiguous-match /

НО, это не очень хорошая идея.

15
ответ дан Ian Mercer 26 August 2018 в 09:32
поделиться

Вот что еще вы можете сделать ... вы хотите метод, который может иметь параметр, а не.

Почему бы не попробовать это ...

public ActionResult Show( string username = null )
{
   ...
}

Это сработало для меня ... и в этом одном методе вы можете проверить, есть ли у вас входящий параметр.

Обновлено для удаления недействительного синтаксиса с нулевым значением для строки и использования значения параметра по умолчанию.

41
ответ дан Josh 26 August 2018 в 09:32
поделиться

Мне нужна перегрузка для:

public ActionResult Index(string i);
public ActionResult Index(int groupId, int itemId);

Достаточно немного аргументов, в которых я это сделал:

public ActionResult Index(string i, int? groupId, int? itemId)
{
    if (!string.IsNullOrWhitespace(i))
    {
        // parse i for the id
    }
    else if (groupId.HasValue && itemId.HasValue)
    {
        // use groupId and itemId for the id
    }
}

Это не идеальное решение, особенно если вы есть много аргументов, но он хорошо работает для меня.

2
ответ дан Kasey Speakman 26 August 2018 в 09:32
поделиться

Для каждого метода контроллера разрешена только одна открытая подпись. Если вы попытаетесь перегрузить его, он будет скомпилирован, но вы получите ошибку времени выполнения, которую вы испытали.

Если вы не хотите использовать разные глаголы (например, атрибуты [HttpGet] и [HttpPost]), чтобы различать перегруженные методы (которые будут работать) или изменять маршрутизацию, тогда остается то, что вы может либо предоставить другой метод с другим именем, либо вы можете отправить внутри существующего метода. Вот как я это сделал:

Однажды я пришел в ситуацию, когда мне пришлось поддерживать обратную совместимость. Первоначальный метод ожидал два параметра, но новый имел только один. Перегрузка, как я ожидала, не сработала, потому что MVC больше не нашел точку входа.

Чтобы решить эту проблему, я сделал следующее:

  1. Изменено 2 перегруженных метода действия из public в private
  2. Создан один новый общедоступный метод, который содержал «just» 2 строковых параметра. Он действовал как диспетчер, т. Е .:
    public ActionResult DoSomething(string param1, string param2)
    {
        if (string.IsNullOrEmpty(param2))
        {
            return DoSomething(ProductName: param1);
        }
        else
        {
            int oldId = int.Parse(param1);
            return DoSomething(OldParam: param1, OldId: oldId);
        }
    }
    
    
    private ActionResult DoSomething(string OldParam, int OldId)
    {
        // some code here
        return Json(result);
    }
    
    
    private ActionResult DoSomething(string ProductName)
    {
        // some code here
        return Json(result);
    }
    

Конечно, это взломать и впоследствии нужно реорганизовать. Но на данный момент это сработало для меня.

Вы также можете создать диспетчера типа:

public ActionResult DoSomething(string action, string param1, string param2)
{
    switch (action)
    {
        case "update":
            return UpdateAction(param1, param2);
        case "remove":
            return DeleteAction(param1);
    }
}

Вы можете видеть, что UpdateAction требует 2 параметра, а DeleteAction просто требуется один.

0
ответ дан Matt 26 August 2018 в 09:32
поделиться

Если это попытка использовать одно действие GET для нескольких представлений, которые POST для нескольких действий с разными моделями, попробуйте добавить действие GET для каждого действия POST, которое перенаправляет на первый GET, чтобы предотвратить обновление 404.

Длинный снимок, но общий сценарий.

-1
ответ дан Panos Roditakis 26 August 2018 в 09:32
поделиться

Нет, Нет и Нет. Идите и попробуйте код контроллера ниже, где мы загрузили «LoadCustomer».

public class CustomerController : Controller
    {
        //
        // GET: /Customer/

        public ActionResult LoadCustomer()
        {
            return Content("LoadCustomer");
        }
        public ActionResult LoadCustomer(string str)
        {
            return Content("LoadCustomer with a string");
        }
    }

Если вы попытаетесь вызвать действие «LoadCustomer», вы получите ошибку как показанном на рисунке ниже.

enter image description here [/g1]

Полиморфизм является частью программирования на C #, а HTTP - протоколом. HTTP не понимает полиморфизм. HTTP работает над концепцией или URL-адресом, а URL-адрес может иметь только уникальное имя. Таким образом, HTTP не реализует полиморфизм.

Чтобы исправить то же самое, нам нужно использовать атрибут «ActionName».

public class CustomerController : Controller
    {
        //
        // GET: /Customer/

        public ActionResult LoadCustomer()
        {
            return Content("LoadCustomer");
        }

        [ActionName("LoadCustomerbyName")]
        public ActionResult LoadCustomer(string str)
        {
            return Content("LoadCustomer with a string");
        }
    }

Итак, теперь, если вы вызываете URL-адрес «Клиент» / LoadCustomer "действие" LoadCustomer "будет вызываться и со структурой URL" Customer / LoadCustomerByName "вызывается" LoadCustomer (string str) ".

enter image description here [/g2]

enter image description here [/g3]

Вышеупомянутый ответ я взял из этой статьи кодепроекта -> Перегрузка действием MVC

17
ответ дан Shivprasad Koirala 26 August 2018 в 09:32
поделиться

Да. Я смог сделать это, установив атрибут HttpGet / HttpPost (или эквивалентный AcceptVerbs) для каждого метода контроллера в нечто отличное, то есть HttpGet или HttpPost, но не оба. Таким образом, он может указывать на основе типа запроса, какой метод использовать.

[HttpGet]
public ActionResult Show()
{
   ...
}

[HttpPost]
public ActionResult Show( string userName )
{
   ...
}

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

67
ответ дан tvanfosson 26 August 2018 в 09:32
поделиться

Насколько я знаю, вы можете использовать один и тот же метод при использовании разных методов http.

i.e.

[AcceptVerbs("GET")]
public ActionResult MyAction()
{

}

[AcceptVerbs("POST")]
public ActionResult MyAction(FormResult fm)
{

}
13
ответ дан Will 26 August 2018 в 09:32
поделиться

Я тоже сталкивался с такой же проблемой в своем приложении. Без Modifiyig любой информации о методе я предоставил [ActionName («SomeMeaningfulName»)] в Action Action. проблема решена

[ActionName("_EmployeeDetailsByModel")]
        public PartialViewResult _EmployeeDetails(Employee model)
        {
            // Some Operation                
                return PartialView(model);
            }
        }

[ActionName("_EmployeeDetailsByModelWithPagination")]
        public PartialViewResult _EmployeeDetails(Employee model,int Page,int PageSize)
        {

                // Some Operation
                return PartialView(model);

        }
1
ответ дан ಅನಿಲ್ 26 August 2018 в 09:32
поделиться
Другие вопросы по тегам:

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