【问题标题】:MVC implicit redirect to another JsonResult action possible?MVC 可能隐式重定向到另一个 JsonResult 操作?
【发布时间】:2017-02-10 09:58:36
【问题描述】:

我有一个动作,根据foo 的值,我想重定向到一个特定的动作:

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

 public JsonResult SecondAction() { }

这不起作用,因为RedirectToAction 不会返回JsonResult 并且无法转换(据我所知)。

我知道我可以在这里使用一些条件,即 foo 上的 switch 以确定要调用的方法,但我想尽可能保持隐含。

【问题讨论】:

  • 将返回类型从JsonResult更改为ActionResultJsonResultRedirectResult都继承自哪个?您并不总是从该方法返回 JSON,因此您使用的返回类型不适合。
  • 嗯,我猜你正在为 AJAX 调用创建一个动作?如果是,那么“重定向”它的逻辑是什么?
  • 使用 ActionResult 代替 JsonResult .. 无论如何,您都可以使用当前操作中的 return Json(yourData, JsonRequestBehavior.AllowGet)SecondAction 返回 JSON 作为结果
  • @Kamo - 好问题,它是远程验证 - 我如何验证取决于 foo 的值。
  • 在您的情况下,我只需将此验证逻辑封装在方法/类/服务中,并摆脱使用重定向来处理您的操作中的调用。

标签: c# asp.net-mvc-5 jsonresult


【解决方案1】:

RedirectToAction 以 Http 302 响应,指示用户的浏览器请求不同的 URI。

您只需将方法的返回类型更改为ActionResult,您的代码就会按预期工作。

【讨论】:

    【解决方案2】:

    因此,如果我理解正确,您希望根据传递给方法的参数值执行不同的操作和不同的逻辑。

    您可以这样做的一种方法是使用路由系统,但我只建议您在参数的可能值大小可管理时选择此方法。

    然后在您的 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 处理的 foo 的每个可能值都有一个自己的 URL,这同样适用于应该由逻辑 #2 处理的值。

    我认为您已经可以看到,这很远,虽然隐含,但它绝不比在您指出要避免的操作中简单地实施决策更易于维护或通常更好。你所要求的听起来像是 C# 不允许的“基于值的重载”,上面的代码是一种让路由引擎为你做的肮脏的解决方法,虽然它不是实际的重载,它只是根据硬编码的可能值映射到不同的操作。

    【讨论】:

    • 谢谢,但理想情况下,我希望按照 OP 中的规定避免这种情况。我想隐含地调用该方法,并且使用 MVC 路由似乎是我最好的选择,而不是反射或一些冗长的条件。不过你是对的,这是一个很好的方法。
    • 请解释您的更改,而不是说“怎么样”,让读者来猜测您的意思。另外,这个问题是关于返回类型的,你没有改变。
    • 老实说,我不明白为什么做一个额外的往返(重定向导致客户端这样做)比实现一个简单的决策逻辑更好。
    • 我不知道重定向结果会告诉客户端,而是想重定向当前请求。事实上,我说的不对吗?
    • 这只有在foo 的可能值是可管理的大小时才有可能,然后您可以使用路由系统,但仍然必须手动输入可能的 url。
    【解决方案3】:

    您应该返回 SecondAction 本身,而不是 RedirectToAction。

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

    【讨论】:

    • 请勇敢地给出拒绝投票的理由。
    【解决方案4】:

    除了我上面描述的基于路由的方法之外,您还应该看看ActionMethodSelectorAttribute 属性。这是一个属性,除其他外,HttpPostHttpGet 都基于该属性,并允许您通过返回布尔值来控制操作是否有效。这是您需要覆盖的方法:

    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) { ... }
    

    如果值适合动作,这将允许执行动作。属性中使用的数字是为了告诉您使用哪种决策逻辑,如果您更清楚,您也可以为每个操作实现一个属性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-22
      • 2014-12-31
      • 1970-01-01
      • 1970-01-01
      • 2014-10-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多