ActionResult с разными параметрами

У меня простой вопрос о поведении ActionResult в ASP.NET MVC.

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

public class CarController : Controller
{
    [AuthorizeUser(AccessLevel = "New")]
    public ActionResult New()
    {
       return View("New");
    }

    [AuthorizeUser(AccessLevel = "New?type=2")]
    public ActionResult New(string type)
    {
       return View("NewCarType2");
    }
}

Я знаю, что могу переименовать второй результат действия другим именем, но хочу ли я оставить его «новым»?

Я пробовал с route.maps без успеха. Я думаю сделать это:

 public class CarController : Controller
{
    public ActionResult New (string type) {
        if(!string.IsNullOrEmpty(type) && type.Equals("2")) {
            return NewCarType2()
        else
            return New()
        }
    }
    [AuthorizeUser(AccessLevel = "New?type=2")]
    private ActionResult NewCarType2()
    {
        return View("NewCarType2");
    }
    [AuthorizeUser(AccessLevel = "New")]
    private ActionResult New()
    {
        return View("New");
    }
}

но атрибут для авторизации пользователя игнорируется.. также с публичной подписью метода и атрибутом [NoAction].

Единственный способ сделать то, что я хочу, - это наследование классов:

public class CarController : Controller
{
    public virtual ActionResult New(string type)
    {
        if (!string.IsNullOrEmpty(type) && type.Equals("2"))
            return RedirectToAction("NewCarType2", "CarOverride");
        else
            return RedirectToAction("New", "CarOverride");
    }
}  
public class CarOverrideController : CarController
{
    [AuthorizeUser(AccessLevel = "New?type=2")]
    public ActionResult NewCarType2(string type)
    {
        return View("NewCarType2");
    }
    [AuthorizeUser(AccessLevel = "New")]
    public override ActionResult New(string type)
    {
        return View("New");
    }
 }

Но является ли это правильным способом управления этой ситуацией (часть записи имени ActionResults отличается)?


person lele.lic    schedule 25.03.2015    source источник
comment
На самом деле это концепция перегрузки метода stackoverflow.com/a/436935/3354492 Этот пост ответит на ваши вопросы.   -  person Puneet    schedule 25.03.2015
comment
Другой способ справиться с этим может состоять в том, чтобы определить одно как действие [HttpGet], а другое как действие [HttpPost]. Примечание: не уверен, что это то, что вы хотите здесь, но это работает таким образом (в любом случае, параметры должны быть разными)   -  person Emmanuel M.    schedule 25.03.2015
comment
Определенно предлагаю НЕ использовать наследование здесь   -  person timothyclifford    schedule 25.03.2015
comment
Какую логику выполняет ваш атрибут AuthorizeUser?   -  person timothyclifford    schedule 25.03.2015
comment
@timothyclifford с атрибутом AuthorizeUser я проверяю роль пользователя и имеет ли он право отображать страницу (методом IsInRole)   -  person lele.lic    schedule 25.03.2015


Ответы (2)


Есть 2 возможности сделать то, что вы хотите.

Как ответил Пунит в комментарии, вы можете перегрузить метод в контроллере, как указано в этот пост.

[ActionName("MyOverloadedName")]

or

Вы можете определить атрибут Route в методе контроллера и направить действие с другого URL-адреса на этот метод. Для получения дополнительных сведений перейдите к ссылке Учебное пособие по ASP.NET.

 [Route("URL")]
public ActionResult New(string type) { ... }
person greenhoorn    schedule 25.03.2015
comment
Но с первой возможностью я должен вызвать 2 разных URL-адреса (новый и новыйПерегруженный), верно? Могу ли я иметь тот же URL (новый) и выбор будет сделан по наличию или меньшему количеству параметра? - person lele.lic; 25.03.2015
comment
Другая возможность — определить 1 метод с необязательным параметром. Таким образом, у вас есть только 1 действие в вашем контроллере, и либо ваш параметр равен нулю, либо установлен по умолчанию (если пользователь не предоставляет данные). Это то, что вы хотите? msdn.microsoft.com/en-us/ библиотека/dd410269%28v=vs.100%29.aspx - person greenhoorn; 25.03.2015
comment
Да, я думаю, это способ.. Я сделаю один метод с необязательным параметром, и если значение будет пустым, я проверю авторизацию для одной роли, иначе для другой. Если результат проверки будет верным, я покажу страницу. Вместо этого с [Маршрут (URL)] я могу указать URL-адрес, например «Автомобиль/Новый? Тип = 2», и связанное с ним действие отвечает только на это? - person lele.lic; 25.03.2015
comment
@DanieleLicini Да, я это и имел в виду. Надеюсь, это сработает для вас :) - person greenhoorn; 25.03.2015

Я бы спросил, зачем вам нужны два маршрута с одинаковым именем, которые делают две разные вещи?

Если все, что делает ваш атрибут AuthorizeUser, — это проверка роли пользователя, почему бы не сделать что-то подобное:

public ActionResult New(string type)
{
    if (!string.IsNullOrWhiteSpace(type) && User.IsInRole("YOUR-ROLE-HERE"))
    {
        // Display NewCarType2 view if type requested and user is in correct role
        return View("NewCarType2");
    }

    // Default to New view if no type requested or user not in role
    return View("New");
}

Это перехватит запросы /new и /new?type=foo.

person timothyclifford    schedule 26.03.2015
comment
Два маршрута делают почти одно и то же: например, визуализация контента отличается. Ваш ответ - это то, что я думаю сделать, но единственная разница в том, что атрибут AuthorizeUser не только проверяет роль пользователя с помощью IsInRole. Я возьму логику этой авторизации в метод и буду использовать ее в ActionResult. - person lele.lic; 30.03.2015
comment
Если они делают почти одно и то же, вы, вероятно, можете возразить, что они должны идти по одному и тому же маршруту. Вы говорите, что это отвечает на ваш вопрос или вам нужна дополнительная информация? - person timothyclifford; 30.03.2015