【问题标题】:ASP.net MVC Controller will not return viewASP.net MVC 控制器不会返回视图
【发布时间】:2012-10-16 02:51:12
【问题描述】:

对 ASP.net 还是有点陌生​​,我遇到了这个奇怪的问题。这是一个非常基本的场景,但有些事情发生了,我无法弄清楚。 Deploy 应该返回一个名为 Deploy 的视图,该视图被键入到模型 CompiledAppModel。但是,当您在视图中单击安装时,尽管调用了 return View() 方法,但它永远不会离开页面。有什么想法吗?

这是我的控制器:

[HttpPost]
public ActionResult Deploy(string key_name, string custom_folder = "")
{
    string userId = Membership.GetUser().ProviderUserKey.ToString();
    UserDataModel user_info = _user_data_service.getUserDataByPrimaryIDNoDB(userId, HttpContext.Cache);
    log.Trace("Deploy was called. key_name:" + key_name + " UID: " + user_info.UID);

    // first we'll call the info to install remote application
    bool serviceInstall = _fms_app_service.DeployFmsApp(user_info, key_name, custom_folder);

    // then we'll call to generate client side info
    bool clientInstall = _fms_app_service.CompileClientApp(user_info, key_name);

    var model = _fms_app_service.getInstalledAppInfo(user_info, key_name);
    if (serviceInstall && clientInstall)
    {
        return RedirectToAction("Deploy", model);
    }

    return View("Error");
}

我的看法:

@model IEnumerable<Models.Applications.FmsAppModel>

@foreach (var item in Model) {
    <div class="col">
        <h2>@Html.DisplayFor(modelItem => item.friendly_name)</h2>
        <p>@Html.DisplayFor(modelItem => item.app_description)</p>
        <p><strong>Tags:</strong> @Html.DisplayFor(modelItem => item.app_type)</p>

        <a href="#" class="btn btn-primary install-app" data-key-name="@(item.key_name)">Install</a>

        @Html.ActionLink("Details", "Detailss", new {  id=item.app_id  })
    </div>
}
</div>

<script type="text/javascript">
   (function () {
        $('.install-app').on('click', function (e) {
            e.preventDefault();
            var data_key_name = $(this).data('key-name');
            //ajax install app
            $.ajax({
                type: "POST",
                url: '@Url.Action("Deploy")',
                data: {
                    key_name: data_key_name
                }
            });
        });
    })();
</script>

还有模特。

public class CompiledAppModel
{
    [Display(Name = "Admin URL")]
    public string adminURL { get; set; }

    [Display(Name = "Viewer URL")]
    public string viewerURL { get; set; }

    [Display(Name = "Embed URL")]
    public string embedURL { get; set; }
}

【问题讨论】:

    标签: c# asp.net-mvc


    【解决方案1】:

    我假设您确实想在进行 ajax 调用后进行重定向。

    据我所知,您必须实现自定义 ActionResult,例如:

    public class AjaxAwareRedirectResult : RedirectResult
    {       
        public AjaxAwareRedirectResult(String url)
            : base(url)
        {
        }
    
        public override void ExecuteResult(ControllerContext context)
        {
            if ( context.RequestContext.HttpContext.Request.IsAjaxRequest() )
            {
                String destinationUrl = UrlHelper.GenerateContentUrl(Url, context.HttpContext);
    
                JavaScriptResult result = new JavaScriptResult()
                {
                    Script = "window.location='" + destinationUrl + "';"
                };
                result.ExecuteResult(context);
            }
            else
            {
                base.ExecuteResult(context);
            }
        }
    }
    

    在您的控制器中,只需执行以下操作:

        [HttpPost]
    public ActionResult Deploy(string key_name, string custom_folder = "")
    {
        string userId = Membership.GetUser().ProviderUserKey.ToString();
        UserDataModel user_info = _user_data_service.getUserDataByPrimaryIDNoDB(userId, HttpContext.Cache);
        log.Trace("Deploy was called. key_name:" + key_name + " UID: " + user_info.UID);
        // first we'll call the info to install remote application
        bool serviceInstall = _fms_app_service.DeployFmsApp(user_info, key_name, custom_folder);
        // then we'll call to generate client side info
        bool clientInstall = _fms_app_service.CompileClientApp(user_info, key_name);
    
        var model = _fms_app_service.getInstalledAppInfo(user_info, key_name);
        if (serviceInstall && clientInstall)
        {
            return RedirectToAction("Deploy", model);
        }
        return AjaxAwareRedirectResult("/foo");
    }
    

    但是,正如我所说,这只是我假设您真的想在 ajax 调用之后重定向。

    【讨论】:

      【解决方案2】:

      在我看来,就像您使用 Ajax 调用将您的帖子发回服务器一样,在这种情况下,如果没有一点额外的工作,结果就不会呈现到页面上。您可以在 ajax 调用上定义一个成功处理程序,以便在 ajax 调用返回时采取行动。所以像

      <script type="text/javascript"> (function () {
          $('.install-app').on('click', function (e) {
              e.preventDefault();
              var data_key_name = $(this).data('key-name');
              //ajax install app
              $.ajax({
                  type: "POST",
                  url: '@Url.Action("Deploy")',
                  data: {
                      key_name: data_key_name
                  },
                  success: function(data) { alert(data) }
              });
          });
      })();
      

      当请求完成时,将通过 ajax 调用返回的 HTML 向您发出警报消息。

      我还会使用 Firebug 或 Chrome 中的开发人员工具来查看返回的 HTML,如果服务器上发生异常,您应该能够使用这些工具更详细地检查这一点。

      【讨论】:

        【解决方案3】:

        在 ajax 调用之后执行 HTTP 重定向可能没有多大意义。您只需使用 html 表单和常规 POST 即可做到这一点。

        但是,如果您确实需要重定向并且仍然希望通过 AJAX 进行 POST,您可以通过返回 Json 而不是重定向来实现,如以下答案中所建议的:

        在这种情况下,您可以在 Json 对象中返回目标操作 url,并在成功处理程序中使用该信息,如 Neil 的回答所示。

        另外,请记住 RedirectToAction 只是一个 302 重定向,因此,它不会直接呈现视图,因此您不会将完整的 ViewModel 传递给它,而只是浏览器发出 GET 的 Action Url到。

        目标 GET 操作应该是负责获取您的已安装应用信息并将其作为参数传递给视图的操作,遵循 POST-REDIRECT-GET pattern

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-03-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-02-28
          • 1970-01-01
          • 2022-01-10
          相关资源
          最近更新 更多