asp.net mvc窗口以自定义属性和模型打开

asp.net mvc window open with custom properties and model

本文关键字:模型 自定义属性 net mvc 窗口 asp      更新时间:2023-09-26

我有一个带有submit的表单,它打开了一个pdf文件

@using (Html.BeginForm(null, null, new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, htmlAttributes: new { @class = "custom" }))
  {
   ......
   @Html.TextboxFor(m=>m.Name)
   <input type="submit" value="Open File"/>
  }

我希望这能在新窗口中打开文件
-我需要将模型传递给post方法(解决方案1)
-我可以打开新窗口,但我也需要命名它,并在同一窗口中重新打开一个文件。(解决方案2)

我有两种可能的解决方案,但我想结合它们的特点。

solution1:

@using (Html.BeginForm(null, null, new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, htmlAttributes: new { @class = "custom" }))
  {
   ......
   @Html.TextboxFor(m=>m.Name)
   <input type="submit" value="Open File" formtarget="_blank"/>
  }

solution2:

    @using (Html.BeginForm(null, null, new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, htmlAttributes: new { @class = "custom" }))
  {
    ......
    @Html.TextboxFor(m=>m.Name)
    <a href="#" onclick="fileDownload()" >Download File</a>
  }
<script type="text/javascript">
    function fileDownload() {
        var title = "my file";
        var win = window.open("@Url.Action("DisplayFile", "MyFile")?name=@Model.Name", title);
        win.onload = function () { this.document.title = title; };
    };
</script>

Solution2中,我不想将模型作为url参数传递,我希望它是POST调用
Solution1中,我似乎无法自定义新窗口的title

任何一种解决方案对我来说都很好,所以如果有人能想出其中一种或组合,我就用它。

EDIT:使用样本模型值更新

有几种方法可以做到这一点。首先,您可以使用解决方案1中的代码,但在控制器中添加一个参数以接受新页面的标题。该值可以通过表单上的隐藏字段进行设置(您可以通过javascript进行操作)。然后,您可以在ViewBag上设置一个属性,并在标题中输出:

HTML:

<head>
    <title>@ViewBag.Title</title>
</head>

形式:

@using (Html.BeginForm(null, null, new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, htmlAttributes: new { @class = "custom" }))
{   
    @Html.TextBoxFor(m=>m.Name)
    @Html.Hidden("Title", "My File")
    <input type="submit" value="Open File" formtarget="_blank" />
}

控制器:

[HttpPost]
public ActionResult Index(SomeClass model, string title)
{
    ViewBag.Title = title;
    //do something profound..
    return View(model);
}

或者,您可以截取submit并通过javascript自己执行post,然后将结果手动写入新窗口。为了方便起见,我在下面使用了jQuery作为示例,但如果你不能/不想使用jQuery,这在纯javascript中是可能的。我给了表单一个id,这样我就可以访问提交事件:

形式:

@using (Html.BeginForm(null, null, new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, htmlAttributes: new { @class = "custom", id="myForm" }))
{
    @Html.TextBoxFor(m => m.Name)
    <input type="submit" value="Open File" />
}

脚本:

$(document).on('submit', '#myForm', function (e) {
    $.ajax({
        url: $(this).attr('action'),
        type: 'POST',
        data: $(this).serialize(),
        success: function (response) {
            var win = window.open("about:blank", "_blank");
            var title = "my file";
            win.onload = function () {
                this.document.write(response);
                this.document.title = title;
            };
        }
    });
    return false;
});

在浏览器中编写PDF文件很棘手,尤其是跨浏览器。您需要确保它具有正确的Content标头,尤其是content-type,它需要是application/pdf。您无法通过JavaScript进行设置,因此服务器端渲染是您的最佳选择。请注意,客户端选项很少,但并非所有浏览器都能很好地运行。

其次,您的第一个解决方案是好的,因为不同的浏览器在显示PDF文件时处理窗口标题的方式不同。现代浏览器读取PDF文档的元数据并显示Title属性(如果有)。如果没有,则只显示文件名。旧浏览器可能会显示文件名(如果有)或临时文件路径(如果没有其他可用路径)。

由于您没有加载HTML文档,因此document.title在这种情况下没有任何意义。这是默认的浏览器行为,您无法控制它,尤其是以跨浏览器一致工作的方式。

如果PDF标题不在您的控制范围内,您可以通过设置来控制显示的文件名(假设PDF没有标题或由于任何原因,浏览器不显示它)

Content-Disposition: inline; filename=<your title.pdf>

此标头需要在指定Content-Type之前指定,并且只能包含ASCII字符。

另一种选择(显示自定义标题)是在目标页面的iFrame中显示PDF。您可以移除iframe的边框,移除body元素的填充/边距,并调整iframe高度/宽度以匹配窗口的高度/宽度,使其看起来像只显示PDF。请参阅此演示和相应的源代码(在iFrame中显示PDF,使其看起来像是在主窗口中加载的)。

HTML

<!DOCTYPE html>
<html>
<head>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
  <meta charset="utf-8">
  <title>Look ma - custom PDF title!</title>
</head>
<body>
  <div id=wrapper>
    <iframe src="http://www.cs.tut.fi/~jkorpela/latin9.pdf">
    </iframe>
  </div>
</body>
</html>

CSS

body {
    margin: 0px;
    padding: 0px;
}
div#wrapper {
    position: fixed;
    width: 100%;
    height: 100%;
}
div#wrapper > iframe {
    display: block;
    width: 100%;
    height: 100%;
    border: none;
}