4

我有以下代码:

protected void gv_inbox_RowCommand(object sender, GridViewCommandEventArgs e)
{
    int index = Convert.ToInt32(e.CommandArgument);

    if (e.CommandName == "sign")
    {
        Session["TransYear"] = int.Parse(((HiddenField)gv_inbox.Rows[index].Cells[1].FindControl("HDN_TransYear")).Value);
        Session["MailNumber"] = int.Parse(((HiddenField)gv_inbox.Rows[index].Cells[1].FindControl("HDN_MailNumber")).Value);
        Response.Redirect("Signature.aspx", false);
        //Response.Write("<script>");
        //Response.Write("window.open('Signature.aspx','_blank')");
        //Response.Write("</script>");
    }
}

我想在新选项卡或窗口中打开页面。注释代码会这样做,但是当refresh原始页面导致错误时Signature.aspx。如何在我的 gridview 的行命令事件中以正确的方式在新窗口或选项卡中打开。

4

6 回答 6

5

您要做的是使用ScriptManager来进行 JavaScript 调用。

您定义的 JavaScript 片段有效,但是,您需要负责ScriptManager为您执行它。

String js = "window.open('Signature.aspx', '_blank');";
ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "Open Signature.aspx", js, true);

using 的问题Response.Write是,在 期间PostBack,浏览器不会执行脚本标签。另一方面,在使用 时ScriptManager.RegisterClientScriptBlock,ASP.NETScriptManager会自动执行代码。

更新 - 2013/02/14

正如弗拉迪斯拉夫的回答所建议的那样,使用ClientScriptvs. ScriptManager; 区别在于ClientScript仅用于同步回发(no asp:UpdatePanel),而ScriptManager用于异步回发(使用asp:UpdatePanel)。

此外,根据以下作者的评论 - 将其包含asp:GridView在 anasp:UpdatePanel中将消除确认刷新的浏览器消息。同步回发(no)后刷新页面时asp:UpdatePanel,浏览器将重新发送最后一条命令,导致服务器再次执行相同的过程。

最后,当将 anasp:UpdatePanel与 结合使用时ScriptManager.RegisterClientScriptBlock,请确保将第一个和第二个参数更新为asp:UpdatePanel对象。

ScriptManager.RegisterClientScriptBlock(updatePanel1, updatePanel1.GetType(), "Open Signature.aspx", js, true);
于 2013-02-13T20:55:38.270 回答
4

首先,这里的练习是如何将简单的值从一个页面传递到另一个页面。

在您的情况下,这些只是键/值,因此您可以通过 GET 传递它们。

您需要呈现每一行,而不是命令按钮。

<a href="Signature.aspx?TransYear=value1&MailNumber=value2" target="_blank">
    Sign
</a>

在此示例中,value1 和 value2 是您分别写入 HDN_TransYear 和 HDN_MailNumber 的值。

在 Signature.aspx 中,如果您想使用会话变量,则必须执行以下操作:

Session["TransYear"]
Session["MailNumber"]

现在应该改成这样:

Request.QueryString["TransYear"]
Request.QueryString["MailNumber"]

这通常会满足您的要求。但...

如果您说此方法不安全,那么任何人都可以通过更改参数值来使用查询字符串变量,那么...

为每一行计算一个签名,将此签名作为第三个参数放在查询字符串中,并验证另一侧的值和签名。

如何计算签名,这取决于你。那是你的秘诀。有很多散列函数和加盐算法。

作为一个非常简单的例子:

string signature = CRC32(HDN_TransYear + "stuff that you only know" + HDN_MailNumber)

然后你的链接应该是这样的:

<a href="Signature.aspx?TransYear=2012&MailNumber=1&sig=8d708768" target="_blank">
    Sign
</a>

在 Signature.aspx 中,您使用来自查询字符串的值和“您只知道的东西”再次计算 CRC32 签名,并根据在查询字符串中作为参数传递的签名进行验证。

没有剧情。

于 2013-02-19T17:00:42.877 回答
2

为什么要在打开新窗口之前设置会话?

如果在打开新窗口后设置会话是可以的,我认为你可以在后面的代码中进行设置Signature.aspx,考虑到你已经将所需的参数作为查询字符串传递,正如@David 指出的那样。

于 2013-02-19T02:42:32.470 回答
2

