从控制器打开MVC视图到新窗口

63

有没有办法从控制器操作中打开一个视图在新窗口中?

public ActionResult NewWindow()
{
    // some code
    return View();
}

怎样才能使NewWindow.cshtml视图在一个新的浏览器标签中打开?

我知道如何在视图中的链接中实现它 - 这不是问题。但有没有人想到过从控制器操作中实现它的方法?

8个回答

88

这不能在控制器内部完成,而是需要在您的视图(View)中完成。 据我所见,你有两个选项:

  1. 使用"_blank"属性修饰您的链接(示例使用HTML助手和纯HTML语法)

    • @Html.ActionLink("链接文本", "Action", new {controller="Controller"}, new {target="_blank"})
    • <a href="@Url.Action("Action", "Controller")" target="_blank">链接文本</a>
  2. 使用Javascript打开新窗口

    window.open("链接URL")


1
如果我想从链接中在新窗口中打开视图,我会使用以下代码:@Html.ActionLink("linkText", "Action", "Controller", new { target="_blank" }。我还没有测试将控制器作为对象路由值传递的情况,为什么要这样做呢?但这不是问题所在。你确实用“无法完成”回答了原始问题,所以我会将其标记为答案。 - Joe
1
@Joe - 这只是我使用的Html.ActionLink重载选择,其签名如下 - Html.ActionLink(string linkText, string Action, object routeValues, object htmlAttributes) - 但这只是个人选择,您可以使用任何接受htmlAttributes参数的重载。 - Tommy
有没有办法为新窗口定义尺寸?(使用 Razor) - phougatv
1
@barnes - 我所知道的唯一一种要求弹出窗口具有特定大小的方法是通过JavaScript。原因:大多数情况下,浏览器决定如何处理窗口。JavaScript是您整个Web应用程序堆栈中唯一可以实际操作客户端浏览器的部分。 - Tommy
1
这是你所指的吗?链接。如果您知道更好的方法,请分享。 - phougatv
显示剩余3条评论

46

你也可以在表单中使用Tommy的方法:

@using (Html.BeginForm("Action", "Controller", FormMethod.Get, new { target = "_blank" }))
{
//code
}

在我找到的所有可能解决方案中,这是我认为最好的。因为它使用了MVC框架,所以它是最简单的。 - mcampos
默认的提交操作是发布并提交最终操作。我们如何在不丢失主窗口数据的情况下,将表单发布但启动部分视图(因此在单独的窗口中)?简单的场景是主表单提交是提交客户端暂存的n个文件,用户选择并预览第一个文件。但是用户可能需要在尚未提交表单的情况下预览某个文件。在这种情况下,用户可能需要在新标签页中查看该文件。那么我们如何为具有不同视图的表单拥有两个POST方法? - AKS
如果您知道请求始终应在新窗口(仅)中打开,则此方法效果很好。如果您可能在操作方法(通常是POST操作)的服务器端检测到错误,则不希望返回的视图在新标签页中...您需要使用“return View(model)”将错误添加到ModelState中。如果您的表单使用POST请求类型,请小心使用新窗口。 - IdahoB
AKS - 使用单个POST,但向您的模型添加标识符,以便您的回传操作可以检测您打算执行的操作,例如SelectedAction枚举(或bool或....)。即使回传本身可能会重定向到其他操作,将GET和POST操作方法结合起来也是一个好习惯。 - IdahoB

8
你问错了问题。代码后端(控制器)与前端无关。实际上,这就是MVC的优势——将代码/概念与视图分离。
如果你想要一个操作在新窗口中打开,那么链接到该操作的链接需要告诉浏览器在点击时打开一个新窗口。
伪代码例子:<a href="NewWindow" target="_new">Click Me</a> 就是这样。将链接的目标设置为该操作即可。

POST 控制器方法的视图代码是什么样子的?在视图中通过传递表单对象等进行提交操作。以上默认使用 GET 方法执行操作。 - AKS
如果你必须使用POST方法完成它,那么你需要创建一个<form method="post" action="url" target="_new">。但是需要注意的是,这只是前端解决方案,与后端无关。 - Eli Gassert

4

你可以使用一些技巧来“模拟”你想要的效果:

1)通过ajax从视图中调用你的控制器。 2)返回你的视图。

