2017-02-10 5 views
0

У меня есть одно действие, и в зависимости от значения foo Я хочу, чтобы перенаправить на определенное действие:Возможна переориентация MVC на другое действие JsonResult?

public JsonResult FirstAction(string foo) // foo == "SecondAction" 
{ 
    return RedirectToAction(foo); 
} 

public JsonResult SecondAction() { } 

Это не работает, так как RedirectToAction не возвращает JsonResult и нет никакого способа (насколько мне известно).

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

+1

Изменить тип возврата с 'JsonResult' на' ActionResult', из которого наследуются как 'JsonResult', так и' RedirectResult'? Вы не всегда возвращаете JSON из этого метода, так что возвращаемый тип, который вы используете, не подходит. – CodeCaster

+2

Да, я думаю, вы создаете действие для звонка AJAX? Если да, то в чем логика «перенаправления»? – Kamo

+0

использовать 'ActionResult' вместо' JsonResult' .. вы можете в любом случае вернуть JSON в качестве результата с помощью 'return Json (yourData, JsonRequestBehavior.AllowGet)' из вашего текущего действия или 'SecondAction' –

ответ

0

RedirectToAction отвечает Http 302, в котором пользовательский браузер запрашивает другой URI.

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

+0

@MikeDebela спасибо. – Jamiec

0

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

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

Тогда в ваших RouteConfig.cs файл:

public static void RegisterRoutes(RouteCollection routes) 
{ 
    // ... other routes 

    string[] possibleValueSet1 = new[] { ... }; 
    string[] possibleValueSet2 = new[] { ... }; 

    for (int i = 0; i < possibleValueSet1.Length; ++i) 
    { 
     routes.MapRoute(
      name: "YourActionWithValueSet1_" + i.ToString(), 
      url: "ControllerName/FirstAction/" + possibleValueSet1[i], 
      defaults: new { controller = "ControllerName", action = "FirstAction", foo = possibleValueSet1[i] } 
     ); 
    } 

    for (int i = 0; i < possibleValueSet2.Length; ++i) 
    { 
     routes.MapRoute(
      name: "YourActionWithValueSet2_" + i.ToString(), 
      url: "ControllerName/SecondAction/" + possibleValueSet2[i], 
      defaults: new { controller = "ControllerName", action = "SecondAction", foo = possibleValueSet2[i] } 
     ); 
    } 

} 

Таким образом, каждое возможное значение обув, которые должны быть обработаны с помощью логики # 1, будет иметь собственный URL, то же самое относится и к значениям который должен обрабатываться логикой № 2.

Я думаю, вы уже можете видеть, что это идет далеко, а в то же время неявное, оно никоим образом не поддерживает или вообще не лучше, чем просто реализовать решение внутри действия, о котором вы указали, которого вы хотели избежать. То, о чем вы просите, звучит как «перегрузка по принципу ценности», который C# не разрешает, приведенный выше код является своего рода грязным обходным решением, позволяющим движку маршрутизации сделать это за вас, хотя это не фактическая перегрузка, это просто сопоставление различных действий на основе жестко заданных значений.

+0

Спасибо, но в идеале я хотел бы избежать этого, как указано в OP. Я хотел бы быть неявным при вызове метода, и использование MVC-маршрутов кажется моим лучшим вариантом, а не отражением или некоторым подробным условием. Вы правы, но это прекрасный подход. –

+0

Пожалуйста, объясните свои изменения вместо того, чтобы сказать «как насчет», оставив читателю догадываться, что вы имеете в виду. Кроме того, этот вопрос касается типа возврата, который вы не изменили. – CodeCaster

+0

Ну, если честно, я не понимаю, зачем делать лишний кругооборот (что перенаправление заставляет клиента делать) лучше, чем реализовать простую логику принятия решения. –

0

Вместо того, чтобы делать RedirectToAction, вы должны вернуть сам SecondAction.

public JsonResult FirstAction(string foo) // foo == "SecondAction" 
{ 
    return SecondAction(); 
} 

public JsonResult SecondAction() { } 
+0

Пожалуйста, будьте мужественны, чтобы дать основания для downvoting. –

0

Помимо подхода маршрута на основе я описал выше, вы также должны взглянуть на атрибут ActionMethodSelectorAttribute. Это атрибут, на котором, помимо прочего, установлены HttpPost и HttpGet и позволяет вам контролировать, действительно ли действие действительно, возвращая логическое значение. Это метод, который вы должны переопределить:

public abstract bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo); 

Тогда вы могли бы реализовать что-то вроде этого:

public class ValidBasedOnFoo 
{ 
    public int MethodNum { get; set; } 

    public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo) 
    { 
     var foo = controllerContext.HttpContext.Request["foo"] as string; 

     if (MethodNum == 1) 
      return YourDecisionLogicForFirstAction(foo); 
     else if (MethodNum == 2) 
      return YourDecisionLogicForSecondAction(foo); 
     else throw new InvalidOperationException("Unknown method number."); 
    } 
} 

Тогда в контроллере, действия как таковые:

[ValidBasedOnFoo(1)] 
public JsonResult FirstAction(string foo) { ... } 

[ValidBasedOnFoo(2)] 
public JsonResult SecondAction(string foo) { ... } 

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

Смежные вопросы