我宁愿使用 ClientScript.RegisterStartupScript(this.GetType(), "Open Signature.aspx", js, true); ,你不需要刷新你的页面。页面从回发中恢复后,脚本块将触发。

只是一个建议:-在您的情况下是否可以使用 DataKeys 来检索 TransYear 和 MailNumber 的值而不是使用 HiddenFields

于 2013-02-14T12:53:16.507 回答
2

我们已经成功使用以下代码多年了。这几种方法是从一个更大的通用模块中提取出来的,但我想我已经包含了所有内容......

public class Utilities
{
    /// <summary>
    /// This will return the first parent of the control that is an update panel
    /// </summary>
    /// <param name="source">The source control</param>
    /// <returns>The first parent found for the control. Null otherwise</returns>
    public static UpdatePanel GetFirstParentUpdatePanel(Control source)
    {
        Page currentPage = source.Page;
        UpdatePanel updatePanel = null;
        Type updatePanelType = typeof(UpdatePanel);
        object test = source.Parent;
        while (test != null && test != currentPage)
        {
            // is this an update panel
            if (test.GetType().FullName == updatePanelType.FullName)
            {
                // we've found the containing UpdatePanel
                updatePanel = (UpdatePanel)test;
            }

            // check the next parent
            test = ((Control)test).Parent;
        } // next test

        return updatePanel;
    }

    /// <summary>
    /// This will open the specified url in a new window by injecting a small script in
    /// the current page that is run when the page is sent to the client's browser.
    /// This method accounts for the presence of update panels and script managers on the
    /// page that the control resides in.
    /// </summary>
    /// <param name="source">The control that the call is being made from</param>
    /// <param name="url">The URL to bring up in a new window</param>
    public static void RedirectToNewWindow(Control source, string url)
    {
        // create the script to register
        string scriptKey = "_NewWindow";
        string script = "window.open('" + url + "');";
        RegisterControlScript(source, scriptKey, script);
    }

    /// <summary>
    /// This will register a script for a specific control accounting for the control's UpdatePanel
    /// and whether or not there is a script manager on the page
    /// </summary>
    /// <param name="source">The control that will be affected by the script</param>
    /// <param name="scriptKey">A unique key for the script</param>
    /// <param name="script">The script that will affect the control</param>
    public static void RegisterControlScript(Control source, string scriptKey, string script)
    {
        // get the control's page
        Page currentPage = source.Page;

        // does the control reside in an UpdatePanel
        UpdatePanel updatePanel = GetFirstParentUpdatePanel(source);

        // did we find the UpdatePanel
        if (updatePanel == null)
        {
            // register the script on the page (works outside the control being in an update panel)
            currentPage.ClientScript.RegisterStartupScript(currentPage.GetType(), scriptKey,
                                                           script, true /*addScriptTags*/);
        }
        else
        {
            // register the script with the UpdatePanel and ScriptManger
            ScriptManager.RegisterClientScriptBlock(source, source.GetType(), scriptKey,
                                                    script, true /*addScriptTags*/);
        } // did we find the UpdatePanel
    }
}

然后,为了你的使用,你会打电话

protected void gv_inbox_RowCommand(object sender, GridViewCommandEventArgs e)
{
    int index = Convert.ToInt32(e.CommandArgument);

    if (e.CommandName == "sign")
    {
        Session["TransYear"] = int.Parse(((HiddenField)gv_inbox.Rows[index].Cells[1].FindControl("HDN_TransYear")).Value);
        Session["MailNumber"] = int.Parse(((HiddenField)gv_inbox.Rows[index].Cells[1].FindControl("HDN_MailNumber")).Value);
        Utilities.RedirectToNewWindow(gv_inbox, "Signature.aspx");
    }
}

不是最简洁的代码,因为我已经提取了这些帮助方法,但你明白了。上面的代码适用于 c#2.0 及更高版本,无论UpdatePanel嵌套如何,甚至根本不UpdatePanel使用 s 都可以工作

于 2013-02-18T17:49:56.833 回答
1

为什么我们使用回发来在 URL 的不同窗口中打开链接。

在创建控件链接时,我们可以将 signature.aspx 所需的值作为 Querystring 嵌入到链接控件上,这将只是一个简单的浏览器单击。

我希望这是简单而干净的。

于 2013-02-20T07:09:15.563 回答