3)在你的$.ajax请求的成功(或者也许是错误!错误对我有用!)部分使用以下类似内容:

$("#imgPrint").click(function () {
        $.ajax({
            url: ...,
            type: 'POST', dataType: 'json',
            data: $("#frm").serialize(),
            success: function (data, textStatus, jqXHR) {
                //Here it is:
                //Gets the model state
                var isValid = '@Html.Raw(Json.Encode(ViewData.ModelState.IsValid))'; 
                // checks that model is valid                    
                if (isValid == 'true') {
                    //open new tab or window - according to configs of browser
                    var w = window.open();
                    //put what controller gave in the new tab or win 
                    $(w.document.body).html(jqXHR.responseText);
                }
                $("#imgSpinner1").hide();
            },
            error: function (jqXHR, textStatus, errorThrown) {
                // And here it is for error section. 
                //Pay attention to different order of 
                //parameters of success and error sections!
                var isValid = '@Html.Raw(Json.Encode(ViewData.ModelState.IsValid))';                    
                if (isValid == 'true') {
                    var w = window.open();
                    $(w.document.body).html(jqXHR.responseText);
                }
                $("#imgSpinner1").hide();
            },
            beforeSend: function () { $("#imgSpinner1").show(); },
            complete: function () { $("#imgSpinner1").hide(); }
        });            
    });      

2
您可以按照以下方式使用:最初的回答
public ActionResult NewWindow()
{
    return Content("<script>window.open('{url}','_blank')</script>");
}

0
@Html.ActionLink("linkText", "Action", new {controller="Controller"}, new {target="_blank",@class="edit"})

   script below will open the action view url in a new window

<script type="text/javascript">
    $(function (){
        $('a.edit').click(function () {
            var url = $(this).attr('href');
            window.open(url, "popupWindow", "width=600,height=800,scrollbars=yes");
            });
            return false;
        });   
</script>

0

我在我的控制器中分配了Javascript:

model.linkCode = "window.open('https://www.yahoo.com', '_blank')";

在我看来:

@section Scripts{
    <script @Html.CspScriptNonce()>

    $(function () {

        @if (!String.IsNullOrEmpty(Model.linkCode))
        {
            WriteLiteral(Model.linkCode);
        }
    });

这将打开一个带有链接的新标签页,并跳转到它。

有趣的是,本地运行时它会触发弹出窗口拦截器,但在服务器上似乎可以正常工作。


0

我曾看到过这样的操作,假设"NewWindow.cshtml"文件在你的"主页"文件夹中:

string url = "/Home/NewWindow";
return JavaScript(string.Format("window.open('{0}', '_blank', 'left=100,top=100,width=500,height=500,toolbar=no,resizable=no,scrollable=yes');", url));

或者

return Content("/Home/NewWindow");

如果你只想在选项卡中打开视图,你可以使用JavaScript点击事件来呈现部分视图。以下是NewWindow.cshtml的控制器方法:

public ActionResult DisplayNewWindow(NewWindowModel nwm) {
    // build model list based on its properties & values
    nwm.Name = "John Doe";
    nwm.Address = "123 Main Street";
    return PartialView("NewWindow", nwm);
}

你页面上调用它的标记应该像这样:

<input type="button" id="btnNewWin" value="Open Window" />
<div id="newWinResults" />

而且JavaScript(需要jQuery):

var url = '@Url.Action("NewWindow", "Home")';
$('btnNewWin').on('click', function() {
    var model = "{ 'Name': 'Jane Doe', 'Address': '555 Main Street' }"; // you must build your JSON you intend to pass into the "NewWindowModel" manually
    $('#newWinResults').load(url, model); // may need to do JSON.stringify(model)
});

请注意,此JSON将覆盖上述C#函数中的内容。我只是为了演示如何硬编码值而将其放在那里。
(改编自在ASP.NET MVC中单击按钮呈现部分视图

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接